11using DaanV2 . UUID ;
2+ using System . Text ;
23
34namespace Tests . RFC ;
45
@@ -12,4 +13,253 @@ 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+ const int count = 1000 ;
226+
227+ // Use batch function which properly handles timestamp incrementing
228+ var uuids = V1 . Batch ( count ) ;
229+ var uniqueUuids = new HashSet < UUID > ( uuids ) ;
230+
231+ // All UUIDs should be unique when using batch generation
232+ Assert . Equal ( count , uniqueUuids . Count ) ;
233+ }
234+
235+ // ========== Encoding Tests ==========
236+
237+ [ Fact ( DisplayName = "RFC4122 - V3 with different encodings" ) ]
238+ public void RFC4122_V3_DifferentEncodings ( ) {
239+ var input = "test string" ;
240+ var uuidUtf8 = V3 . Generate ( input , Encoding . UTF8 ) ;
241+ var uuidAscii = V3 . Generate ( input , Encoding . ASCII ) ;
242+
243+ // Same string with same encoding should produce same UUID
244+ var uuidUtf8_2 = V3 . Generate ( input , Encoding . UTF8 ) ;
245+ Assert . Equal ( uuidUtf8 , uuidUtf8_2 ) ;
246+
247+ // For ASCII-compatible strings, UTF8 and ASCII should be the same
248+ Assert . Equal ( uuidUtf8 , uuidAscii ) ;
249+ }
250+
251+ [ Fact ( DisplayName = "RFC4122 - V5 with different encodings" ) ]
252+ public void RFC4122_V5_DifferentEncodings ( ) {
253+ var input = "test string" ;
254+ var uuidUtf8 = V5 . Generate ( input , Encoding . UTF8 ) ;
255+ var uuidAscii = V5 . Generate ( input , Encoding . ASCII ) ;
256+
257+ // Same string with same encoding should produce same UUID
258+ var uuidUtf8_2 = V5 . Generate ( input , Encoding . UTF8 ) ;
259+ Assert . Equal ( uuidUtf8 , uuidUtf8_2 ) ;
260+
261+ // For ASCII-compatible strings, UTF8 and ASCII should be the same
262+ Assert . Equal ( uuidUtf8 , uuidAscii ) ;
263+ }
264+
15265}
0 commit comments