Skip to content

Commit e938e39

Browse files
committed
Get it more working, add some initial tests
1 parent 82781b9 commit e938e39

File tree

14 files changed

+494
-79
lines changed

14 files changed

+494
-79
lines changed

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ extension Array where Element == PackageDescription.SwiftSetting {
389389
// (via CMake). Enabling it is dependent on acceptance of the @section
390390
// proposal via Swift Evolution.
391391
.enableExperimentalFeature("SymbolLinkageMarkers"),
392+
.enableExperimentalFeature("CompileTimeValuesPreview"),
392393

393394
.enableUpcomingFeature("InferIsolatedConformances"),
394395

Sources/Testing/ABI/ABI.Record+Streaming.swift

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ extension ABI.Version {
2424

2525
let humanReadableOutputRecorder = Event.HumanReadableOutputRecorder()
2626
return { [eventHandler = eventHandlerCopy] event, context in
27-
if case .testDiscovered = event.kind, let test = context.test {
27+
if case let .libraryDiscovered(library) = event.kind {
28+
if let libraryRecord = ABI.Record<Self>(encoding: library) {
29+
try? JSON.withEncoding(of: libraryRecord) { libraryJSON in
30+
eventHandler(libraryJSON)
31+
}
32+
}
33+
} else if case .testDiscovered = event.kind, let test = context.test {
2834
try? JSON.withEncoding(of: ABI.Record<Self>(encoding: test)) { testJSON in
2935
eventHandler(testJSON)
3036
}
@@ -47,24 +53,25 @@ extension ABI.Xcode16 {
4753
forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void
4854
) -> Event.Handler {
4955
return { event, context in
50-
if case .testDiscovered = event.kind {
56+
switch event.kind {
57+
case .libraryDiscovered, .testDiscovered:
5158
// Discard events of this kind rather than forwarding them to avoid a
5259
// crash in Xcode 16 (which does not expect any events to occur before
5360
// .runStarted.)
5461
return
55-
}
56-
57-
struct EventAndContextSnapshot: Codable {
58-
var event: Event.Snapshot
59-
var eventContext: Event.Context.Snapshot
60-
}
61-
let snapshot = EventAndContextSnapshot(
62-
event: Event.Snapshot(snapshotting: event),
63-
eventContext: Event.Context.Snapshot(snapshotting: context)
64-
)
65-
try? JSON.withEncoding(of: snapshot) { eventAndContextJSON in
66-
eventAndContextJSON.withUnsafeBytes { eventAndContextJSON in
67-
eventHandler(eventAndContextJSON)
62+
default:
63+
struct EventAndContextSnapshot: Codable {
64+
var event: Event.Snapshot
65+
var eventContext: Event.Context.Snapshot
66+
}
67+
let snapshot = EventAndContextSnapshot(
68+
event: Event.Snapshot(snapshotting: event),
69+
eventContext: Event.Context.Snapshot(snapshotting: context)
70+
)
71+
try? JSON.withEncoding(of: snapshot) { eventAndContextJSON in
72+
eventAndContextJSON.withUnsafeBytes { eventAndContextJSON in
73+
eventHandler(eventAndContextJSON)
74+
}
6875
}
6976
}
7077
}

Sources/Testing/ABI/ABI.Record.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ extension ABI {
1818
struct Record<V>: Sendable where V: ABI.Version {
1919
/// An enumeration describing the various kinds of record.
2020
enum Kind: Sendable {
21+
/// A testing library.
22+
///
23+
/// - Warning: Testing libraries are not yet part of the JSON schema.
24+
case library(EncodedLibrary<V>)
25+
2126
/// A test record.
2227
case test(EncodedTest<V>)
2328

@@ -28,6 +33,13 @@ extension ABI {
2833
/// The kind of record.
2934
var kind: Kind
3035

36+
init?(encoding library: borrowing Library) {
37+
guard V.includesExperimentalFields else {
38+
return nil
39+
}
40+
kind = .library(EncodedLibrary(encoding: library))
41+
}
42+
3143
init(encoding test: borrowing Test) {
3244
kind = .test(EncodedTest(encoding: test))
3345
}
@@ -58,6 +70,9 @@ extension ABI.Record: Codable {
5870
var container = encoder.container(keyedBy: CodingKeys.self)
5971
try container.encode(V.versionNumber, forKey: .version)
6072
switch kind {
73+
case let .library(library):
74+
try container.encode("_library", forKey: .kind)
75+
try container.encode(library, forKey: .payload)
6176
case let .test(test):
6277
try container.encode("test", forKey: .kind)
6378
try container.encode(test, forKey: .payload)
@@ -81,6 +96,9 @@ extension ABI.Record: Codable {
8196
}
8297

8398
switch try container.decode(String.self, forKey: .kind) {
99+
case "_library":
100+
let library = try container.decode(ABI.EncodedLibrary<V>.self, forKey: .payload)
101+
kind = .library(library)
84102
case "test":
85103
let test = try container.decode(ABI.EncodedTest<V>.self, forKey: .payload)
86104
kind = .test(test)

Sources/Testing/ABI/ABI.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ extension ABI {
5959
/// - Returns: A type conforming to ``ABI/Version`` that represents the given
6060
/// ABI version, or `nil` if no such type exists.
6161
static func version(forVersionNumber versionNumber: VersionNumber = ABI.CurrentVersion.versionNumber) -> (any Version.Type)? {
62+
// Special-case the experimental ABI version number (which is intentionally
63+
// higher than any Swift release's version number).
64+
if versionNumber == ExperimentalVersion.versionNumber {
65+
return ExperimentalVersion.self
66+
}
67+
6268
if versionNumber > ABI.HighestVersion.versionNumber {
6369
// If the caller requested an ABI version higher than the current Swift
6470
// compiler version and it's not an ABI version we've explicitly defined,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// This source file is part of the Swift.org open source project
3+
//
4+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
5+
// Licensed under Apache License v2.0 with Runtime Library Exception
6+
//
7+
// See https://swift.org/LICENSE.txt for license information
8+
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
//
10+
11+
extension ABI {
12+
/// A type implementing the JSON encoding of ``Library`` for the ABI entry
13+
/// point and event stream output.
14+
///
15+
/// The properties and members of this type are documented in ABI/JSON.md.
16+
///
17+
/// This type is not part of the public interface of the testing library. It
18+
/// assists in converting values to JSON; clients that consume this JSON are
19+
/// expected to write their own decoders.
20+
///
21+
/// - Warning: Testing libraries are not yet part of the JSON schema.
22+
struct EncodedLibrary<V>: Sendable where V: ABI.Version {
23+
/// The human-readable name of the library.
24+
var name: String
25+
26+
/// The canonical form of the "hint" to run the testing library's tests at
27+
/// runtime.
28+
var canonicalHint: String
29+
30+
init(encoding library: borrowing Library) {
31+
name = library.name
32+
canonicalHint = library.canonicalHint
33+
}
34+
}
35+
}
36+
37+
// MARK: - Codable
38+
39+
extension ABI.EncodedLibrary: Codable {}

Sources/Testing/ABI/EntryPoints/EntryPoint.swift

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,19 @@ func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Ha
3030

3131
do {
3232
#if !SWT_NO_EXIT_TESTS
33-
// If an exit test was specified, run it. `exitTest` returns `Never`.
34-
if let exitTest = ExitTest.findInEnvironmentForEntryPoint() {
35-
await exitTest()
36-
}
33+
// If an exit test was specified, run it. `exitTest` returns `Never`.
34+
if let exitTest = ExitTest.findInEnvironmentForEntryPoint() {
35+
await exitTest()
36+
}
3737
#endif
3838

3939
let args = try args ?? parseCommandLineArguments(from: CommandLine.arguments)
4040

41-
if let library = args.testingLibrary.flatMap(Library.init(named:)) {
41+
#if !SWT_NO_RUNTIME_LIBRARY_DISCOVERY
42+
if let library = args.testingLibrary.flatMap(Library.init(withHint:)) {
4243
return await library.callEntryPoint(passing: args)
4344
}
45+
#endif
4446

4547
// Configure the test runner.
4648
var configuration = try configurationForEntryPoint(from: args)
@@ -96,7 +98,7 @@ func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Ha
9698

9799
// The set of matching tests (or, in the case of `swift test list`, the set
98100
// of all tests.)
99-
let tests: [Test]
101+
var tests = [Test]()
100102

101103
if args.listTests ?? false {
102104
tests = await Array(Test.all)
@@ -117,6 +119,28 @@ func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Ha
117119
for test in tests {
118120
Event.post(.testDiscovered, for: (test, nil), configuration: configuration)
119121
}
122+
} else if args.experimentalListLibraries ?? false {
123+
#if !SWT_NO_RUNTIME_LIBRARY_DISCOVERY
124+
let libraries = Library.all
125+
#else
126+
let libraries = [Library.swiftTesting]
127+
#endif
128+
129+
if args.verbosity > .min {
130+
for library in libraries {
131+
// Print the test ID to stdout (classical CLI behavior.)
132+
#if SWT_TARGET_OS_APPLE && !SWT_NO_FILE_IO
133+
try? FileHandle.stdout.write("\(library.name) (\(library.canonicalHint))\n")
134+
#else
135+
print("\(library.name) (\(library.canonicalHint))")
136+
#endif
137+
}
138+
}
139+
140+
// Post an event for every discovered library (as with tests above).
141+
for library in libraries {
142+
Event.post(.libraryDiscovered(library), for: (nil, nil), configuration: configuration)
143+
}
120144
} else {
121145
// Run the tests.
122146
let runner = await Runner(configuration: configuration)
@@ -212,6 +236,9 @@ public struct __CommandLineArguments_v0: Sendable {
212236
/// The value of the `--list-tests` argument.
213237
public var listTests: Bool?
214238

239+
/// The value of the `--experimental-list-libraries` argument.
240+
public var experimentalListLibraries: Bool?
241+
215242
/// The value of the `--parallel` or `--no-parallel` argument.
216243
public var parallel: Bool?
217244

@@ -346,6 +373,7 @@ extension __CommandLineArguments_v0: Codable {
346373
// do not end up with leading underscores when encoded.
347374
enum CodingKeys: String, CodingKey {
348375
case listTests
376+
case experimentalListLibraries
349377
case parallel
350378
case experimentalMaximumParallelizationWidth
351379
case symbolicateBacktraces
@@ -476,7 +504,7 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
476504
#endif
477505

478506
// Testing library
479-
if let testingLibrary = args.argumentValue(forLabel: "--testing-library") {
507+
if let testingLibrary = Environment.variable(named: "SWT_EXPERIMENTAL_LIBRARY") ?? args.argumentValue(forLabel: "--testing-library") {
480508
result.testingLibrary = testingLibrary
481509
}
482510

@@ -498,6 +526,9 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
498526
// makes invocation from e.g. Wasmtime a bit more intuitive/idiomatic.
499527
result.listTests = true
500528
}
529+
if Environment.flag(named: "SWT_EXPERIMENTAL_LIST_LIBRARIES") == true || args.contains("--experimental-list-libraries") {
530+
result.experimentalListLibraries = true
531+
}
501532

502533
// Parallelization (on by default)
503534
if args.contains("--no-parallel") {

0 commit comments

Comments
 (0)