Skip to content

Commit 970fe7d

Browse files
committed
Add support for platforms without Foundation
1 parent ec8b828 commit 970fe7d

File tree

5 files changed

+57
-8
lines changed

5 files changed

+57
-8
lines changed

.spi.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ version: 1
22
builder:
33
configs:
44
- documentation_targets: [PropertyBased]
5+
custom_documentation_parameters:
6+
- --enable-experimental-overloaded-symbol-presentation

Sources/PropertyBased/FixedSeedTrait.swift

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import Testing
1212
///
1313
/// Use ``fixedSeed(_:sourceLocation:)`` to construct an instance of this trait.
1414
public struct FixedSeedTrait: TestTrait, TestScoping {
15-
init(_ seed: String, _ sourceLocation: SourceLocation) {
16-
rng = Xoshiro(seed: seed)
15+
init(_ rng: Xoshiro?, _ sourceLocation: SourceLocation) {
16+
self.rng = rng
1717
self.sourceLocation = sourceLocation
1818
}
1919

@@ -58,7 +58,34 @@ extension Trait where Self == FixedSeedTrait {
5858
/// - sourceLocation: The source location of the trait.
5959
///
6060
/// - Returns: An instance of ``FixedSeedTrait``.
61+
#if canImport(Foundation)
6162
public static func fixedSeed(_ seed: StaticString, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
62-
return Self(seed.description, sourceLocation)
63+
let rng = Xoshiro(seed: seed.description)
64+
return Self(rng, sourceLocation)
65+
}
66+
#else
67+
@available(*, unavailable, message: "Base64-encoded seeds aren't supported on platforms without Foundation.\nUse the fixedSeed() overload that takes UInt64's instead.")
68+
public static func fixedSeed(_ seed: StaticString, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
69+
fatalError("Base64 is not supported")
70+
}
71+
#endif
72+
73+
/// Override the seed used by all property checks within this Test.
74+
///
75+
/// If one of your property checks fails intermittently, apply this trait to reliably reproduce the issue.
76+
///
77+
/// > Important: Do not commit usages of this trait into version control. Applying this trait will always report an issue regardless of the existence of any failures within the test.
78+
///
79+
/// - Parameters:
80+
/// - s1: The first part of the seed to use.
81+
/// - s2: The second part of the seed.
82+
/// - s3: The third part of the seed.
83+
/// - s4: The fourth part of the seed.
84+
/// - sourceLocation: The source location of the trait.
85+
///
86+
/// - Returns: An instance of ``FixedSeedTrait``.
87+
public static func fixedSeed(_ s1: UInt64, _ s2: UInt64, _ s3: UInt64, _ s4: UInt64, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
88+
let rng = Xoshiro(seed: (s1, s2, s3, s4))
89+
return Self(rng, sourceLocation)
6390
}
6491
}

Sources/PropertyBased/PropertyCheck.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public func propertyCheck<each Value>(isolation: isolated (any Actor)? = #isolat
9393
}
9494

9595
if foundIssues > 0 {
96-
let seed = rngCopy.currentSeed
96+
let seed = rngCopy.traitHint
9797

9898
var paramLabels: [String] = []
9999
for gen in repeat each input {
@@ -105,7 +105,7 @@ public func propertyCheck<each Value>(isolation: isolated (any Actor)? = #isolat
105105
"Failure occured with inputs (\(paramLabels.joined(separator: ", ")))."
106106

107107
if fixedRng == nil {
108-
Issue.record("\(inputLabel)\n\nAdd `.fixedSeed(\"\(seed)\")` to the Test to reproduce this issue.", sourceLocation: sourceLocation)
108+
Issue.record("\(inputLabel)\n\nAdd `.fixedSeed\(seed)` to the Test to reproduce this issue.", sourceLocation: sourceLocation)
109109
} else {
110110
Issue.record("\(inputLabel)", sourceLocation: sourceLocation)
111111
}

Sources/PropertyBased/SeededRandomNumberGenerator.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
public protocol SeededRandomNumberGenerator: RandomNumberGenerator, Hashable, Sendable {
1414

1515
/// The type to use as the seed.
16-
associatedtype Seed: Hashable & Codable
16+
associatedtype Seed: Sendable
1717

1818
/// The current seed of the generator.
1919
///
@@ -25,7 +25,7 @@ public protocol SeededRandomNumberGenerator: RandomNumberGenerator, Hashable, Se
2525
///
2626
/// If the seed is invalid or incomplete, this initializer returns `nil`.
2727
/// - Parameter seed: The seed to use.
28-
init?(seed: String)
28+
init?(seed: Seed)
2929

3030
/// Create an instance of this generator with a seed provided by a high-quality random source.
3131
init()

Sources/PropertyBased/Xoshiro+SeededRandomNumberGenerator.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//
77

88
import Gen
9-
import Foundation
109

1110
extension Xoshiro: @retroactive @unchecked Sendable {}
1211
extension Xoshiro: @retroactive Hashable {
@@ -22,6 +21,15 @@ extension Xoshiro: @retroactive Hashable {
2221
}
2322
}
2423

24+
extension Xoshiro {
25+
public init(seed: (UInt64, UInt64, UInt64, UInt64)) {
26+
self.init(state: seed)
27+
}
28+
}
29+
30+
#if canImport(Foundation)
31+
import Foundation
32+
2533
extension Xoshiro: SeededRandomNumberGenerator {
2634
public typealias Seed = String
2735

@@ -43,4 +51,16 @@ extension Xoshiro: SeededRandomNumberGenerator {
4351
let data = bytes.withUnsafeBufferPointer { Data(buffer: $0) }
4452
return data.base64EncodedString()
4553
}
54+
55+
var traitHint: String {
56+
"(\"\(currentSeed)\")"
57+
}
58+
}
59+
#else
60+
extension Xoshiro: SeededRandomNumberGenerator {
61+
public typealias Seed = (UInt64, UInt64, UInt64, UInt64)
62+
63+
public var currentSeed: Seed { currentState }
64+
var traitHint: String { "\(currentState)" }
4665
}
66+
#endif

0 commit comments

Comments
 (0)