File: Transitivity.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (145 lines) | stat: -rw-r--r-- 5,408 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//===---------------- Transitivity.swift - Swift Testing ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 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 IncrementalTestFramework

// This test establishes a "transitive" chain of modules that import one another
// and ensures that a cross-module incremental build rebuilds all modules
// involved in the chain.
//
// Module C    Module B    Module A
// -------- -> -------- -> --------
//    |                        ^
//    |                        |
//    -------------------------
class TransitivityTest: XCTestCase {
  func testTransitiveTopLevelUses() throws {
    try IncrementalTest.perform([
      // Build a baseline
      Step(adding: "transitive-baseline",
           building: [.C, .B, .A],
           .expecting([.C, .B, .A].allSourcesToCompile)),
      // Swap in a new default argument: B needs to rebuild `fromB` and
      // relink against fromC, but A doesn't import `C` so only non-incremental
      // imports rebuilds it.
      Step(adding: "transitive-add-default",
           building: [.C, .B, .A],
           .expecting(.init(always: [.C, .B], andWhenDisabled: [.A]))),
      // Now change C back to the old baseline. We edit A in the process to
      // introduce a dependency on C, so it needs to rebuild.
      Step(adding: "transitive-baseline", "transitive-add-use-in-A",
           building: [.C, .B, .A],
           .expecting(.init(always: [.C, .B, .A]))),
      // Same as before - the addition of a default argument requires B rebuild,
      // but A doesn't use anything from C, so it doesn't rebuild unless
      // incremental imports are disabled.
      Step(adding: "transitive-add-default", "transitive-add-use-in-A",
           building: [.C, .B, .A],
           .expecting(.init(always: [.C, .B], andWhenDisabled: [.A]))),
    ])
  }

  func testTransitiveStructMember() throws {
    try IncrementalTest.perform([
      // Establish the baseline build
      Step(adding: "transitive-baseline",
           building: [.C, .B, .A],
           .expecting(.init(always: [ .A, .B, .C ]))),
      // Add the def of a struct to C, which B imports and has a use of so
      // B rebuilds but A does not unless incremental imports are disabled.
      Step(adding: "transitive-baseline", "transitive-struct-def-in-C",
           building: [.C, .B, .A],
           .expecting(.init(always: [ .B, .C ], andWhenDisabled: [ .A ]))),
      // Now add a use in B, make sure C doesn't rebuild.
      Step(adding: "transitive-baseline", "transitive-struct-def-in-C", "transitive-struct-def-in-B",
           building: [.C, .B, .A],
           .expecting(.init(always: [ .B, ], andWhenDisabled: [ .A ]))),
      // Now add a use in A and make sure only A rebuilds.
      Step(adding: "transitive-baseline", "transitive-struct-def-in-C", "transitive-struct-def-in-B", "transitive-struct-def-in-A",
           building: [.C, .B, .A],
           .expecting(.init(always: [ .A ]))),
      // Finally, add a member to a struct in C, which influences the layout of
      // the struct in B, which influences the layout of the struct in A.
      // Everything rebuilds!
      Step(adding: "transitive-baseline", "transitive-struct-add-member-in-C", "transitive-struct-def-in-B", "transitive-struct-def-in-A",
           building: [.C, .B, .A],
           .expecting(.init(always: [ .A, .B, .C ]))),
    ])
  }
}

fileprivate extension Module {
  static var A = Module(named: "A", containing: [
    .A,
  ], importing: [
    .B, .C,
  ], producing: .executable)

  static var B = Module(named: "B", containing: [
    .B,
  ], importing: [
    .C
  ], producing: .library)

  static var C = Module(named: "C", containing: [
    .C,
  ], producing: .library)
}

fileprivate extension Source {
  static var A: Source {
    Self(
    named: "A",
    containing: """
                import B

                //# transitive-add-use-in-A import C
                //# transitive-add-use-in-A public func fromA() {
                //# transitive-add-use-in-A   return fromB()
                //# transitive-add-use-in-A }

                //# transitive-struct-def-in-A import C
                //# transitive-struct-def-in-A struct AStruct { var b: BStruct }
                """)
  }
}

fileprivate extension Source {
  static var B: Source {
    Self(
    named: "B",
    containing: """
                import C

                public func fromB() {
                  return fromC()
                }

                //# transitive-struct-def-in-B public struct BStruct { var c: CStruct }
                """)
  }
}

fileprivate extension Source {
  static var C: Source {
    Self(
    named: "C",
    containing: """
                //# transitive-baseline public func fromC() {}
                //# transitive-add-default public func fromC(parameter: Int = 0) {}

                //# transitive-struct-def-in-C public struct CStruct {  }
                //# transitive-struct-add-member-in-C public struct CStruct { var x: Int }
                """)
  }
}