@@ -25,6 +25,46 @@ let uuid_arrays =
25
25
let non_uuid_arrays =
26
26
[[|0 |]; [|0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ; 10 ; 11 ; 12 ; 13 ; 14 |]]
27
27
28
+ let uuid_v7_times =
29
+ let of_ms ms = Int64. mul 1_000_000L (Int64. of_float ms) in
30
+ let power_of_2_ms n = Float. pow 2.0 (Float. of_int n) |> of_ms in
31
+ let zero = 0L in
32
+ let ms = 1_000_000L in
33
+ let ns = 1L in
34
+ (* Using RFC9562 "method 3" for representiong sub-millisecond fractions,
35
+ that smallest amount of time a v7 UUID can represent is 1 / 4096 ms,
36
+ which is (just more than) 244 nanoseconds *)
37
+ let tick = 245L in
38
+ let ( + ) = Int64. add in
39
+ let ( - ) = Int64. sub in
40
+ [
41
+ (zero, " 00000000-0000-7000-8000-000000000000" )
42
+ ; (tick, " 00000000-0000-7001-8000-000000000000" )
43
+ ; (ms, " 00000000-0001-7000-8000-000000000000" )
44
+ ; (ms - ns, " 00000000-0000-7fff-8000-000000000000" )
45
+ (* Test a wide range of dates - however, we can't express dates of
46
+ beyond epoch + (2^64 - 1) nanoseconds, which is about approximately
47
+ epoch + 2^44 milliseconds - some point in the 26th century *)
48
+ ; (power_of_2_ms 05 , " 00000000-0020-7000-8000-000000000000" )
49
+ ; (power_of_2_ms 10 , " 00000000-0400-7000-8000-000000000000" )
50
+ ; (power_of_2_ms 15 , " 00000000-8000-7000-8000-000000000000" )
51
+ ; (power_of_2_ms 20 , " 00000010-0000-7000-8000-000000000000" )
52
+ ; (power_of_2_ms 25 , " 00000200-0000-7000-8000-000000000000" )
53
+ ; (power_of_2_ms 30 , " 00004000-0000-7000-8000-000000000000" )
54
+ ; (power_of_2_ms 35 , " 00080000-0000-7000-8000-000000000000" )
55
+ ; (power_of_2_ms 40 , " 01000000-0000-7000-8000-000000000000" )
56
+ ; (power_of_2_ms 44 , " 10000000-0000-7000-8000-000000000000" )
57
+ ; (power_of_2_ms 44 - ns, " 0fffffff-ffff-7fff-8000-000000000000" )
58
+ ; (power_of_2_ms 44 + tick, " 10000000-0000-7001-8000-000000000000" )
59
+ ]
60
+
61
+ let uuid_v7_bytes =
62
+ [
63
+ (1L , " 00000000-0000-7000-8000-000000000001" )
64
+ ; (- 1L , " 00000000-0000-7000-bfff-ffffffffffff" )
65
+ ; (0x1234_5678_9abc_def0L , " 00000000-0000-7000-9234-56789abcdef0" )
66
+ ]
67
+
28
68
type resource = [`Generic ]
29
69
30
70
let uuid_testable : (module Alcotest.TESTABLE with type t = resource Uuidx. t) =
@@ -51,6 +91,36 @@ let roundtrip_tests testing_uuid =
51
91
; (" Roundtrip array conversion" , `Quick , test_array)
52
92
]
53
93
94
+ let uuid_v7_time_tests (t , expected_as_string ) =
95
+ let expected =
96
+ match Uuidx. of_string expected_as_string with
97
+ | Some uuid ->
98
+ uuid
99
+ | None ->
100
+ Alcotest. fail
101
+ (Printf. sprintf " Couldn't convert to UUID: %s" expected_as_string)
102
+ in
103
+ let test () =
104
+ let result = Uuidx. make_v7_uuid_from_parts t 0L in
105
+ Alcotest. (check @@ uuid_testable) " make UUIDv7" expected result
106
+ in
107
+ (expected_as_string, [(" Make UUIDv7 from time" , `Quick , test)])
108
+
109
+ let uuid_v7_bytes_tests (rand_b , expected_as_string ) =
110
+ let expected =
111
+ match Uuidx. of_string expected_as_string with
112
+ | Some uuid ->
113
+ uuid
114
+ | None ->
115
+ Alcotest. fail
116
+ (Printf. sprintf " Couldn't convert to UUID: %s" expected_as_string)
117
+ in
118
+ let test () =
119
+ let result = Uuidx. make_v7_uuid_from_parts 0L rand_b in
120
+ Alcotest. (check @@ uuid_testable) " make UUIDv7" expected result
121
+ in
122
+ (expected_as_string, [(" Make UUIDv7 from bytes" , `Quick , test)])
123
+
54
124
let string_roundtrip_tests testing_string =
55
125
let testing_uuid =
56
126
match Uuidx. of_string testing_string with
@@ -111,6 +181,8 @@ let regression_tests =
111
181
; List. map array_roundtrip_tests uuid_arrays
112
182
; List. map invalid_string_tests non_uuid_strings
113
183
; List. map invalid_array_tests non_uuid_arrays
184
+ ; List. map uuid_v7_time_tests uuid_v7_times
185
+ ; List. map uuid_v7_bytes_tests uuid_v7_bytes
114
186
]
115
187
116
188
let () = Alcotest. run " Uuid" regression_tests
0 commit comments