Skip to content

Commit f1ad046

Browse files
authored
[9.x] Add additional uuid testing helpers (#42619)
* add uuid testing helpers * allow devs to handle empty sequences * cleanup in case * docblocks
1 parent ff5c52b commit f1ad046

File tree

2 files changed

+146
-1
lines changed

2 files changed

+146
-1
lines changed

src/Illuminate/Support/Str.php

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Illuminate\Support;
44

5+
use Closure;
56
use Illuminate\Support\Traits\Macroable;
67
use JsonException;
78
use League\CommonMark\GithubFlavoredMarkdownConverter;
@@ -39,7 +40,7 @@ class Str
3940
/**
4041
* The callback that should be used to generate UUIDs.
4142
*
42-
* @var callable
43+
* @var callable|null
4344
*/
4445
protected static $uuidFactory;
4546

@@ -1112,6 +1113,61 @@ public static function createUuidsUsing(callable $factory = null)
11121113
static::$uuidFactory = $factory;
11131114
}
11141115

1116+
/**
1117+
* Set the sequence that will be used to generate UUIDs.
1118+
*
1119+
* @param array $sequence
1120+
* @param callable|null $whenMissing
1121+
* @return void
1122+
*/
1123+
public static function createUuidsUsingSequence(array $sequence, $whenMissing = null)
1124+
{
1125+
$next = 0;
1126+
1127+
$whenMissing ??= function () use (&$next) {
1128+
$factoryCache = static::$uuidFactory;
1129+
1130+
static::$uuidFactory = null;
1131+
1132+
$uuid = static::uuid();
1133+
1134+
static::$uuidFactory = $factoryCache;
1135+
1136+
$next++;
1137+
1138+
return $uuid;
1139+
};
1140+
1141+
static::createUuidsUsing(function () use (&$next, $sequence, $whenMissing) {
1142+
if (array_key_exists($next, $sequence)) {
1143+
return $sequence[$next++];
1144+
}
1145+
1146+
return $whenMissing();
1147+
});
1148+
}
1149+
1150+
/**
1151+
* Always return the same UUID when generating new UUIDs.
1152+
*
1153+
* @param \Closure|null $callback
1154+
* @return \Ramsey\Uuid\UuidInterface
1155+
*/
1156+
public static function freezeUuids(Closure $callback = null)
1157+
{
1158+
$uuid = Str::uuid();
1159+
1160+
Str::createUuidsUsing(fn () => $uuid);
1161+
1162+
if ($callback !== null) {
1163+
$callback($uuid);
1164+
1165+
Str::createUuidsNormally();
1166+
}
1167+
1168+
return $uuid;
1169+
}
1170+
11151171
/**
11161172
* Indicate that UUIDs should be created normally and not using a custom factory.
11171173
*

tests/Support/SupportStrTest.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,95 @@ public function testTransliterateStrict(string $value, string $expected): void
891891
{
892892
$this->assertSame($expected, Str::transliterate($value, '?', true));
893893
}
894+
895+
public function testItCanFreezeUuids()
896+
{
897+
$this->assertNotSame((string) Str::uuid(), (string) Str::uuid());
898+
$this->assertNotSame(Str::uuid(), Str::uuid());
899+
900+
$uuid = Str::freezeUuids();
901+
902+
$this->assertSame($uuid, Str::uuid());
903+
$this->assertSame(Str::uuid(), Str::uuid());
904+
$this->assertSame((string) $uuid, (string) Str::uuid());
905+
$this->assertSame((string) Str::uuid(), (string) Str::uuid());
906+
907+
Str::createUuidsNormally();
908+
909+
$this->assertNotSame(Str::uuid(), Str::uuid());
910+
$this->assertNotSame((string) Str::uuid(), (string) Str::uuid());
911+
}
912+
913+
public function testItCanFreezeUuidsInAClosure()
914+
{
915+
$uuids = [];
916+
917+
$uuid = Str::freezeUuids(function ($uuid) use (&$uuids) {
918+
$uuids[] = $uuid;
919+
$uuids[] = Str::uuid();
920+
$uuids[] = Str::uuid();
921+
});
922+
923+
$this->assertSame($uuid, $uuids[0]);
924+
$this->assertSame((string) $uuid, (string) $uuids[0]);
925+
$this->assertSame((string) $uuids[0], (string) $uuids[1]);
926+
$this->assertSame($uuids[0], $uuids[1]);
927+
$this->assertSame((string) $uuids[0], (string) $uuids[1]);
928+
$this->assertSame($uuids[1], $uuids[2]);
929+
$this->assertSame((string) $uuids[1], (string) $uuids[2]);
930+
$this->assertNotSame(Str::uuid(), Str::uuid());
931+
$this->assertNotSame((string) Str::uuid(), (string) Str::uuid());
932+
933+
Str::createUuidsNormally();
934+
}
935+
936+
public function testItCanSpecifyASquenceOfUuidsToUtilise()
937+
{
938+
Str::createUuidsUsingSequence([
939+
0 => ($zeroth = Str::uuid()),
940+
1 => ($first = Str::uuid()),
941+
// just generate a random one here...
942+
3 => ($third = Str::uuid()),
943+
// continue to generate random uuids...
944+
]);
945+
946+
$retrieved = Str::uuid();
947+
$this->assertSame($zeroth, $retrieved);
948+
$this->assertSame((string) $zeroth, (string) $retrieved);
949+
950+
$retrieved = Str::uuid();
951+
$this->assertSame($first, $retrieved);
952+
$this->assertSame((string) $first, (string) $retrieved);
953+
954+
$retrieved = Str::uuid();
955+
$this->assertFalse(in_array($retrieved, [$zeroth, $first, $third], true));
956+
$this->assertFalse(in_array((string) $retrieved, [(string) $zeroth, (string) $first, (string) $third], true));
957+
958+
$retrieved = Str::uuid();
959+
$this->assertSame($third, $retrieved);
960+
$this->assertSame((string) $third, (string) $retrieved);
961+
962+
$retrieved = Str::uuid();
963+
$this->assertFalse(in_array($retrieved, [$zeroth, $first, $third], true));
964+
$this->assertFalse(in_array((string) $retrieved, [(string) $zeroth, (string) $first, (string) $third], true));
965+
966+
Str::createUuidsNormally();
967+
}
968+
969+
public function testItCanSpecifyAFallbackForASequence()
970+
{
971+
Str::createUuidsUsingSequence([Str::uuid(), Str::uuid()], fn () => throw new \Exception('Out of Uuids.'));
972+
Str::uuid();
973+
Str::uuid();
974+
975+
try {
976+
$this->expectExceptionMessage('Out of Uuids.');
977+
Str::uuid();
978+
$this->fail();
979+
} finally {
980+
Str::createUuidsNormally();
981+
}
982+
}
894983
}
895984

896985
class StringableObjectStub

0 commit comments

Comments
 (0)