Skip to content

Commit 4b2d294

Browse files
authored
Remove legacy test content discovery. (#1013)
This PR removes the legacy test content discovery mechanism that is based on finding protocol conformances in the type metadata section emitted by the Swift compiler. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent 30daff0 commit 4b2d294

16 files changed

Lines changed: 44 additions & 541 deletions

Documentation/EnvironmentVariables.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,5 @@ names prefixed with `SWT_`.
6767
| `SWIFT_TESTING_XCTEST_INTEROP_MODE` | `String` | Overrides the behavior for handling XCTest assertion failures recorded during a Swift Testing test. One of `none`, `limited`, `complete`, or `strict`. Explanation of modes can be found in [ST-0021][interop-modes]. | <!--prefer to link to MigratingFromXCTest.md once it is updated with interop-->
6868
| `SWT_EXPERIMENTAL_SERIALIZED_TRAIT_APPLIES_GLOBALLY` | `Bool` | Whether or not `.serialized` applies globally or just to its branch of the test graph. |
6969
| `SWT_EXPERIMENTAL_MAXIMUM_PARALLELIZATION_WIDTH` | `Int` | The default parallelization width when parallelized testing is enabled. |
70-
| `SWT_USE_LEGACY_TEST_DISCOVERY` | `Bool` | Used to explicitly enable or disable legacy test discovery. |
7170

7271
[interop-modes]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0021-targeted-interoperability-swift-testing-and-xctest.md#interoperability-modes

Documentation/Porting.md

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,9 @@ When porting to a new platform, you may need to provide a new implementation for
131131
on Swift metadata discovery which is an inherently platform-specific operation.
132132

133133
_Most_ platforms in use today use the ELF image format and will be able to reuse
134-
the implementation used by Linux, FreeBSD, etc.
135-
136-
> [!NOTE]
137-
> We are not using `objectFormat()` in this file yet in order to maintain
138-
> compatibility with the Swift 6.2 toolchain. We will migrate to
139-
> `objectFormat()` when the `_TestDiscovery` target drops Swift 6.2 toolchain
140-
> support in the future.
134+
the implementation used by Linux, FreeBSD, etc. On platforms that use the ELF
135+
image format, the Swift runtime exports a function that Swift Testing uses
136+
during test discovery, and you likely do not need to make changes here.
141137

142138
Classic does not use the ELF image format, so you'll need to write a custom
143139
implementation of `_sectionBounds(_:)` instead. Assuming that the Swift compiler
@@ -150,15 +146,11 @@ to load that information:
150146
+++ b/Sources/_TestDiscovery/SectionBounds.swift
151147

152148
// ...
153-
+#elseif os(Classic)
149+
+#elseif os(Classic) && objectFormat(CFM)
154150
+private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
155151
+ let resourceName: Str255 = switch kind {
156152
+ case .testContent:
157153
+ "__swift5_tests"
158-
+#if !SWT_NO_LEGACY_TEST_DISCOVERY
159-
+ case .typeMetadata:
160-
+ "__swift5_types"
161-
+#endif
162154
+ }
163155
+
164156
+ let oldRefNum = CurResFile()
@@ -206,6 +198,7 @@ platform if it does not use an image format already supported by Swift Testing:
206198
```diff
207199
--- a/Sources/TestingMacros/Support/TestContentGeneration.swift
208200
+++ b/Sources/TestingMacros/Support/TestContentGeneration.swift
201+
209202
let objectFormatsAndSectionNames: [(objectFormat: String, sectionName: String)] = [
210203
("MachO", "__DATA_CONST,__swift5_tests"),
211204
("ELF", "swift5_tests"),
@@ -220,9 +213,8 @@ platform if it does not use an image format already supported by Swift Testing:
220213
If your platform does not support dynamic linking and loading, you will need to
221214
use static linkage instead. Define the `"SWT_NO_DYNAMIC_LINKING"` compiler
222215
conditional for your platform in both `Package.swift` and
223-
`CompilerSettings.cmake`, then define the symbols `_testContentSectionBegin`,
224-
`_testContentSectionEnd`, `_typeMetadataSectionBegin`, and
225-
`_typeMetadataSectionEnd` in `SectionBounds.swift`:
216+
`CompilerSettings.cmake`, then define the symbols `_testContentSectionBegin` and
217+
`_testContentSectionEnd` in `SectionBounds.swift`:
226218

227219
```diff
228220
--- a/Sources/_TestDiscovery/SectionBounds.swift
@@ -231,18 +223,10 @@ conditional for your platform in both `Package.swift` and
231223
+#elseif os(Classic)
232224
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _testContentSectionBegin: _SectionBound
233225
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _testContentSectionEnd: _SectionBound
234-
+#if !SWT_NO_LEGACY_TEST_DISCOVERY
235-
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _typeMetadataSectionBegin: _SectionBound
236-
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _typeMetadataSectionEnd: _SectionBound
237-
+#endif
238226
#else
239227
#warning("Platform-specific implementation missing: Runtime test discovery unavailable (static)")
240228
private nonisolated(unsafe) let _testContentSectionBegin = UnsafeMutableRawPointer.allocate(byteCount: 1, alignment: 16)
241229
private nonisolated(unsafe) let _testContentSectionEnd = _testContentSectionBegin
242-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
243-
private nonisolated(unsafe) let _typeMetadataSectionBegin = UnsafeMutableRawPointer.allocate(byteCount: 1, alignment: 16)
244-
private nonisolated(unsafe) let _typeMetadataSectionEnd = _typeMetadataSectionBegin
245-
#endif
246230
#endif
247231
// ...
248232
```

Package.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,6 @@ extension Array where Element: _LanguageBuildSetting {
514514
"SWT_NO_GLOBAL_ACTORS": (platforms: .none, embedded: true),
515515
"SWT_NO_SUSPENDING_CLOCK": (platforms: .none, embedded: true),
516516

517-
"SWT_NO_LEGACY_TEST_DISCOVERY": (platforms: .none, embedded: true),
518517
"SWT_NO_LIBDISPATCH": (platforms: .none, embedded: true),
519518
]
520519

Sources/Testing/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ add_library(Testing
111111
Test.swift
112112
Test+Cancellation.swift
113113
Test+Discovery.swift
114-
Test+Discovery+Legacy.swift
115114
Test+Macro.swift
116115
Traits/AttachmentSavingTrait.swift
117116
Traits/Bug.swift

Sources/Testing/ExitTests/ExitTest.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -435,15 +435,6 @@ extension ExitTest {
435435
}
436436
}
437437

438-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
439-
// Call the legacy lookup function that discovers tests embedded in types.
440-
for record in Record.allTypeMetadataBasedTestContentRecords() {
441-
if let exitTest = record.load(withHint: id)?.makeExitTest() {
442-
return exitTest
443-
}
444-
}
445-
#endif
446-
447438
return nil
448439
}
449440
}

Sources/Testing/Test+Discovery+Legacy.swift

Lines changed: 0 additions & 62 deletions
This file was deleted.

Sources/Testing/Test+Discovery.swift

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -63,51 +63,17 @@ extension Test {
6363
// defective test records.)
6464
var result = Set<Self>()
6565

66-
// Figure out which discovery mechanism to use. By default, we'll use both
67-
// the legacy and new mechanisms, but we can set an environment variable
68-
// to explicitly select one or the other. When we remove legacy support,
69-
// we can also remove this enumeration and environment variable check.
70-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
71-
let (useNewMode, useLegacyMode) = switch Environment.flag(named: "SWT_USE_LEGACY_TEST_DISCOVERY") {
72-
case .none:
73-
(true, true)
74-
case .some(true):
75-
(false, true)
76-
case .some(false):
77-
(true, false)
78-
}
79-
#else
80-
let useNewMode = true
81-
#endif
82-
8366
// Walk all test content and gather generator functions, then call them in
8467
// a task group and collate their results.
85-
if useNewMode {
86-
let generators = Generator.allTestContentRecords().lazy.compactMap { $0.load() }
87-
await withTaskGroup { taskGroup in
88-
for (i, generator) in generators.enumerated() {
89-
taskGroup.addTask(name: decorateTaskName("test discovery", withAction: "loading test #\(i)")) {
90-
await generator.rawValue()
91-
}
92-
}
93-
result = await taskGroup.reduce(into: result) { $0.insert($1) }
94-
}
95-
}
96-
97-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
98-
// Perform legacy test discovery if needed.
99-
if useLegacyMode && result.isEmpty {
100-
let generators = Generator.allTypeMetadataBasedTestContentRecords().lazy.compactMap { $0.load() }
101-
await withTaskGroup { taskGroup in
102-
for (i, generator) in generators.enumerated() {
103-
taskGroup.addTask(name: decorateTaskName("type-based test discovery", withAction: "loading test #\(i)")) {
104-
await generator.rawValue()
105-
}
68+
let generators = Generator.allTestContentRecords().lazy.compactMap { $0.load() }
69+
await withTaskGroup(of: Self.self) { taskGroup in
70+
for (i, generator) in generators.enumerated() {
71+
taskGroup.addTask(name: decorateTaskName("test discovery", withAction: "loading test #\(i)")) {
72+
await generator.rawValue()
10673
}
107-
result = await taskGroup.reduce(into: result) { $0.insert($1) }
10874
}
75+
result = await taskGroup.reduce(into: result) { $0.insert($1) }
10976
}
110-
#endif
11177

11278
return result
11379
}

Sources/_TestDiscovery/DiscoverableAsTestContent.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,4 @@ public protocol DiscoverableAsTestContent: Sendable {
3939
/// By default, this type equals `Never`, indicating that this type of test
4040
/// content does not support hinting during discovery.
4141
associatedtype TestContentAccessorHint = Never
42-
43-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
44-
/// A string present in the names of types containing test content records
45-
/// associated with this type.
46-
@available(swift, deprecated: 100000.0, message: "Do not adopt this functionality in new code. It will be removed in a future release.")
47-
static var _testContentTypeNameHint: String { get }
48-
#endif
49-
}
50-
51-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
52-
extension DiscoverableAsTestContent {
53-
public static var _testContentTypeNameHint: String {
54-
"__🟡$"
55-
}
5642
}
57-
#endif

Sources/_TestDiscovery/SectionBounds.swift

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ struct SectionBounds: Sendable, BitwiseCopyable {
2626
enum Kind: Int, Equatable, Hashable, CaseIterable {
2727
/// The test content metadata section.
2828
case testContent
29-
30-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
31-
/// The type metadata section.
32-
case typeMetadata
33-
#endif
3429
}
3530

3631
/// All section bounds of the given kind found in the current process.
@@ -45,7 +40,7 @@ struct SectionBounds: Sendable, BitwiseCopyable {
4540
}
4641
}
4742

48-
#if SWT_TARGET_OS_APPLE && !SWT_NO_DYNAMIC_LINKING
43+
#if SWT_TARGET_OS_APPLE && objectFormat(MachO) && !SWT_NO_DYNAMIC_LINKING
4944
// MARK: - Apple implementation
5045

5146
extension SectionBounds.Kind {
@@ -61,10 +56,6 @@ extension SectionBounds.Kind {
6156
switch self {
6257
case .testContent:
6358
("__DATA_CONST", "__swift5_tests")
64-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
65-
case .typeMetadata:
66-
("__TEXT", "__swift5_types")
67-
#endif
6859
}
6960
}
7061
}
@@ -193,7 +184,7 @@ private func _sectionBounds(_ kind: SectionBounds.Kind) -> some RandomAccessColl
193184
#endif
194185
}
195186

196-
#elseif (os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)) && !SWT_NO_DYNAMIC_LINKING
187+
#elseif objectFormat(ELF) && !SWT_NO_DYNAMIC_LINKING
197188
// MARK: - ELF implementation
198189

199190
private import SwiftShims // For MetadataSections
@@ -226,10 +217,6 @@ private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
226217
let range = switch context.pointee.kind {
227218
case .testContent:
228219
sections.swift5_tests
229-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
230-
case .typeMetadata:
231-
sections.swift5_type_metadata
232-
#endif
233220
}
234221
let start = UnsafeRawPointer(bitPattern: range.start)
235222
let size = Int(clamping: range.length)
@@ -247,7 +234,7 @@ private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
247234
return context.result
248235
}
249236

250-
#elseif os(Windows)
237+
#elseif os(Windows) && objectFormat(COFF)
251238
// MARK: - Windows implementation
252239

253240
/// Find the section with the given name in the given module.
@@ -319,10 +306,6 @@ private func _sectionBounds(_ kind: SectionBounds.Kind) -> some Sequence<Section
319306
let sectionName = switch kind {
320307
case .testContent:
321308
".sw5test"
322-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
323-
case .typeMetadata:
324-
".sw5tymd"
325-
#endif
326309
}
327310
return HMODULE.all.lazy.compactMap { _findSection(named: sectionName, in: $0) }
328311
}
@@ -367,28 +350,16 @@ private struct _SectionBound: Sendable, ~Copyable {
367350
}
368351
}
369352

370-
#if SWT_TARGET_OS_APPLE
353+
#if objectFormat(MachO)
371354
@_silgen_name(raw: "section$start$__DATA_CONST$__swift5_tests") private nonisolated(unsafe) var _testContentSectionBegin: _SectionBound
372355
@_silgen_name(raw: "section$end$__DATA_CONST$__swift5_tests") private nonisolated(unsafe) var _testContentSectionEnd: _SectionBound
373-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
374-
@_silgen_name(raw: "section$start$__TEXT$__swift5_types") private nonisolated(unsafe) var _typeMetadataSectionBegin: _SectionBound
375-
@_silgen_name(raw: "section$end$__TEXT$__swift5_types") private nonisolated(unsafe) var _typeMetadataSectionEnd: _SectionBound
376-
#endif
377-
#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI)
356+
#elseif objectFormat(ELF) || objectFormat(Wasm)
378357
@_silgen_name(raw: "__start_swift5_tests") private nonisolated(unsafe) var _testContentSectionBegin: _SectionBound
379358
@_silgen_name(raw: "__stop_swift5_tests") private nonisolated(unsafe) var _testContentSectionEnd: _SectionBound
380-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
381-
@_silgen_name(raw: "__start_swift5_type_metadata") private nonisolated(unsafe) var _typeMetadataSectionBegin: _SectionBound
382-
@_silgen_name(raw: "__stop_swift5_type_metadata") private nonisolated(unsafe) var _typeMetadataSectionEnd: _SectionBound
383-
#endif
384359
#else
385360
#warning("Platform-specific implementation missing: Runtime test discovery unavailable (static)")
386361
private nonisolated(unsafe) let _testContentSectionBegin = UnsafeMutableRawPointer.allocate(byteCount: 1, alignment: 16)
387362
private nonisolated(unsafe) let _testContentSectionEnd = _testContentSectionBegin
388-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
389-
private nonisolated(unsafe) let _typeMetadataSectionBegin = UnsafeMutableRawPointer.allocate(byteCount: 1, alignment: 16)
390-
private nonisolated(unsafe) let _typeMetadataSectionEnd = _typeMetadataSectionBegin
391-
#endif
392363
#endif
393364

394365
/// The common implementation of ``SectionBounds/all(_:)`` for platforms that do
@@ -403,10 +374,6 @@ private func _sectionBounds(_ kind: SectionBounds.Kind) -> CollectionOfOne<Secti
403374
let range = switch kind {
404375
case .testContent:
405376
_testContentSectionBegin ..< _testContentSectionEnd
406-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
407-
case .typeMetadata:
408-
_typeMetadataSectionBegin ..< _typeMetadataSectionEnd
409-
#endif
410377
}
411378
let buffer = UnsafeRawBufferPointer(start: range.lowerBound, count: range.count)
412379
let sb = SectionBounds(imageAddress: nil, buffer: buffer)

0 commit comments

Comments
 (0)