diff --git a/Package.swift b/Package.swift index 0ea3194287..6dd8486963 100644 --- a/Package.swift +++ b/Package.swift @@ -38,7 +38,7 @@ let package = Package( dependencies: [ .package( url: "https://github.com/stephencelis/SQLite.swift.git", - .upToNextMinor(from: "0.13.1")) + .upToNextMinor(from: "0.13.1")), .package( url: "https://github.com/mattt/InflectorKit", .upToNextMinor(from: "1.0.0")), @@ -81,7 +81,6 @@ let package = Package( ], resources: [ .copy("Frontend/dist/ApolloCodegenFrontend.bundle.js"), - .copy("Frontend/dist/ApolloCodegenFrontend.bundle.js.map") ]), .target( name: "ApolloSQLite", diff --git a/Sources/Apollo/GraphQLSelectionSetMapper.swift b/Sources/Apollo/GraphQLSelectionSetMapper.swift index fb2712dcc7..2287578815 100644 --- a/Sources/Apollo/GraphQLSelectionSetMapper.swift +++ b/Sources/Apollo/GraphQLSelectionSetMapper.swift @@ -41,6 +41,6 @@ final class GraphQLSelectionSetMapper: GraphQLRes } func finish(rootValue: JSONObject) -> SelectionSet { - return SelectionSet.init(data: ResponseDict(rootValue)) + return SelectionSet.init(data: DataDict(rootValue)) } } diff --git a/Sources/ApolloAPI/ResponseDict.swift b/Sources/ApolloAPI/DataDict.swift similarity index 84% rename from Sources/ApolloAPI/ResponseDict.swift rename to Sources/ApolloAPI/DataDict.swift index 4e6cde131b..73fcb9bfea 100644 --- a/Sources/ApolloAPI/ResponseDict.swift +++ b/Sources/ApolloAPI/DataDict.swift @@ -1,5 +1,5 @@ /// A structure that wraps the underlying data dictionary used by `SelectionSet`s. -public struct ResponseDict { +public struct DataDict { let data: JSONObject @@ -41,21 +41,21 @@ public struct ResponseDict { public subscript(_ key: String) -> T { let objectData = data[key] as! JSONObject - return T.init(data: ResponseDict(objectData)) + return T.init(data: DataDict(objectData)) } public subscript(_ key: String) -> T? { guard let objectData = data[key] as? JSONObject else { return nil } - return T.init(data: ResponseDict(objectData)) + return T.init(data: DataDict(objectData)) } public subscript(_ key: String) -> [T] { let objectData = data[key] as! [JSONObject] - return objectData.map { T.init(data: ResponseDict($0)) } + return objectData.map { T.init(data: DataDict($0)) } } public subscript(_ key: String) -> [T]? { guard let objectData = data[key] as? [JSONObject] else { return nil } - return objectData.map { T.init(data: ResponseDict($0)) } + return objectData.map { T.init(data: DataDict($0)) } } } diff --git a/Sources/ApolloAPI/FragmentProtocols.swift b/Sources/ApolloAPI/FragmentProtocols.swift index 592cf8493c..f7c40c14b7 100644 --- a/Sources/ApolloAPI/FragmentProtocols.swift +++ b/Sources/ApolloAPI/FragmentProtocols.swift @@ -1,26 +1,33 @@ // MARK: - Fragment -/// A protocol representing a fragment that a `ResponseObject` object may be converted to. +/// A protocol representing a fragment that a `SelectionSet` object may be converted to. /// -/// A `ResponseObject` that conforms to `HasFragments` can be converted to -/// any `Fragment` included in it's `Fragments` object via its `fragments` property. -/// -/// - SeeAlso: `HasFragments`, `ToFragments` +/// A `SelectionSet` can be converted to any `Fragment` included in it's `Fragments` object via +/// its `fragments` property. public protocol Fragment: AnySelectionSet { static var fragmentDefinition: String { get } } -// MARK: - HasFragments - -/// A protocol that a `ResponseObject` that contains fragments should conform to. -public protocol HasFragments: AnySelectionSet { +public protocol FragmentContainer { + var data: DataDict { get } - /// A type representing all of the fragments contained on the `ResponseObject`. - associatedtype Fragments: ResponseObject + init(data: DataDict) } -public extension HasFragments { - /// A `FieldData` object that contains accessors for all of the fragments - /// the object can be converted to. - var fragments: Fragments { Fragments(data: data) } +public extension FragmentContainer { + + /// Converts a `SelectionSet` to a `Fragment` given a generic fragment type. + /// + /// - Warning: This function is not supported for use outside of generated call sites. + /// Generated call sites are guaranteed by the GraphQL compiler to be safe. + /// Unsupported usage may result in unintended consequences including crashes. + #warning("TODO: Audit all _ prefixed things to see if they should be available using ApolloExtension.") + func _toFragment() -> T { + return T.init(data: data) + } } + +/// A `FragmentContainer` to be used by `SelectionSet`s that have no fragments. +/// This is the default `FragmentContainer` for a `SelectionSet` that does not specify a +/// `Fragments` type. +public enum NoFragments {} diff --git a/Sources/ApolloAPI/ResponseObject.swift b/Sources/ApolloAPI/ResponseObject.swift deleted file mode 100644 index 69dabc2f55..0000000000 --- a/Sources/ApolloAPI/ResponseObject.swift +++ /dev/null @@ -1,26 +0,0 @@ -public protocol ResponseObject { - var data: ResponseDict { get } - - init(data: ResponseDict) -} - -extension ResponseObject { - - public init(json: JSONObject) { - self.init(data: ResponseDict(json)) - } - - #warning("TODO: Audit all _ prefixed things to see if they should be available using ApolloExtension.") - public func _toJSONObject() -> JSONObject { - data.data - } - - /// Converts a `SelectionSet` to a `Fragment` given a generic fragment type. - /// - /// - Warning: This function is not supported for use outside of generated call sites. - /// Generated call sites are guaranteed by the GraphQL compiler to be safe. - /// Unsupported usage may result in unintended consequences including crashes. - func _toFragment() -> T { - return T.init(data: data) - } -} diff --git a/Sources/ApolloAPI/SelectionSet.swift b/Sources/ApolloAPI/SelectionSet.swift index e0cedf2a2b..f306b88215 100644 --- a/Sources/ApolloAPI/SelectionSet.swift +++ b/Sources/ApolloAPI/SelectionSet.swift @@ -1,6 +1,6 @@ // MARK: - Type Erased SelectionSets -public protocol AnySelectionSet: ResponseObject { +public protocol AnySelectionSet { static var schema: SchemaConfiguration.Type { get } static var selections: [Selection] { get } @@ -9,6 +9,10 @@ public protocol AnySelectionSet: ResponseObject { /// /// This may be a concrete type (`Object`) or an abstract type (`Interface`, or `Union`). static var __parentType: ParentType { get } + + var data: DataDict { get } + + init(data: DataDict) } public extension AnySelectionSet { @@ -48,6 +52,11 @@ public protocol TypeCase: AnySelectionSet { } // MARK: - SelectionSet public protocol SelectionSet: AnySelectionSet { associatedtype Schema: SchemaConfiguration + + /// A type representing all of the fragments the `SelectionSet` can be converted to. + /// Defaults to a stub type with no fragments. + /// A `SelectionSet` with fragments should provide a type that conforms to `FragmentContainer` + associatedtype Fragments = NoFragments } extension SelectionSet { @@ -71,3 +80,8 @@ extension SelectionSet { return T.init(data: data) } } + +extension SelectionSet where Fragments: FragmentContainer { + /// Contains accessors for all of the fragments the `SelectionSet` can be converted to. + var fragments: Fragments { Fragments(data: data) } +} diff --git a/Sources/ApolloCodegenLib/CLIDownloader.swift b/Sources/ApolloCodegenLib/CLIDownloader.swift deleted file mode 100644 index e68d8d5f9c..0000000000 --- a/Sources/ApolloCodegenLib/CLIDownloader.swift +++ /dev/null @@ -1,60 +0,0 @@ -import Foundation - -// Only available on macOS -#if os(macOS) - -/// Helper for downloading the CLI Zip file so we don't have to include it in the repo. -struct CLIDownloader { - /// The URL string for getting the current version of the CLI - static let downloadURLString = "https://install.apollographql.com/legacy-cli/darwin/2.33.9" - - /// Downloads the appropriate Apollo CLI in a zip file. - /// - /// - Parameters: - /// - cliFolderURL: The folder URL to download the zip file to. - /// - timeout: The maximum time to wait before indicating that the download timed out, in seconds. - static func downloadIfNeeded(to cliFolderURL: URL, timeout: Double) throws { - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: cliFolderURL) - - guard !FileManager.default.apollo.doesFileExist(atPath: zipFileURL.path) else { - CodegenLogger.log("Zip file with the CLI is already downloaded!") - return - } - - try self.download(to: zipFileURL, timeout: timeout) - } - - /// Deletes any existing version of the zip file and re-downloads a new version. - /// - /// - Parameters: - /// - cliFolderURL: The folder where the zip file lives. - /// - timeout: The maximum time to wait before indicating that the download timed out, in seconds. - static func forceRedownload(to cliFolderURL: URL, timeout: Double) throws { - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: cliFolderURL) - try FileManager.default.apollo.deleteFile(atPath: zipFileURL.path) - let apolloFolderURL = ApolloFilePathHelper.apolloFolderURL(fromCLIFolder: cliFolderURL) - try FileManager.default.apollo.deleteDirectory(atPath: apolloFolderURL.path) - - try self.download(to: zipFileURL, timeout: timeout) - } - - /// Downloads the zip file of the Apollo CLI synchronously. - /// - /// - Parameters: - /// - zipFileURL: The URL where downloaded data should be saved. - /// - timeout: The maximum time to wait before indicating that the download timed out, in seconds. - private static func download(to zipFileURL: URL, timeout: Double) throws { - try FileManager.default.apollo.createContainingDirectoryIfNeeded(forPath: zipFileURL.path) - - CodegenLogger.log("Downloading zip file with the CLI...") - - let urlRequest = URLRequest(url: URL(string: CLIDownloader.downloadURLString)!) - try URLDownloader().downloadSynchronously(with: urlRequest, - to: zipFileURL, - timeout: timeout) - - CodegenLogger.log("CLI zip file successfully downloaded!") - } -} - -#endif diff --git a/Sources/ApolloCodegenLib/CLIExtractor.swift b/Sources/ApolloCodegenLib/CLIExtractor.swift deleted file mode 100644 index 4e9aaa324a..0000000000 --- a/Sources/ApolloCodegenLib/CLIExtractor.swift +++ /dev/null @@ -1,145 +0,0 @@ -import Foundation - -// Only available on macOS -#if os(macOS) - -/// Helper for extracting and validating the node-based Apollo CLI from a zip. -struct CLIExtractor { - - // MARK: - Extracting the binary - - enum CLIExtractorError: Error, LocalizedError { - case noBinaryFolderAfterUnzipping(atURL: URL) - case zipFileHasInvalidSHASUM(expectedSHASUM: String, gotSHASUM: String) - case zipFileNotPresent(atURL: URL) - - var errorDescription: String? { - switch self { - case .noBinaryFolderAfterUnzipping(let url): - return "Some kind of error occurred with unzipping and the binary folder could not be found at \(url)" - case .zipFileHasInvalidSHASUM(let expectedSHASUM, let gotSHASUM): - return "Error: The SHASUM of this zip file (\(gotSHASUM)) does not match the official released version from Apollo (\(expectedSHASUM))! This may present security issues. Terminating code generation." - case .zipFileNotPresent(let url): - return "Could not locate file to unzip at \(url). Please make sure you're passing in the correct URL for the scripts folder!" - } - } - } - - static let expectedSHASUM = "cb73089deb2a720a7d2f5a39ad449e1cfbdc22771130cd6e2a405aaa887c343e" - - /// Checks to see if the CLI has already been extracted and is the correct version, and extracts or re-extracts as necessary - /// - /// - Parameter cliFolderURL: The URL to the folder which contains the zip file with the CLI. - /// - Parameter expectedSHASUM: The expected SHASUM. Defaults to the real expected SHASUM. This parameter exists mostly for testing. - /// - Returns: The URL to the binary folder of the extracted CLI. - static func extractCLIIfNeeded(from cliFolderURL: URL, expectedSHASUM: String = CLIExtractor.expectedSHASUM) throws -> URL { - let apolloFolderURL = ApolloFilePathHelper.apolloFolderURL(fromCLIFolder: cliFolderURL) - - guard FileManager.default.apollo.doesDirectoryExist(atPath: apolloFolderURL.path) else { - CodegenLogger.log("Apollo folder doesn't exist, extracting CLI from zip file.") - return try self.extractCLIFromZip(cliFolderURL: cliFolderURL) - } - - guard try self.validateSHASUMInExtractedFile(apolloFolderURL: apolloFolderURL, expected: expectedSHASUM) else { - CodegenLogger.log("SHASUM of extracted zip does not match expected, deleting existing folder and re-extracting.") - try FileManager.default.apollo.deleteDirectory(atPath: apolloFolderURL.path) - return try self.extractCLIFromZip(cliFolderURL: cliFolderURL) - } - - let binaryFolderURL = ApolloFilePathHelper.binaryFolderURL(fromApollo: apolloFolderURL) - let binaryURL = ApolloFilePathHelper.binaryURL(fromBinaryFolder: binaryFolderURL) - guard FileManager.default.apollo.doesFileExist(atPath: binaryURL.path) else { - CodegenLogger.log("There was a valid `.shasum` file, but no binary at the expected path. Deleting existing apollo folder and re-extracting.", logLevel: .warning) - try FileManager.default.apollo.deleteDirectory(atPath: apolloFolderURL.path) - return try self.extractCLIFromZip(cliFolderURL: cliFolderURL, expectedSHASUM: expectedSHASUM) - } - - CodegenLogger.log("Binary already extracted!") - return binaryFolderURL - } - - /// Checks the `.shasum` file which was written out the last time the CLI - /// was extracted to see if it matches the current version - /// - Parameter apolloFolderURL: The URL to the extracted apollo folder. - /// - Parameter expected: The expected SHASUM. Defaults to the real expected SHASUM. This parameter exists mostly for testing. - /// - Returns: true if the shasums match, false if not. - static func validateSHASUMInExtractedFile(apolloFolderURL: URL, expected: String = CLIExtractor.expectedSHASUM) throws -> Bool { - let shasumFileURL = ApolloFilePathHelper.shasumFileURL(fromApollo: apolloFolderURL) - guard FileManager.default.apollo.doesFileExist(atPath: shasumFileURL.path) else { - return false - } - - let contents = try String(contentsOf: shasumFileURL, encoding: .utf8) - - guard contents == expected else { - return contents.hasPrefix(expected) - } - - return true - } - - static func validateSHASUMOfDownloadedFile(in cliFolderURL: URL, expected: String = CLIExtractor.expectedSHASUM) throws -> Bool { - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: cliFolderURL) - - do { - try self.validateZipFileSHASUM(at: zipFileURL) - return true - } catch { - switch error { - case CLIExtractorError.zipFileHasInvalidSHASUM: - return false - default: - throw error - } - } - } - - /// Writes the SHASUM of the extracted version of the CLI to a file for faster checks to ensure we have the correct version. - /// - /// - Parameter apolloFolderURL: The URL to the extracted apollo folder. - static func writeSHASUMToFile(apolloFolderURL: URL) throws { - let shasumFileURL = ApolloFilePathHelper.shasumFileURL(fromApollo: apolloFolderURL) - try CLIExtractor.expectedSHASUM.write(to: shasumFileURL, - atomically: true, - encoding: .utf8) - } - - /// Extracts the CLI from a zip file in the scripts folder. - /// - /// - Parameter cliFolderURL: The URL to the folder which contains the zip file with the CLI. - /// - Parameter expectedSHASUM: The expected SHASUM. Defaults to the real expected SHASUM. This parameter exists mostly for testing. - /// - Returns: The URL for the binary folder post-extraction. - static func extractCLIFromZip(cliFolderURL: URL, expectedSHASUM: String = CLIExtractor.expectedSHASUM) throws -> URL { - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: cliFolderURL) - - try self.validateZipFileSHASUM(at: zipFileURL, expected: expectedSHASUM) - - CodegenLogger.log("Extracting CLI from zip file. This may take a second...") - _ = try Basher.run(command: "tar xzf '\(zipFileURL.path)' -C '\(cliFolderURL.path)'", from: nil) - - let apolloFolderURL = ApolloFilePathHelper.apolloFolderURL(fromCLIFolder: cliFolderURL) - let binaryFolderURL = ApolloFilePathHelper.binaryFolderURL(fromApollo: apolloFolderURL) - - guard FileManager.default.apollo.doesDirectoryExist(atPath: binaryFolderURL.path) else { - throw CLIExtractorError.noBinaryFolderAfterUnzipping(atURL: binaryFolderURL) - } - - try self.writeSHASUMToFile(apolloFolderURL: apolloFolderURL) - - return binaryFolderURL - } - - /// Checks that the file at the given URL matches the expected SHASUM. - /// - /// - Parameter zipFileURL: The url to the zip file containing the Apollo CLI. - /// - Parameter expected: The expected SHASUM. Defaults to the real expected SHASUM. This parameter exists mostly for testing. - static func validateZipFileSHASUM(at zipFileURL: URL, expected: String = CLIExtractor.expectedSHASUM) throws { - let shasum = try FileManager.default.apollo.shasum(at: zipFileURL) - print("SHASUM of downloaded file: \(shasum)") - guard shasum == expected else { - throw CLIExtractorError.zipFileHasInvalidSHASUM(expectedSHASUM: expected, gotSHASUM: shasum) - } - } -} - -#endif diff --git a/Tests/ApolloCodegenTests/CLIDownloaderTests.swift b/Tests/ApolloCodegenTests/CLIDownloaderTests.swift deleted file mode 100644 index 257933147b..0000000000 --- a/Tests/ApolloCodegenTests/CLIDownloaderTests.swift +++ /dev/null @@ -1,45 +0,0 @@ -@testable import ApolloCodegenLib -import ApolloCodegenTestSupport -import XCTest - -class CLIDownloaderTests: XCTestCase { - func testForceRedownloading_withExistingFile_shouldOverwriteWithExpectedChecksum() throws { - let scriptsURL = CodegenTestHelper.cliFolderURL() - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: scriptsURL) - - try "Dummy file".data(using: .utf8)?.write(to: zipFileURL) - XCTAssertTrue(FileManager.default.apollo.doesFileExist(atPath: zipFileURL.path), "Created dummy file to be overwritten") - - try CLIDownloader.forceRedownload(to: scriptsURL, timeout: CodegenTestHelper.timeout) - XCTAssertTrue(FileManager.default.apollo.doesFileExist(atPath: zipFileURL.path), "Downloaded Apollo CLI") - XCTAssertEqual(try FileManager.default.apollo.shasum(at: zipFileURL), CLIExtractor.expectedSHASUM) - } - - func testDownloading_toFolderThatDoesNotExist_shouldCreateFolder() throws { - let scriptsURL = CodegenTestHelper.cliFolderURL() - try FileManager.default.apollo.deleteDirectory(atPath: scriptsURL.path) - XCTAssertFalse(FileManager.default.apollo.doesDirectoryExist(atPath: scriptsURL.path)) - - try CLIDownloader.downloadIfNeeded(to: scriptsURL, timeout: 90.0) - XCTAssertTrue(FileManager.default.apollo.doesDirectoryExist(atPath: scriptsURL.path)) - } - - func testTimeout_shouldThrowCorrectError() throws { - let scriptsURL = CodegenTestHelper.cliFolderURL() - - do { - try CLIDownloader.forceRedownload(to: scriptsURL, timeout: 0.5) - } catch { - guard - let DownloadError = error as? URLDownloader.DownloadError, - case .downloadTimedOut(let seconds) = DownloadError - else { - XCTFail("Wrong type of error") - return - } - - XCTAssertEqual(seconds, 0.5, accuracy: 0.0001) - } - } -} - diff --git a/Tests/ApolloCodegenTests/CLIExtractorTests.swift b/Tests/ApolloCodegenTests/CLIExtractorTests.swift deleted file mode 100644 index 1d1910369d..0000000000 --- a/Tests/ApolloCodegenTests/CLIExtractorTests.swift +++ /dev/null @@ -1,192 +0,0 @@ -// -// CLIExtractorTests.swift -// ApolloCodegenTests -// -// Created by Ellen Shapiro on 10/7/19. -// Copyright © 2019 Apollo GraphQL. All rights reserved. -// - -import XCTest -import ApolloCodegenTestSupport -@testable import ApolloCodegenLib - -class CLIExtractorTests: XCTestCase { - - override func setUp() { - super.setUp() - CodegenTestHelper.downloadCLIIfNeeded() - CodegenTestHelper.deleteExistingApolloFolder() - } - - private func checkSHASUMFileContentsDirectly(at url: URL, - match expected: String, - file: StaticString = #filePath, - line: UInt = #line) { - guard let contents = try? String(contentsOf: url, encoding: .utf8) else { - XCTFail("Could not load file at \(url.path)", - file: file, - line: line) - return - } - - XCTAssertEqual(contents, - expected, - "Direct check of SHASUM failed. Got \(contents), expected \(expected)", - file: #file, - line: #line) - } - - private func validateSHASUMFile(shouldBeValid: Bool, - apolloFolderURL: URL, - match expected: String, - file: StaticString = #filePath, - line: UInt = #line) { - do { - let isValid = try CLIExtractor.validateSHASUMInExtractedFile(apolloFolderURL: apolloFolderURL, expected: expected) - XCTAssertEqual(isValid, - shouldBeValid, - file: file, - line: line) - } catch { - XCTFail("Error validating shasum in extracted file: \(error)", - file: file, - line: line) - } - } - - func validateCLIIsExtractedWithRealSHASUM(file: StaticString = #filePath, - line: UInt = #line) { - let binaryFolderURL = CodegenTestHelper.binaryFolderURL() - XCTAssertTrue(FileManager.default.apollo.doesDirectoryExist(atPath: binaryFolderURL.path), - "Binary folder doesn't exist at \(binaryFolderURL)", - file: file, - line: line) - let binaryURL = ApolloFilePathHelper.binaryURL(fromBinaryFolder: binaryFolderURL) - XCTAssertTrue(FileManager.default.apollo.doesFileExist(atPath: binaryURL.path), - "Binary doesn't exist at \(binaryURL)", - file: file, - line: line) - let shasumFileURL = CodegenTestHelper.shasumFileURL() - self.checkSHASUMFileContentsDirectly(at: shasumFileURL, - match: CLIExtractor.expectedSHASUM, - file: file, - line: line) - } - - func testValidatingSHASUMWithMatchingWorks() throws { - let cliFolderURL = CodegenTestHelper.cliFolderURL() - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: cliFolderURL) - try CLIExtractor.validateZipFileSHASUM(at: zipFileURL, expected: CLIExtractor.expectedSHASUM) - } - - func testValidatingSHASUMFailsWithoutMatch() throws { - let cliFolderURL = CodegenTestHelper.cliFolderURL() - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: cliFolderURL) - let bogusSHASUM = CLIExtractor.expectedSHASUM + "NOPE" - do { - try CLIExtractor.validateZipFileSHASUM(at: zipFileURL, expected: bogusSHASUM) - XCTFail("This should not have validated!") - } catch { - switch error { - case CLIExtractor.CLIExtractorError.zipFileHasInvalidSHASUM(let expectedSHASUM, let gotSHASUM): - XCTAssertEqual(expectedSHASUM, bogusSHASUM) - XCTAssertEqual(gotSHASUM, CLIExtractor.expectedSHASUM) - default: - XCTFail("Unexpected error: \(error)") - } - } - } - - func testExtractingZip() throws { - // Check that the binary hasn't already been extracted - // (it should be getting deleted in `setUp`) - let binaryFolderURL = CodegenTestHelper.binaryFolderURL() - XCTAssertFalse(FileManager.default.apollo.doesDirectoryExist(atPath: binaryFolderURL.path)) - - // Actually extract the CLI - let cliFolderURL = CodegenTestHelper.cliFolderURL() - let extractedURL = try CLIExtractor.extractCLIIfNeeded(from: cliFolderURL) - - // Make sure we're getting the binary folder path back and that something's now there. - XCTAssertEqual(extractedURL.path, binaryFolderURL.path) - self.validateCLIIsExtractedWithRealSHASUM() - - // Make sure the validator is working - let apolloFolderURL = CodegenTestHelper.apolloFolderURL() - self.validateSHASUMFile(shouldBeValid: true, - apolloFolderURL: apolloFolderURL, - match: CLIExtractor.expectedSHASUM) - self.validateSHASUMFile(shouldBeValid: false, - apolloFolderURL: apolloFolderURL, - match: "NOPE") - } - - func testReExtractingZipWithDifferentSHA() throws { - // Extract the existing CLI - let cliFolderURL = CodegenTestHelper.cliFolderURL() - _ = try CLIExtractor.extractCLIIfNeeded(from: cliFolderURL) - - // Validate that it extracted and has the correct shasum - self.validateCLIIsExtractedWithRealSHASUM() - - // Replace the SHASUM file URL with a fake that doesn't match - let shasumFileURL = CodegenTestHelper.shasumFileURL() - let fakeSHASUM = "Old Shasum" - try fakeSHASUM.write(to: shasumFileURL, atomically: true, encoding: .utf8) - - // Validation should now fail since the SHASUMs don't match - let apolloFolderURL = CodegenTestHelper.apolloFolderURL() - XCTAssertFalse(try CLIExtractor.validateSHASUMInExtractedFile(apolloFolderURL: apolloFolderURL)) - - // Now try extracting again, and check SHASUM is now real again - _ = try CLIExtractor.extractCLIIfNeeded(from: cliFolderURL) - self.validateCLIIsExtractedWithRealSHASUM() - } - - func testFolderExistsButMissingSHASUMFileReExtractionWorks() throws { - // Make sure there is an apollo folder but no `.shasum` file - let apolloFolder = CodegenTestHelper.apolloFolderURL() - try FileManager.default.apollo.createDirectoryIfNeeded(atPath: apolloFolder.path) - - let cliFolderURL = CodegenTestHelper.cliFolderURL() - - // Now try extracting again, and check SHASUM is now real again - _ = try CLIExtractor.extractCLIIfNeeded(from: cliFolderURL) - self.validateCLIIsExtractedWithRealSHASUM() - } - - func testCorrectSHASUMButMissingBinaryReExtractionWorks() throws { - // Write just the SHASUM file, but nothing else - try CodegenTestHelper.writeSHASUMOnly(CLIExtractor.expectedSHASUM) - - // Make sure the binary folder's not there - let binaryFolderURL = CodegenTestHelper.binaryFolderURL() - XCTAssertFalse(FileManager.default.apollo.doesDirectoryExist(atPath: binaryFolderURL.path)) - - // Re-extract and now everything should be there - let cliFolderURL = CodegenTestHelper.cliFolderURL() - _ = try CLIExtractor.extractCLIIfNeeded(from: cliFolderURL) - self.validateCLIIsExtractedWithRealSHASUM() - } - - func testMissingSHASUMFileButCorrectZipFileCreatesSHASUMFile() throws { - let shasumFileURL = CodegenTestHelper.shasumFileURL() - try FileManager.default.apollo.deleteFile(atPath: shasumFileURL.path) - - XCTAssertFalse(FileManager.default.apollo.doesFileExist(atPath: shasumFileURL.path)) - - let cliFolderURL = CodegenTestHelper.cliFolderURL() - let zipFileURL = ApolloFilePathHelper.zipFileURL(fromCLIFolder: cliFolderURL) - - XCTAssertTrue(FileManager.default.apollo.doesFileExist(atPath: zipFileURL.path)) - - let binaryURL = try CLIExtractor.extractCLIIfNeeded(from: cliFolderURL) - - /// Was the binary extracted? - XCTAssertTrue(FileManager.default.apollo.doesDirectoryExist(atPath: binaryURL.path)) - - /// Did the SHASUM file get created? - XCTAssertTrue(FileManager.default.apollo.doesFileExist(atPath: shasumFileURL.path)) - self.validateCLIIsExtractedWithRealSHASUM() - } -}