Skip to content

Commit 00c40c3

Browse files
committed
Seeded deterministic UUID generation test
1 parent d9ffe2f commit 00c40c3

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

Tests/FoundationEssentialsTests/UUIDTests.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ final class UUIDTests : XCTestCase {
124124
XCTAssertEqual(uuid.varint, 0b10)
125125
}
126126
}
127+
128+
func testDeterministicRandomGeneration() {
129+
var generator = PCGRandomNumberGenerator(seed: 123456789)
130+
131+
let firstUUID = UUID.random(using: &generator)
132+
XCTAssertEqual(firstUUID, UUID(uuidString: "9492BAC4-F353-49E7-ACBB-A40941CA65DE"))
133+
134+
let secondUUID = UUID.random(using: &generator)
135+
XCTAssertEqual(secondUUID, UUID(uuidString: "392C44E5-EB3E-4455-85A7-AF9556722B9A"))
136+
137+
let thirdUUID = UUID.random(using: &generator)
138+
XCTAssertEqual(thirdUUID, UUID(uuidString: "9ABFCCE9-AA85-485C-9CBF-C62F0C8D1D1A"))
139+
140+
let fourthUUID = UUID.random(using: &generator)
141+
XCTAssertEqual(fourthUUID, UUID(uuidString: "2B29542E-F719-4D58-87B9-C6291ADD4541"))
142+
}
127143
}
128144

129145
extension UUID {
@@ -135,3 +151,29 @@ extension UUID {
135151
Int(self.uuid.8 >> 6 & 0b11)
136152
}
137153
}
154+
155+
fileprivate struct PCGRandomNumberGenerator: RandomNumberGenerator {
156+
private static let multiplier: UInt128 = 47_026_247_687_942_121_848_144_207_491_837_523_525
157+
private static let increment: UInt128 = 117_397_592_171_526_113_268_558_934_119_004_209_487
158+
159+
private var state: UInt128
160+
161+
fileprivate init(seed: UInt64) {
162+
self.state = UInt128(seed)
163+
}
164+
165+
// Implements pcg_oneseq_128_xsl_rr_64_random_r from https://www.pcg-random.org
166+
fileprivate mutating func next() -> UInt64 {
167+
self.state = self.state &* Self.multiplier &+ Self.increment
168+
169+
return rotr64(
170+
value: UInt64(truncatingIfNeeded: self.state &>> 64) ^ UInt64(truncatingIfNeeded: self.state),
171+
rotation: UInt64(truncatingIfNeeded: self.state &>> 122)
172+
)
173+
}
174+
175+
private func rotr64(value: UInt64, rotation: UInt64) -> UInt64 {
176+
(value &>> rotation) | value &<< ((~rotation &+ 1) & 63)
177+
}
178+
}
179+

0 commit comments

Comments
 (0)