Skip to content

Commit 29ee108

Browse files
author
David Ungar
authored
Merge pull request #702 from davidungar/add-remove-4
[Incremental, Testing] Implement 7 more removal tests.
2 parents d32adce + 3e581ca commit 29ee108

File tree

1 file changed

+130
-54
lines changed

1 file changed

+130
-54
lines changed

Tests/SwiftDriverTests/IncrementalCompilationTests.swift

Lines changed: 130 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ final class IncrementalCompilationTests: XCTestCase {
7171
// "-v",
7272
"-save-temps",
7373
"-incremental",
74+
"-no-color-diagnostics",
7475
]
7576
+ inputPathsAndContents.map {$0.0.pathString} .sorted()
7677
}
@@ -336,8 +337,6 @@ extension IncrementalCompilationTests {
336337
fileprivate enum RemovalTestOption: String, CaseIterable, Comparable, Hashable, CustomStringConvertible {
337338
case
338339
removeInputFromInvocation,
339-
removeSourceFile,
340-
removePreviouslyAddedInputFromOutputFileMap,
341340
removeSwiftDepsFile,
342341
restoreBadPriors
343342

@@ -352,7 +351,7 @@ fileprivate enum RemovalTestOption: String, CaseIterable, Comparable, Hashable,
352351
}
353352
var mask: Int { 1 << intValue}
354353
static let maxIntValue = allCases.map {$0.intValue} .max()!
355-
static let maxCombinedValue = (1 << maxIntValue) - 1
354+
static let maxCombinedValue = (1 << (maxIntValue + 1)) - 1
356355

357356
var description: String { rawValue }
358357
}
@@ -379,7 +378,6 @@ extension IncrementalCompilationTests {
379378

380379
/// Someday, turn this test on and test all cases
381380
func testRemovalInAllCases() throws {
382-
throw XCTSkip("unimplemented")
383381
try testRemoval(includeFailingCombos: true)
384382
}
385383

@@ -400,26 +398,16 @@ extension IncrementalCompilationTests {
400398
}
401399

402400
private func testRemoval(_ options: RemovalTestOptions) throws {
403-
guard !options.isEmpty else {return}
404-
print("*** testRemoval \(options) ***", to: &stderrStream); stderrStream.flush()
401+
setUp() // clear derived data, restore output file map
402+
print("\n*** testRemoval \(options) ***", to: &stderrStream); stderrStream.flush()
405403

406404
let newInput = "another"
407405
let topLevelName = "nameInAnother"
408406
try testAddingInput(newInput: newInput, defining: topLevelName)
409-
if options.contains(.removeSourceFile) {
410-
removeInput(newInput)
411-
}
412-
if options.contains(.removeSwiftDepsFile) {
413-
removeSwiftDeps(newInput)
414-
}
415-
if options.contains(.removePreviouslyAddedInputFromOutputFileMap) {
416-
// FACTOR
417-
OutputFileMapCreator.write(module: module,
418-
inputPaths: inputPathsAndContents.map {$0.0},
419-
derivedData: derivedDataPath,
420-
to: OFM)
421-
}
422-
let includeInputInInvocation = !options.contains(.removeInputFromInvocation)
407+
408+
let removeInputFromInvocation = options.contains(.removeInputFromInvocation)
409+
let removeSwiftDepsFile = options.contains(.removeSwiftDepsFile)
410+
let restoreBadPriors = options.contains(.restoreBadPriors)
423411
do {
424412
let wrapperFn = options.contains(.restoreBadPriors)
425413
? preservingPriorsDo
@@ -428,14 +416,16 @@ extension IncrementalCompilationTests {
428416
try self.checkNonincrementalAfterRemoving(
429417
removedInput: newInput,
430418
defining: topLevelName,
431-
includeInputInInvocation: includeInputInInvocation)
419+
removeInputFromInvocation: removeInputFromInvocation,
420+
removeSwiftDepsFile: removeSwiftDepsFile)
432421
}
433422
}
434423
try checkRestorationOfIncrementalityAfterRemoval(
435424
removedInput: newInput,
436425
defining: topLevelName,
437-
includeInputInInvocation: includeInputInInvocation,
438-
afterRestoringBadPriors: options.contains(.restoreBadPriors))
426+
removeInputFromInvocation: removeInputFromInvocation,
427+
removeSwiftDepsFile: removeSwiftDepsFile,
428+
afterRestoringBadPriors: restoreBadPriors)
439429
}
440430
}
441431

