Skip to content

[Incremental] Reorder IncrementalCompilationTests and extract OutputFileMapCreator #519

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions Tests/SwiftDriverTests/Helpers/OutputFileMapCreator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//===--------------- OutputFileMapCreator.swift - Swift Testing -----------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import XCTest
import TSCBasic

import Foundation

struct OutputFileMapCreator {
private let module: String
private let inputPaths: [AbsolutePath]
private let derivedData: AbsolutePath

private init(module: String, inputPaths: [AbsolutePath], derivedData: AbsolutePath) {
self.module = module
self.inputPaths = inputPaths
self.derivedData = derivedData
}

static func write(module: String,
Copy link
Contributor

@CodaFi CodaFi Mar 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to be a convenience method we ought to hide the member wise initializer

inputPaths: [AbsolutePath],
derivedData: AbsolutePath,
to dst: AbsolutePath) {
let creator = Self(module: module, inputPaths: inputPaths, derivedData: derivedData)
try! localFileSystem.writeFileContents(dst, bytes: ByteString(creator.generateData()))
}

private func generateDict() -> [String: [String: String]] {
let master = ["swift-dependencies": "\(derivedData.pathString)/\(module)-master.swiftdeps"]
func baseNameEntry(_ s: AbsolutePath) -> [String: String] {
[
"dependencies": ".d",
"diagnostics": ".dia",
"llvm-bc": ".bc",
"object": ".o",
"swift-dependencies": ".swiftdeps",
"swiftmodule": "-partial.swiftmodule"
]
.mapValues {"\(derivedData.appending(component: s.basenameWithoutExt))\($0)"}
}
return Dictionary(uniqueKeysWithValues:
inputPaths.map { ("\($0)", baseNameEntry($0)) }
)
.merging(["": master]) {_, _ in fatalError()}
}

private func generateData() -> Data {
let d: [String: [String: String]] = generateDict()
let enc = JSONEncoder()
return try! enc.encode(d)
}
}

171 changes: 71 additions & 100 deletions Tests/SwiftDriverTests/IncrementalCompilationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import TSCBasic
@_spi(Testing) import SwiftDriver
import SwiftOptions

