Skip to content

Commit

Permalink
Add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
polac24 committed May 30, 2023
1 parent c26aaf7 commit f8757b6
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2021 Spotify AB.
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import Foundation

/// Products generator that doesn't create any swiftmodule. It is used in the compilation swift-frontend mocking, where
/// only individual .o files are created and not .swiftmodule of -Swift.h
/// (which is part of swift-frontend -emit-module invocation)
class NoopSwiftcProductsGenerator: SwiftcProductsGenerator {
func generateFrom(
artifactSwiftModuleFiles: [SwiftmoduleFileExtension: URL],
artifactSwiftModuleObjCFile: URL
) throws -> SwiftcProductsGeneratorOutput {
infoLog("""
Invoking module generation from NoopSwiftcProductsGenerator does nothing. \
It might be a side-effect of a plugin asking to generate a module.
""")
// NoopSwiftcProductsGenerator is intended only for the swift-frontend
let trivialURL = URL(fileURLWithPath: "/non-existing")
return SwiftcProductsGeneratorOutput(swiftmoduleDir: trivialURL, objcHeaderFile: trivialURL)
}
}
10 changes: 5 additions & 5 deletions Sources/XCRemoteCache/Commands/Swiftc/SwiftcContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import Foundation
public struct SwiftcContext {
/// Describes the action if the module emit should happen
/// that generates .swiftmodule and/or -Swift.h
public struct SwiftcStepEmitModule {
public struct SwiftcStepEmitModule: Equatable {
// where the -Swift.h should be placed
let objcHeaderOutput: URL
// where should the .swiftmodule be placed
Expand All @@ -34,31 +34,31 @@ public struct SwiftcContext {

/// Which files (from the list of all files in the module)
/// should be compiled in this process
public enum SwiftcStepCompileFilesScope {
public enum SwiftcStepCompileFilesScope: Equatable {
/// used if only emit module should be done
case none
case all
case subset([URL])
}

/// Describes which steps should be done as a part of this process
public struct SwiftcSteps {
public struct SwiftcSteps: Equatable {
/// which files should be compiled
let compileFilesScope: SwiftcStepCompileFilesScope
/// if a module should be generated
let emitModule: SwiftcStepEmitModule?
}

/// Defines how a list of input files (*.swift) is passed to the invocation
public enum CompilationFilesSource {
public enum CompilationFilesSource: Equatable {
/// defined in a separate file (via @/.../*.SwiftFileList)
case fileList(String)
/// explicitly passed a list of files
case list([String])
}

/// Defines how a list of output files (*.d, *.o etc.) is passed to the invocation
public enum CompilationFilesInputs {
public enum CompilationFilesInputs: Equatable {
/// defined in a separate file (via -output-file-map)
case fileMap(String)
/// defined in a separate file (via -supplementary-output-file-map)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import Yams
enum SwiftcInputReaderError: Error {
case readingFailed
case invalidFormat
/// The file is not in the yaml format
case invalidYamlFormat
/// The yaml string contains illegal characters
case invalidYamlString
case missingField(String)
}

Expand Down Expand Up @@ -98,7 +101,10 @@ class SwiftcFilemapInputEditor: SwiftcInputReader, SwiftcInputWriter {
case .json:
return try JSONSerialization.jsonObject(with: content, options: []) as? [String: Any]
case .yaml:
return try Yams.load(yaml: String(data: content, encoding: .utf8)!) as? [String: Any]
guard let stringContent = String(data: content, encoding: .utf8) else {
throw SwiftcInputReaderError.invalidYamlString
}
return try Yams.load(yaml: stringContent) as? [String: Any]
}
}
}
Expand Down
9 changes: 7 additions & 2 deletions Sources/XCRemoteCache/Commands/Swiftc/XCSwiftc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,18 @@ public class XCSwiftAbstract<InputArgs> {
fileManager: fileManager
)
case .supplementaryFileMap(let path):
// Supplementary file map is endoded in the yaml file (contraty to
// the standard filemap, which is in json)
inputReader = SwiftcFilemapInputEditor(
URL(fileURLWithPath: path),
fileFormat: .yaml,
fileManager: fileManager
)
case .map(let map):
// static - passed via the arguments list
// TODO: check if first 2 ars can always be `nil`
// with Xcode 14, inputs via cmd are only used for compilations
inputReader = StaticSwiftcInputReader(
moduleDependencies: context.steps.emitModule?.dependencies,
// with Xcode 14, inputs via cmd are only used for compilations
swiftDependencies: nil,
compilationFiles: Array(map.values)
)
Expand Down Expand Up @@ -134,6 +135,10 @@ public class XCSwiftAbstract<InputArgs> {
diskCopier: HardLinkDiskCopier(fileManager: fileManager)
)
} else {
// If the module was not requested for this proces (compiling files only)
// do nothing, when someone (e.g. a plugin) asks for the products generation
// This generation will happend in a separate process, where the module
// generation is requested
productsGenerator = NoopSwiftcProductsGenerator()
}
let allInvocationsStorage = ExistingFileStorage(
Expand Down
38 changes: 34 additions & 4 deletions Tests/XCRemoteCacheTests/Commands/SwiftcContextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,25 @@ class SwiftcContextTests: FileXCTestCase {
private var config: XCRemoteCacheConfig!
private var input: SwiftcArgInput!
private var remoteCommitFile: URL!
private var modulePathOutput: URL!
private var fileMapUrl: URL!
private var fileListUrl: URL!

override func setUpWithError() throws {
try super.setUpWithError()
let workingDir = try prepareTempDir()
remoteCommitFile = workingDir.appendingPathComponent("arc.rc")
let modulePathOutput = workingDir.appendingPathComponent("mpo")
modulePathOutput = workingDir.appendingPathComponent("mpo")
fileMapUrl = workingDir.appendingPathComponent("filemap")
fileListUrl = workingDir.appendingPathComponent("filelist")
config = XCRemoteCacheConfig(remoteCommitFile: remoteCommitFile.path, sourceRoot: workingDir.path)
input = SwiftcArgInput(
objcHeaderOutput: "Target-Swift.h",
moduleName: "Target",
moduleName: "Module",
modulePathOutput: modulePathOutput.path,
filemap: "",
filemap: fileMapUrl.path,
target: "",
fileList: ""
fileList: fileListUrl.path
)
try fileManager.write(toPath: remoteCommitFile.path, contents: "123".data(using: .utf8))
}
Expand Down Expand Up @@ -77,4 +82,29 @@ class SwiftcContextTests: FileXCTestCase {

XCTAssertEqual(context.mode, .producer)
}

func testStepsContainEmitingModuleAndAllCompilationScope() throws {
let context = try SwiftcContext(config: config, input: input)

XCTAssertEqual(context.steps, .init(
compileFilesScope: .all,
emitModule: .init(
objcHeaderOutput: "Target-Swift.h",
modulePathOutput: modulePathOutput,
dependencies: nil)
)
)
}

func testReadsInputsFromFileMap() throws {
let context = try SwiftcContext(config: config, input: input)

XCTAssertEqual(context.inputs, .fileMap(fileMapUrl.path))
}

func testReadsCompilationFilesFromFileList() throws {
let context = try SwiftcContext(config: config, input: input)

XCTAssertEqual(context.compilationFiles, .fileList(fileListUrl.path))
}
}
41 changes: 41 additions & 0 deletions Tests/XCRemoteCacheTests/Commands/SwiftcOrchestratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,45 @@ class SwiftcOrchestratorTests: XCTestCase {
XCTAssertEqual(artifactBuilder.addedObjCHeaders, [:])
}


func testNotSetObjCHeaderIsNotCreated() throws {
let swiftc = SwiftcMock(mockingResult: .success)
let orchestrator = SwiftcOrchestrator(
mode: .producer,
swiftc: swiftc,
swiftcCommand: "",
objcHeaderOutput: nil,
moduleOutput: moduleOutputURL,
arch: "arch",
artifactBuilder: artifactBuilder,
producerFallbackCommandProcessors: [],
invocationStorage: invocationStorage,
shellOut: shellOutSpy
)

try orchestrator.run()

XCTAssertEqual(artifactBuilder.addedObjCHeaders, [:])
}

func testNotSetModuleOutputIsNotCreated() throws {
let swiftc = SwiftcMock(mockingResult: .success)
let orchestrator = SwiftcOrchestrator(
mode: .producer,
swiftc: swiftc,
swiftcCommand: "",
objcHeaderOutput: objcHeaderURL,
moduleOutput: nil,
arch: "arch",
artifactBuilder: artifactBuilder,
producerFallbackCommandProcessors: [],
invocationStorage: invocationStorage,
shellOut: shellOutSpy
)

try orchestrator.run()

XCTAssertEqual(artifactBuilder.addedModuleDefinitions, [:])
}

}

0 comments on commit f8757b6

Please sign in to comment.