4
4
5
5
namespace Visus \Cuid2 \Test ;
6
6
7
+ use Exception ;
7
8
use OutOfRangeException ;
8
9
use PHPUnit \Framework \TestCase ;
9
10
use Visus \Cuid2 \Cuid2 ;
10
11
11
12
class Cuid2Test extends TestCase
12
13
{
13
- public function testDefaultConstructor (): void
14
+ /**
15
+ * Provides invalid lengths for CUID2.
16
+ *
17
+ * @return array<string, array<int>>
18
+ */
19
+ public static function invalidLengthProvider (): array
14
20
{
15
- $ cuid = new Cuid2 ();
21
+ return [
22
+ 'too small ' => [3 ],
23
+ 'negative ' => [-1 ],
24
+ 'zero ' => [0 ],
25
+ 'too large ' => [33 ],
26
+ 'way too large ' => [100 ],
27
+ ];
28
+ }
16
29
17
- $ result = strlen ((string )$ cuid ) === 24 &&
18
- ctype_alnum ((string )$ cuid );
30
+ /**
31
+ * Provides valid lengths for CUID2.
32
+ *
33
+ * @return array<string, array<int>>
34
+ */
35
+ public static function validLengthProvider (): array
36
+ {
37
+ return [
38
+ 'minimum length ' => [4 ],
39
+ 'small length ' => [8 ],
40
+ 'medium length ' => [16 ],
41
+ 'default length ' => [24 ],
42
+ 'maximum length ' => [32 ],
43
+ ];
44
+ }
19
45
20
- $ this ->assertTrue ($ result );
46
+ /**
47
+ * Tests that the generated CUID2 contains only base36 characters (0-9, a-z).
48
+ *
49
+ * @throws OutOfRangeException|Exception
50
+ */
51
+ public function testBase36Characters (): void
52
+ {
53
+ $ cuid = new Cuid2 ();
54
+ $ result = (string )$ cuid ;
55
+
56
+ // Should only contain characters from 0-9 and a-z
57
+ $ this ->assertMatchesRegularExpression ('/^[0-9a-z]+$/ ' , $ result );
21
58
}
22
59
23
- public function testVariableLengthConstructor (): void
60
+ /**
61
+ * Tests that the string representation of CUID2 is consistent across methods.
62
+ *
63
+ * @throws OutOfRangeException|Exception
64
+ */
65
+ public function testConsistentStringRepresentation (): void
24
66
{
25
- $ cuid = new Cuid2 (10 );
67
+ $ cuid = new Cuid2 ();
26
68
27
- $ result = strlen ((string )$ cuid ) === 10 &&
28
- ctype_alnum ((string )$ cuid );
69
+ $ toString = $ cuid ->toString ();
70
+ $ magicToString = (string )$ cuid ;
71
+ $ jsonSerialize = $ cuid ->jsonSerialize ();
29
72
30
- $ this ->assertTrue ($ result );
73
+ $ this ->assertEquals ($ toString , $ magicToString );
74
+ $ this ->assertEquals ($ toString , $ jsonSerialize );
31
75
}
32
76
77
+ /**
78
+ * Tests the constructor with a length of 24.
79
+ *
80
+ * @throws OutOfRangeException|Exception
81
+ */
33
82
public function testConstructorThrowsOutOfRangeException (): void
34
83
{
35
84
$ this ->expectException (OutOfRangeException::class);
36
85
37
86
$ _ = new Cuid2 (48 );
38
87
}
39
88
89
+ /**
90
+ * Tests the default constructor of Cuid2.
91
+ *
92
+ * @throws OutOfRangeException
93
+ */
94
+ public function testDefaultConstructor (): void
95
+ {
96
+ $ cuid = new Cuid2 ();
97
+
98
+ $ result = strlen ((string )$ cuid ) === 24 &&
99
+ ctype_alnum ((string )$ cuid );
100
+
101
+ $ this ->assertTrue ($ result );
102
+ }
103
+
104
+ /**
105
+ * Tests that different instances of Cuid2 generate different values.
106
+ *
107
+ * @throws OutOfRangeException|Exception
108
+ */
109
+ public function testDifferentInstancesHaveDifferentValues (): void
110
+ {
111
+ $ cuid1 = new Cuid2 ();
112
+ $ cuid2 = new Cuid2 ();
113
+
114
+ $ this ->assertNotEquals ((string )$ cuid1 , (string )$ cuid2 );
115
+ }
116
+
117
+ /**
118
+ * Tests the constructor with a length of 4.
119
+ *
120
+ * @throws OutOfRangeException|Exception
121
+ */
40
122
public function testExplicitToString (): void
41
123
{
42
124
$ cuid = new Cuid2 ();
@@ -49,6 +131,11 @@ public function testExplicitToString(): void
49
131
$ this ->assertTrue ($ result );
50
132
}
51
133
134
+ /**
135
+ * Tests the implicit string conversion of Cuid2.
136
+ *
137
+ * @throws OutOfRangeException|Exception
138
+ */
52
139
public function testImplicitToString (): void
53
140
{
54
141
$ cuid = new Cuid2 ();
@@ -63,4 +150,210 @@ public function testImplicitToString(): void
63
150
64
151
$ this ->assertTrue ($ result );
65
152
}
153
+
154
+ /**
155
+ * @dataProvider invalidLengthProvider
156
+ * @throws Exception
157
+ */
158
+ public function testInvalidLengthThrowsException (int $ length ): void
159
+ {
160
+ $ this ->expectException (OutOfRangeException::class);
161
+ $ this ->expectExceptionMessage ("maxLength: cannot be less than 4 or greater than 32. " );
162
+
163
+ new Cuid2 ($ length );
164
+ }
165
+
166
+ /**
167
+ * Tests the JSON encoding of Cuid2.
168
+ *
169
+ * @throws OutOfRangeException|Exception
170
+ */
171
+ public function testJsonEncodeIntegration (): void
172
+ {
173
+ $ cuid = new Cuid2 ();
174
+ $ jsonString = json_encode ($ cuid );
175
+
176
+ $ this ->assertIsString ($ jsonString );
177
+ $ this ->assertStringStartsWith ('" ' , $ jsonString );
178
+ $ this ->assertStringEndsWith ('" ' , $ jsonString );
179
+
180
+ $ decoded = json_decode ($ jsonString , true );
181
+ $ this ->assertIsString ($ decoded );
182
+ $ this ->assertEquals (24 , strlen ($ decoded ));
183
+ }
184
+
185
+ /**
186
+ * Tests the JSON serialization of Cuid2.
187
+ *
188
+ * @throws OutOfRangeException|Exception
189
+ */
190
+ public function testJsonSerialize (): void
191
+ {
192
+ $ cuid = new Cuid2 ();
193
+ $ jsonValue = $ cuid ->jsonSerialize ();
194
+
195
+ $ this ->assertEquals (24 , strlen ($ jsonValue ));
196
+ $ this ->assertTrue (ctype_alnum ($ jsonValue ));
197
+ }
198
+
199
+ /**
200
+ * Tests that the length of the generated CUID2 matches the specified length.
201
+ *
202
+ * @throws OutOfRangeException|Exception
203
+ */
204
+ public function testLengthConsistencyAcrossInstances (): void
205
+ {
206
+ $ lengths = [4 , 8 , 12 , 16 , 20 , 24 , 28 , 32 ];
207
+
208
+ foreach ($ lengths as $ length ) {
209
+ $ cuid1 = new Cuid2 ($ length );
210
+ $ cuid2 = new Cuid2 ($ length );
211
+
212
+ $ this ->assertEquals ($ length , strlen ((string )$ cuid1 ));
213
+ $ this ->assertEquals ($ length , strlen ((string )$ cuid2 ));
214
+ $ this ->assertNotEquals ((string )$ cuid1 , (string )$ cuid2 );
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Tests the memory usage of CUID2 generation.
220
+ *
221
+ * This test checks that generating multiple CUID2 instances does not consume excessive memory.
222
+ *
223
+ * @throws OutOfRangeException|Exception
224
+ */
225
+ public function testMemoryUsage (): void
226
+ {
227
+ $ initialMemory = memory_get_usage ();
228
+
229
+ $ cuids = [];
230
+ for ($ i = 0 ; $ i < 100 ; $ i ++) {
231
+ $ cuids [] = new Cuid2 ();
232
+ }
233
+
234
+ $ finalMemory = memory_get_usage ();
235
+ $ memoryUsed = $ finalMemory - $ initialMemory ;
236
+
237
+ // Memory usage should be reasonable (adjust threshold as needed)
238
+ $ this ->assertLessThan (5 * 1024 * 1024 , $ memoryUsed , 'Memory usage should be reasonable ' );
239
+ }
240
+
241
+ /**
242
+ * Tests that multiple calls to the string representation return the same value.
243
+ *
244
+ * @throws OutOfRangeException|Exception
245
+ */
246
+ public function testMultipleCallsReturnSameValue (): void
247
+ {
248
+ $ cuid = new Cuid2 ();
249
+
250
+ $ first = $ cuid ->toString ();
251
+ $ second = $ cuid ->toString ();
252
+ $ third = (string )$ cuid ;
253
+ $ fourth = $ cuid ->jsonSerialize ();
254
+
255
+ $ this ->assertEquals ($ first , $ second );
256
+ $ this ->assertEquals ($ first , $ third );
257
+ $ this ->assertEquals ($ first , $ fourth );
258
+ }
259
+
260
+ /**
261
+ * Tests that the generated CUID2 does not contain any special characters.
262
+ *
263
+ * @throws OutOfRangeException|Exception
264
+ */
265
+ public function testNoSpecialCharacters (): void
266
+ {
267
+ $ cuid = new Cuid2 ();
268
+ $ result = (string )$ cuid ;
269
+
270
+ // Should not contain any special characters, spaces, or uppercase letters
271
+ $ this ->assertDoesNotMatchRegularExpression ('/[^0-9a-z]/ ' , $ result );
272
+ }
273
+
274
+ /**
275
+ * Tests the performance of CUID2 generation with multiple instances.
276
+ *
277
+ * @throws OutOfRangeException|Exception
278
+ */
279
+ public function testPerformanceWithMultipleInstances (): void
280
+ {
281
+ $ startTime = microtime (true );
282
+ $ count = 100 ;
283
+
284
+ for ($ i = 0 ; $ i < $ count ; $ i ++) {
285
+ $ cuid = new Cuid2 ();
286
+ $ result = (string )$ cuid ;
287
+ $ this ->assertNotEmpty ($ result );
288
+ }
289
+
290
+ $ endTime = microtime (true );
291
+ $ executionTime = $ endTime - $ startTime ;
292
+
293
+ // Should complete within reasonable time (adjust as needed)
294
+ $ this ->assertLessThan (5.0 , $ executionTime , 'CUID generation should be performant ' );
295
+ }
296
+
297
+ /**
298
+ * Tests that the prefix of CUID2 is a lowercase letter.
299
+ *
300
+ * @throws OutOfRangeException|Exception
301
+ */
302
+ public function testPrefixIsLowercaseLetter (): void
303
+ {
304
+ $ cuid = new Cuid2 ();
305
+ $ result = (string )$ cuid ;
306
+ $ firstChar = $ result [0 ];
307
+
308
+ $ this ->assertTrue (ctype_alpha ($ firstChar ));
309
+ $ this ->assertTrue (ctype_lower ($ firstChar ));
310
+ $ this ->assertGreaterThanOrEqual ('a ' , $ firstChar );
311
+ $ this ->assertLessThanOrEqual ('z ' , $ firstChar );
312
+ }
313
+
314
+ /**
315
+ * Tests the uniqueness of generated CUIDs.
316
+ *
317
+ * @throws OutOfRangeException|Exception
318
+ */
319
+ public function testUniqueness (): void
320
+ {
321
+ $ cuids = [];
322
+ $ count = 1000 ;
323
+
324
+ for ($ i = 0 ; $ i < $ count ; $ i ++) {
325
+ $ cuids [] = (string )new Cuid2 ();
326
+ }
327
+
328
+ $ uniqueCuids = array_unique ($ cuids );
329
+ $ this ->assertCount ($ count , $ uniqueCuids , 'All CUIDs should be unique ' );
330
+ }
331
+
332
+ /**
333
+ * @dataProvider validLengthProvider
334
+ * @throws Exception
335
+ */
336
+ public function testValidLengthRange (int $ length ): void
337
+ {
338
+ $ cuid = new Cuid2 ($ length );
339
+ $ result = (string )$ cuid ;
340
+
341
+ $ this ->assertEquals ($ length , strlen ($ result ));
342
+ $ this ->assertTrue (ctype_alnum ($ result ));
343
+ }
344
+
345
+ /**
346
+ * Tests the constructor with a variable length.
347
+ *
348
+ * @throws OutOfRangeException|Exception
349
+ */
350
+ public function testVariableLengthConstructor (): void
351
+ {
352
+ $ cuid = new Cuid2 (10 );
353
+
354
+ $ result = strlen ((string )$ cuid ) === 10 &&
355
+ ctype_alnum ((string )$ cuid );
356
+
357
+ $ this ->assertTrue ($ result );
358
+ }
66
359
}
0 commit comments