Skip to content

Commit be2cbf2

Browse files
committed
refactor(tests): improve unit tests
Signed-off-by: Alan Brault <alan.brault@visus.io>
1 parent 2298018 commit be2cbf2

File tree

1 file changed

+303
-10
lines changed

1 file changed

+303
-10
lines changed

tests/Cuid2Test.php

Lines changed: 303 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,121 @@
44

55
namespace Visus\Cuid2\Test;
66

7+
use Exception;
78
use OutOfRangeException;
89
use PHPUnit\Framework\TestCase;
910
use Visus\Cuid2\Cuid2;
1011

1112
class Cuid2Test extends TestCase
1213
{
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
1420
{
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+
}
1629

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+
}
1945

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);
2158
}
2259

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
2466
{
25-
$cuid = new Cuid2(10);
67+
$cuid = new Cuid2();
2668

27-
$result = strlen((string)$cuid) === 10 &&
28-
ctype_alnum((string)$cuid);
69+
$toString = $cuid->toString();
70+
$magicToString = (string)$cuid;
71+
$jsonSerialize = $cuid->jsonSerialize();
2972

30-
$this->assertTrue($result);
73+
$this->assertEquals($toString, $magicToString);
74+
$this->assertEquals($toString, $jsonSerialize);
3175
}
3276

77+
/**
78+
* Tests the constructor with a length of 24.
79+
*
80+
* @throws OutOfRangeException|Exception
81+
*/
3382
public function testConstructorThrowsOutOfRangeException(): void
3483
{
3584
$this->expectException(OutOfRangeException::class);
3685

3786
$_ = new Cuid2(48);
3887
}
3988

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+
*/
40122
public function testExplicitToString(): void
41123
{
42124
$cuid = new Cuid2();
@@ -49,6 +131,11 @@ public function testExplicitToString(): void
49131
$this->assertTrue($result);
50132
}
51133

134+
/**
135+
* Tests the implicit string conversion of Cuid2.
136+
*
137+
* @throws OutOfRangeException|Exception
138+
*/
52139
public function testImplicitToString(): void
53140
{
54141
$cuid = new Cuid2();
@@ -63,4 +150,210 @@ public function testImplicitToString(): void
63150

64151
$this->assertTrue($result);
65152
}
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+
}
66359
}

0 commit comments

Comments
 (0)