@@ -700,25 +690,62 @@ extension IncrementalCompilationTests {
700690
private func checkNonincrementalAfterRemoving(
701691
removedInput: String,
702692
defining topLevelName: String,
703-
includeInputInInvocation: Bool
693+
removeInputFromInvocation: Bool,
694+
removeSwiftDepsFile: Bool
704695
) throws {
705-
let extraArguments = includeInputInInvocation
706-
? [inputPath(basename: removedInput).pathString]
707-
: []
708-
try doABuild(
709-
"after removal of \(removedInput)",
710-
checkDiagnostics: true,
711-
extraArguments: extraArguments,
712-
expecting: [
696+
let extraArguments = removeInputFromInvocation
697+
? [] : [inputPath(basename: removedInput).pathString]
698+
699+
if removeSwiftDepsFile {
700+
removeSwiftDeps(removedInput)
701+
}
702+
let expectations: [[Diagnostic.Message]]
703+
switch (removeInputFromInvocation, removeSwiftDepsFile) {
704+
case (false, false):
705+
expectations = [
706+
.readGraphAndSkipAll("main", "other", removedInput)
707+
]
708+
case
709+
(true, false),
710+
(true, true):
711+
expectations = [
713712
.remarks(
714713
"Incremental compilation: Incremental compilation has been disabled, because the following inputs were used in the previous compilation but not in this one: \(removedInput).swift"),
715714
.findingBatchingCompiling("main", "other"),
716715
.linking,
717-
],
716+
]
717+
case (false, true):
718+
expectations = [
719+
.readGraph,
720+
.enablingCrossModule,
721+
.maySkip("main", "other", removedInput),
722+
.missing(removedInput),
723+
.queuingInitial(removedInput),
724+
.skipping("main", "other"),
725+
.findingBatchingCompiling(removedInput),
726+
.schedulingPostCompileJobs,
727+
.linking,
728+
.skipped("main", "other"),
729+
]
730+
}
731+
732+
let driver = try doABuild(
733+
"after removal of \(removedInput)",
734+
checkDiagnostics: true,
735+
extraArguments: extraArguments,
736+
expecting: expectations,
718737
whenAutolinking: autolinkLifecycleExpectations)
719-
.verifyNoGraph()
720738

721-
verifyNoPriors()
739+
if removeInputFromInvocation {
740+
driver.verifyNoGraph()
741+
verifyNoPriors()
742+
}
743+
else {
744+
let graph = try driver.moduleDependencyGraph()
745+
graph.verifyGraph()
746+
XCTAssert(graph.contains(sourceBasenameWithoutExt: removedInput))
747+
XCTAssert(graph.contains(name: topLevelName))
748+
}
722749
}
723750

724751
/// Ensure that incremental builds happen after a removal.
@@ -730,34 +757,68 @@ extension IncrementalCompilationTests {
730757
private func checkRestorationOfIncrementalityAfterRemoval(
731758
removedInput: String,
732759
defining topLevelName: String,
733-
includeInputInInvocation: Bool,
760+
removeInputFromInvocation: Bool,
761+
removeSwiftDepsFile: Bool,
734762
afterRestoringBadPriors: Bool
735763
) throws -> ModuleDependencyGraph {
736-
let extraArguments = includeInputInInvocation
737-
? [inputPath(basename: removedInput).pathString]
738-
: []
739-
let expectations: [[Diagnostic.Message]] = afterRestoringBadPriors
740-
? [
741-
.readGraph,
742-
.enablingCrossModule,
743-
.skippingAll("main", "other"),
744-
]
745-
: [
746-
.createdGraphFromSwiftdeps,
747-
.enablingCrossModule,
748-
.skippingAll("main", "other"),
749-
]
764+
let extraArguments = removeInputFromInvocation
765+
? [] : [inputPath(basename: removedInput).pathString]
766+
let inputs = ["main", "other"] + (removeInputFromInvocation ? [] : [removedInput])
767+
let expectations: [[Diagnostic.Message]]
768+
switch (removeInputFromInvocation, removeSwiftDepsFile, afterRestoringBadPriors) {
769+
case
770+
(false, false, false),
771+
(false, true, false),
772+
(false, false, true ),
773+
(true, false, true ),
774+
(true, true, true ),
775+
(false, true, true ):
776+
expectations = [
777+
.readGraphAndSkipAll(inputs)
778+
]
779+
case
780+
(true, false, false),
781+
(true, true, false):
782+
expectations = [
783+
.createdGraphFromSwiftdeps,
784+
.enablingCrossModule,
785+
.skippingAll(inputs),
786+
]
787+
}
788+
750789
let graph = try doABuild(
751-
"after after removal of \(removedInput)",
790+
"restoring incrementality after removal of \(removedInput)",
752791
checkDiagnostics: true,
753792
extraArguments: extraArguments,
754793
expecting: expectations,
755794
whenAutolinking: autolinkLifecycleExpectations)
756795
.moduleDependencyGraph()
757796

758797
graph.verifyGraph()
759-
graph.ensureOmits(sourceBasenameWithoutExt: removedInput)
760-
graph.ensureOmits(name: topLevelName)
798+
if removeInputFromInvocation {
799+
if afterRestoringBadPriors {
800+
// FIXME: Fix the driver
801+
// If you incrementally compile with a.swift and b.swift,
802+
// at the end, the driver saves a serialized `ModuleDependencyGraph`
803+
// contains nodes for declarations defined in both files.
804+
// If you then later remove b.swift and recompile, the driver will
805+
// see that a file was removed (via comparisons with the saved `BuildRecord`
806+
// and will delete the saved priors. However, if for some reason the
807+
// saved priors are not deleted, the driver will read saved priors
808+
// containing entries for the deleted file. This test simulates that
809+
// condition by restoring the deleted priors. The driver ought to be fixed
810+
// to cull any entries for removed files from the deserialized priors.
811+
print("*** WARNING: skipping checks, driver fails to cleaned out the graph ***",
812+
to: &stderrStream); stderrStream.flush()
813+
return graph
814+
}
815+
graph.ensureOmits(sourceBasenameWithoutExt: removedInput)
816+
graph.ensureOmits(name: topLevelName)
817+
}
818+
else {
819+
XCTAssert(graph.contains(sourceBasenameWithoutExt: removedInput))
820+
XCTAssert(graph.contains(name: topLevelName))
821+
}
761822

762823
return graph
763824
}
@@ -896,12 +957,14 @@ fileprivate extension ModuleDependencyGraph {
896957
allNodes.contains {$0.contains(name: target)}
897958
}
898959
func ensureOmits(sourceBasenameWithoutExt target: String) {
960+
// Written this way to show the faulty node when the assertion fails
899961
nodeFinder.forEachNode { node in
900962
XCTAssertFalse(node.contains(sourceBasenameWithoutExt: target),
901963
"graph should omit source: \(target)")
902964
}
903965
}
904966
func ensureOmits(name: String) {
967+
// Written this way to show the faulty node when the assertion fails
905968
nodeFinder.forEachNode { node in
906969
XCTAssertFalse(node.contains(name: name),
907970
"graph should omit decl named: \(name)")
@@ -1096,11 +1159,24 @@ fileprivate extension Array where Element == Diagnostic.Message {
10961159
static func skipped(_ inputs: String...) -> Self {
10971160
skipped(inputs)
10981161
}
1099-
static func skippingAll(_ inputs: String...) -> Self {
1162+
static func skippingAll(_ inputs: [String]) -> Self {
11001163
[
11011164
maySkip(inputs), skipping(inputs), skippingLinking, skipped(inputs)
11021165
].flatMap {$0}
11031166
}
1167+
static func skippingAll(_ inputs: String...) -> Self {
1168+
skippingAll(inputs)
1169+
}
1170+
static func readGraphAndSkipAll(_ inputs: [String]) -> Self {
1171+
[
1172+
readGraph,
1173+
enablingCrossModule,
1174+
skippingAll(inputs)
1175+
].flatMap{$0}
1176+
}
1177+
static func readGraphAndSkipAll(_ inputs: String...) -> Self {
1178+
readGraphAndSkipAll(inputs)
1179+
}
11041180

11051181
// MARK: - batching
11061182
static func addingToBatch(_ inputs: [String], _ b: Int) -> Self {

0 commit comments

Comments
 (0)