Skip to content

Commit e1749fb

Browse files
CopilotDaanV2
andcommitted
Add comprehensive RFC4122 and RFC9562 compliance tests
Co-authored-by: DaanV2 <2393905+DaanV2@users.noreply.github.com>
1 parent 50386bd commit e1749fb

2 files changed

Lines changed: 531 additions & 0 deletions

File tree

Tests/RFC/RFC4122.cs

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using DaanV2.UUID;
2+
using System.Text;
23

34
namespace Tests.RFC;
45

@@ -12,4 +13,254 @@ public void RFC4122_AppendixB_V3_MD5_DNS_ExampleCom() {
1213
Utility.ValidateUUID(uuid, V3.Version, V3.Variant);
1314
}
1415

16+
// ========== Bit-Level Validation Tests ==========
17+
18+
[Fact(DisplayName = "RFC4122 Section 4.1.3 - Version bits must be in correct position")]
19+
public void RFC4122_VersionBits_CorrectPosition() {
20+
// Version field is in octet 6, bits 12-15 of time_hi_and_version
21+
var v1uuid = V1.Generate();
22+
var v3uuid = V3.Generate("test");
23+
var v4uuid = V4.Generate();
24+
var v5uuid = V5.Generate("test");
25+
26+
// Version should be readable from the UUID
27+
Assert.Equal(DaanV2.UUID.Version.V1, v1uuid.Version);
28+
Assert.Equal(DaanV2.UUID.Version.V3, v3uuid.Version);
29+
Assert.Equal(DaanV2.UUID.Version.V4, v4uuid.Version);
30+
Assert.Equal(DaanV2.UUID.Version.V5, v5uuid.Version);
31+
}
32+
33+
[Fact(DisplayName = "RFC4122 Section 4.1.1 - Variant bits must be 10x for RFC4122 UUIDs")]
34+
public void RFC4122_VariantBits_RFC4122Compliant() {
35+
// Variant field is in octet 8, bits 6-7 of clock_seq_hi_and_reserved
36+
// Must be 10xxxxxx (0x80-0xBF) for RFC4122 compliant UUIDs
37+
var v1uuid = V1.Generate();
38+
var v3uuid = V3.Generate("test");
39+
var v4uuid = V4.Generate();
40+
var v5uuid = V5.Generate("test");
41+
42+
// All should have variant V1 (RFC4122)
43+
Assert.Equal(Variant.V1, v1uuid.Variant);
44+
Assert.Equal(Variant.V1, v3uuid.Variant);
45+
Assert.Equal(Variant.V1, v4uuid.Variant);
46+
Assert.Equal(Variant.V1, v5uuid.Variant);
47+
}
48+
49+
// ========== Nil and Max UUID Tests (RFC4122 Section 4.1.7) ==========
50+
51+
[Fact(DisplayName = "RFC4122 Section 4.1.7 - Nil UUID is all zeros")]
52+
public void RFC4122_NilUUID_AllZeros() {
53+
var nilUuid = UUID.Zero;
54+
Assert.Equal("00000000-0000-0000-0000-000000000000", nilUuid.ToString().ToLower());
55+
}
56+
57+
[Fact(DisplayName = "RFC4122 - Max UUID is all ones")]
58+
public void RFC4122_MaxUUID_AllOnes() {
59+
var maxUuid = UUID.Max;
60+
Assert.Equal("ffffffff-ffff-ffff-ffff-ffffffffffff", maxUuid.ToString().ToLower());
61+
}
62+
63+
// ========== Determinism Tests for Name-Based UUIDs ==========
64+
65+
[Fact(DisplayName = "RFC4122 Section 4.3 - V3 (MD5) is deterministic")]
66+
public void RFC4122_V3_Deterministic() {
67+
// Same input should always produce the same UUID
68+
var input = "www.example.com";
69+
var uuid1 = V3.Generate(input);
70+
var uuid2 = V3.Generate(input);
71+
var uuid3 = V3.Generate(input);
72+
73+
Assert.Equal(uuid1, uuid2);
74+
Assert.Equal(uuid2, uuid3);
75+
Assert.Equal(uuid1.ToString(), uuid2.ToString());
76+
}
77+
78+
[Fact(DisplayName = "RFC4122 Section 4.3 - V5 (SHA1) is deterministic")]
79+
public void RFC4122_V5_Deterministic() {
80+
// Same input should always produce the same UUID
81+
var input = "www.example.com";
82+
var uuid1 = V5.Generate(input);
83+
var uuid2 = V5.Generate(input);
84+
var uuid3 = V5.Generate(input);
85+
86+
Assert.Equal(uuid1, uuid2);
87+
Assert.Equal(uuid2, uuid3);
88+
Assert.Equal(uuid1.ToString(), uuid2.ToString());
89+
}
90+
91+
[Fact(DisplayName = "RFC4122 - V3 different inputs produce different UUIDs")]
92+
public void RFC4122_V3_DifferentInputs_DifferentUUIDs() {
93+
var uuid1 = V3.Generate("input1");
94+
var uuid2 = V3.Generate("input2");
95+
var uuid3 = V3.Generate("input3");
96+
97+
Assert.NotEqual(uuid1, uuid2);
98+
Assert.NotEqual(uuid2, uuid3);
99+
Assert.NotEqual(uuid1, uuid3);
100+
}
101+
102+
[Fact(DisplayName = "RFC4122 - V5 different inputs produce different UUIDs")]
103+
public void RFC4122_V5_DifferentInputs_DifferentUUIDs() {
104+
var uuid1 = V5.Generate("input1");
105+
var uuid2 = V5.Generate("input2");
106+
var uuid3 = V5.Generate("input3");
107+
108+
Assert.NotEqual(uuid1, uuid2);
109+
Assert.NotEqual(uuid2, uuid3);
110+
Assert.NotEqual(uuid1, uuid3);
111+
}
112+
113+
// ========== Round-Trip Tests ==========
114+
115+
[Fact(DisplayName = "RFC4122 - Parse and ToString round-trip for V1")]
116+
public void RFC4122_V1_RoundTrip() {
117+
var original = V1.Generate();
118+
var str = original.ToString();
119+
var parsed = new UUID(str);
120+
121+
Assert.Equal(original, parsed);
122+
Assert.Equal(original.Version, parsed.Version);
123+
Assert.Equal(original.Variant, parsed.Variant);
124+
}
125+
126+
[Fact(DisplayName = "RFC4122 - Parse and ToString round-trip for V3")]
127+
public void RFC4122_V3_RoundTrip() {
128+
var original = V3.Generate("test");
129+
var str = original.ToString();
130+
var parsed = new UUID(str);
131+
132+
Assert.Equal(original, parsed);
133+
Assert.Equal(original.Version, parsed.Version);
134+
Assert.Equal(original.Variant, parsed.Variant);
135+
}
136+
137+
[Fact(DisplayName = "RFC4122 - Parse and ToString round-trip for V4")]
138+
public void RFC4122_V4_RoundTrip() {
139+
var original = V4.Generate();
140+
var str = original.ToString();
141+
var parsed = new UUID(str);
142+
143+
Assert.Equal(original, parsed);
144+
Assert.Equal(original.Version, parsed.Version);
145+
Assert.Equal(original.Variant, parsed.Variant);
146+
}
147+
148+
[Fact(DisplayName = "RFC4122 - Parse and ToString round-trip for V5")]
149+
public void RFC4122_V5_RoundTrip() {
150+
var original = V5.Generate("test");
151+
var str = original.ToString();
152+
var parsed = new UUID(str);
153+
154+
Assert.Equal(original, parsed);
155+
Assert.Equal(original.Version, parsed.Version);
156+
Assert.Equal(original.Variant, parsed.Variant);
157+
}
158+
159+
// ========== Format Tests ==========
160+
161+
[Fact(DisplayName = "RFC4122 Section 3 - UUID format is 8-4-4-4-12 hexadecimal")]
162+
public void RFC4122_Format_Correct() {
163+
var uuid = V4.Generate();
164+
var str = uuid.ToString();
165+
166+
// Check format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
167+
Assert.Equal(36, str.Length);
168+
Assert.Equal('-', str[8]);
169+
Assert.Equal('-', str[13]);
170+
Assert.Equal('-', str[18]);
171+
Assert.Equal('-', str[23]);
172+
173+
// All other characters should be valid hex
174+
var hexParts = str.Split('-');
175+
Assert.Equal(5, hexParts.Length);
176+
Assert.Equal(8, hexParts[0].Length);
177+
Assert.Equal(4, hexParts[1].Length);
178+
Assert.Equal(4, hexParts[2].Length);
179+
Assert.Equal(4, hexParts[3].Length);
180+
Assert.Equal(12, hexParts[4].Length);
181+
}
182+
183+
// ========== V1 Time-Based Tests ==========
184+
185+
[Fact(DisplayName = "RFC4122 Section 4.2.1 - V1 contains timestamp")]
186+
public void RFC4122_V1_ContainsTimestamp() {
187+
var beforeGen = DateTime.UtcNow;
188+
var uuid = V1.Generate();
189+
var afterGen = DateTime.UtcNow;
190+
191+
var info = V1.Extract(uuid);
192+
193+
// Extracted timestamp should be within reasonable range
194+
Assert.True(info.Timestamp >= beforeGen.AddSeconds(-1));
195+
Assert.True(info.Timestamp <= afterGen.AddSeconds(1));
196+
}
197+
198+
[Fact(DisplayName = "RFC4122 Section 4.2.1 - V1 contains MAC address")]
199+
public void RFC4122_V1_ContainsMacAddress() {
200+
var uuid = V1.Generate();
201+
var info = V1.Extract(uuid);
202+
203+
// MAC address should be 6 bytes
204+
Assert.NotNull(info.MacAddress);
205+
Assert.Equal(6, info.MacAddress.Length);
206+
}
207+
208+
// ========== Uniqueness Tests ==========
209+
210+
[Fact(DisplayName = "RFC4122 Section 4.4 - V4 generates unique UUIDs")]
211+
public void RFC4122_V4_Uniqueness() {
212+
var uuids = new HashSet<UUID>();
213+
const int count = 10000;
214+
215+
for (int i = 0; i < count; i++) {
216+
var uuid = V4.Generate();
217+
Assert.True(uuids.Add(uuid), $"Duplicate UUID generated: {uuid}");
218+
}
219+
220+
Assert.Equal(count, uuids.Count);
221+
}
222+
223+
[Fact(DisplayName = "RFC4122 - V1 generates unique UUIDs")]
224+
public void RFC4122_V1_Uniqueness() {
225+
var uuids = new HashSet<UUID>();
226+
const int count = 1000;
227+
228+
for (int i = 0; i < count; i++) {
229+
var uuid = V1.Generate();
230+
Assert.True(uuids.Add(uuid), $"Duplicate UUID generated: {uuid}");
231+
}
232+
233+
Assert.Equal(count, uuids.Count);
234+
}
235+
236+
// ========== Encoding Tests ==========
237+
238+
[Fact(DisplayName = "RFC4122 - V3 with different encodings")]
239+
public void RFC4122_V3_DifferentEncodings() {
240+
var input = "test string";
241+
var uuidUtf8 = V3.Generate(input, Encoding.UTF8);
242+
var uuidAscii = V3.Generate(input, Encoding.ASCII);
243+
244+
// Same string with same encoding should produce same UUID
245+
var uuidUtf8_2 = V3.Generate(input, Encoding.UTF8);
246+
Assert.Equal(uuidUtf8, uuidUtf8_2);
247+
248+
// For ASCII-compatible strings, UTF8 and ASCII should be the same
249+
Assert.Equal(uuidUtf8, uuidAscii);
250+
}
251+
252+
[Fact(DisplayName = "RFC4122 - V5 with different encodings")]
253+
public void RFC4122_V5_DifferentEncodings() {
254+
var input = "test string";
255+
var uuidUtf8 = V5.Generate(input, Encoding.UTF8);
256+
var uuidAscii = V5.Generate(input, Encoding.ASCII);
257+
258+
// Same string with same encoding should produce same UUID
259+
var uuidUtf8_2 = V5.Generate(input, Encoding.UTF8);
260+
Assert.Equal(uuidUtf8, uuidUtf8_2);
261+
262+
// For ASCII-compatible strings, UTF8 and ASCII should be the same
263+
Assert.Equal(uuidUtf8, uuidAscii);
264+
}
265+
15266
}

0 commit comments

Comments
 (0)