// MARK: - Baseline: nonincremental
final class NonincrementalCompilationTests: XCTestCase {
func testBuildRecordReading() throws {
let buildRecord = try XCTUnwrap(
Expand Down Expand Up @@ -322,10 +323,11 @@ final class NonincrementalCompilationTests: XCTestCase {
}
}


// MARK: - IncrementalCompilation
final class IncrementalCompilationTests: XCTestCase {

var tempDir: AbsolutePath = AbsolutePath("/tmp")

var derivedDataDir: AbsolutePath {
tempDir.appending(component: "derivedData")
}
Expand Down Expand Up @@ -360,7 +362,7 @@ final class IncrementalCompilationTests: XCTestCase {
"Finished Extracting autolink information for module \(module)",
]
}
var args: [String] {
var commonArgs: [String] {
[
"swiftc",
"-module-name", module,
Expand All @@ -375,17 +377,14 @@ final class IncrementalCompilationTests: XCTestCase {
]
+ inputPathsAndContents.map {$0.0.pathString} .sorted()
}
deinit {
try? localFileSystem.removeFileTree(tempDir)
}

override func setUp() {
self.tempDir = try! withTemporaryDirectory(removeTreeOnDeinit: false) {$0}
try! localFileSystem.createDirectory(derivedDataPath)
writeOutputFileMapData(module: module,
inputPaths: inputPathsAndContents.map {$0.0},
derivedData: derivedDataPath,
to: OFM)
OutputFileMapCreator.write(module: module,
inputPaths: inputPathsAndContents.map {$0.0},
derivedData: derivedDataPath,
to: OFM)
for (base, contents) in baseNamesAndContents {
let filePath = tempDir.appending(component: "\(base).swift")
try! localFileSystem.writeFileContents(filePath) {
Expand All @@ -394,6 +393,63 @@ final class IncrementalCompilationTests: XCTestCase {
}
}

deinit {
try? localFileSystem.removeFileTree(tempDir)
}
}

extension IncrementalCompilationTests {
func doABuild(_ message: String,
checkDiagnostics: Bool,
extraArguments: [String],
expectingRemarks texts: [String],
whenAutolinking: [String]) throws {
try doABuild(
message,
checkDiagnostics: checkDiagnostics,
extraArguments: extraArguments,
expecting: texts.map {.remark($0)},
expectingWhenAutolinking: whenAutolinking.map {.remark($0)})
}

func doABuild(_ message: String,
checkDiagnostics: Bool,
extraArguments: [String],
expecting expectations: [Diagnostic.Message],
expectingWhenAutolinking autolinkExpectations: [Diagnostic.Message]) throws {
print("*** starting build \(message) ***", to: &stderrStream); stderrStream.flush()

func doIt(_ driver: inout Driver) {
let jobs = try! driver.planBuild()
try? driver.run(jobs: jobs)
}

let allArgs = try commonArgs + extraArguments + Driver.sdkArgumentsForTesting()
if checkDiagnostics {
try assertDriverDiagnostics(args: allArgs) {driver, verifier in
verifier.forbidUnexpected(.error, .warning, .note, .remark, .ignored)
expectations.forEach {verifier.expect($0)}
if driver.isAutolinkExtractJobNeeded {
autolinkExpectations.forEach {verifier.expect($0)}
}
doIt(&driver)
}
}
else {
let diagnosticEngine = DiagnosticsEngine(handlers: [
{print($0, to: &stderrStream); stderrStream.flush()}
])
var driver = try Driver(args: allArgs, env: ProcessEnv.vars,
diagnosticsEngine: diagnosticEngine,
fileSystem: localFileSystem)
doIt(&driver)
}
print("", to: &stderrStream); stderrStream.flush()
}
}

extension IncrementalCompilationTests {

func testOptionsParsing() throws {
let optionPairs: [(
Option, (IncrementalCompilationState.InitialStateComputer) -> Bool
Expand All @@ -413,7 +469,7 @@ final class IncrementalCompilationTests: XCTestCase {
expectingRemarks: [],
whenAutolinking: [])

var driver = try Driver(args: self.args + [
var driver = try Driver(args: self.commonArgs + [
driverOption.spelling,
] + Driver.sdkArgumentsForTesting())
_ = try driver.planBuild()
Expand All @@ -422,6 +478,9 @@ final class IncrementalCompilationTests: XCTestCase {
XCTAssertTrue(stateOptionFn(state.moduleDependencyGraph.info))
}
}
}

extension IncrementalCompilationTests {

// FIXME: why does it fail on Linux in CI?
func testIncrementalDiagnostics() throws {
Expand Down Expand Up @@ -716,53 +775,6 @@ final class IncrementalCompilationTests: XCTestCase {
XCTAssert(previousContents != newContents, "\(path.pathString) unchanged after write")
XCTAssert(replacement == newContents, "\(path.pathString) failed to write")
}
func doABuild(_ message: String,
checkDiagnostics: Bool,
extraArguments: [String],
expectingRemarks texts: [String],
whenAutolinking: [String]) throws {
try doABuild(
message,
checkDiagnostics: checkDiagnostics,
extraArguments: extraArguments,
expecting: texts.map {.remark($0)},
expectingWhenAutolinking: whenAutolinking.map {.remark($0)})
}

func doABuild(_ message: String,
checkDiagnostics: Bool,
extraArguments: [String],
expecting expectations: [Diagnostic.Message],
expectingWhenAutolinking autolinkExpectations: [Diagnostic.Message]) throws {
print("*** starting build \(message) ***", to: &stderrStream); stderrStream.flush()

func doIt(_ driver: inout Driver) {
let jobs = try! driver.planBuild()
try? driver.run(jobs: jobs)
}

let allArgs = try args + extraArguments + Driver.sdkArgumentsForTesting()
if checkDiagnostics {
try assertDriverDiagnostics(args: allArgs) {driver, verifier in
verifier.forbidUnexpected(.error, .warning, .note, .remark, .ignored)
expectations.forEach {verifier.expect($0)}
if driver.isAutolinkExtractJobNeeded {
autolinkExpectations.forEach {verifier.expect($0)}
}
doIt(&driver)
}
}
else {
let diagnosticEngine = DiagnosticsEngine(handlers: [
{print($0, to: &stderrStream); stderrStream.flush()}
])
var driver = try Driver(args: allArgs, env: ProcessEnv.vars,
diagnosticsEngine: diagnosticEngine,
fileSystem: localFileSystem)
doIt(&driver)
}
print("", to: &stderrStream); stderrStream.flush()
}

/// Ensure that autolink output file goes with .o directory, to not prevent incremental omission of
/// autolink job.
Expand All @@ -774,7 +786,7 @@ final class IncrementalCompilationTests: XCTestCase {
env["SWIFT_DRIVER_DSYMUTIL_EXEC"] = "/garbage/dsymutil"

var driver = try! Driver(
args: args
args: commonArgs
+ ["-emit-library", "-target", "x86_64-unknown-linux"],
env: env)
let plannedJobs = try! driver.planBuild()
Expand All @@ -788,48 +800,6 @@ final class IncrementalCompilationTests: XCTestCase {
let expected = AbsolutePath(derivedDataPath, "\(module).autolink")
XCTAssertEqual(autoOut.file.absolutePath, expected)
}

private func generateOutputFileMapDict(module: String, inputPaths: [AbsolutePath],
derivedData: AbsolutePath
) -> [String: [String: String]] {
let master = ["swift-dependencies": "\(derivedData.pathString)/\(module)-master.swiftdeps"]
func baseNameEntry(_ s: AbsolutePath) -> [String: String] {
[
"dependencies": ".d",
"diagnostics": ".dia",
"llvm-bc": ".bc",
"object": ".o",
"swift-dependencies": ".swiftdeps",
"swiftmodule": "-partial.swiftmodule"
]
.mapValues {"\(derivedData.appending(component: s.basenameWithoutExt))\($0)"}
}
return Dictionary( uniqueKeysWithValues:
inputPaths.map { ("\($0)", baseNameEntry($0)) }
)
.merging(["": master]) {_, _ in fatalError()}
}

private func generateOutputFileMapData(module: String,
inputPaths: [AbsolutePath],
derivedData: AbsolutePath
) -> Data {
let d: [String: [String: String]] = generateOutputFileMapDict(
module: module,
inputPaths: inputPaths,
derivedData: derivedData)
let enc = JSONEncoder()
return try! enc.encode(d)
}

private func writeOutputFileMapData(module: String,
inputPaths: [AbsolutePath],
derivedData: AbsolutePath,
to dst: AbsolutePath) {
let d: Data = generateOutputFileMapData(module: module, inputPaths: inputPaths,
derivedData: derivedData)
try! localFileSystem.writeFileContents(dst, bytes: ByteString(d))
}
}

class CrossModuleIncrementalBuildTests: XCTestCase {
Expand Down Expand Up @@ -935,3 +905,4 @@ class CrossModuleIncrementalBuildTests: XCTestCase {
}
}
}