Skip to content

Commit

Permalink
[10.x] Add ulid testing helpers (#48276)
Browse files Browse the repository at this point in the history
* add ulid testing helpers

* fix code style
  • Loading branch information
Jasonej authored Sep 4, 2023
1 parent ae93199 commit c02a064
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 0 deletions.
89 changes: 89 additions & 0 deletions src/Illuminate/Support/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ class Str
*/
protected static $uuidFactory;

/**
* The callback that should be used to generate ULIDs.
*
* @var callable|null
*/
protected static $ulidFactory;

/**
* The callback that should be used to generate random strings.
*
Expand Down Expand Up @@ -1543,13 +1550,95 @@ public static function createUuidsNormally()
*/
public static function ulid($time = null)
{
if (static::$ulidFactory) {
return call_user_func(static::$ulidFactory);
}

if ($time === null) {
return new Ulid();
}

return new Ulid(Ulid::generate($time));
}

/**
* Indicate that ULIDs should be created normally and not using a custom factory.
*
* @return void
*/
public static function createUlidsNormally()
{
static::$ulidFactory = null;
}

/**
* Set the callable that will be used to generate ULIDs.
*
* @param callable|null $factory
* @return void
*/
public static function createUlidsUsing(callable $factory = null)
{
static::$ulidFactory = $factory;
}

/**
* Set the sequence that will be used to generate ULIDs.
*
* @param array $sequence
* @param callable|null $whenMissing
* @return void
*/
public static function createUlidsUsingSequence(array $sequence, $whenMissing = null)
{
$next = 0;

$whenMissing ??= function () use (&$next) {
$factoryCache = static::$ulidFactory;

static::$ulidFactory = null;

$ulid = static::ulid();

static::$ulidFactory = $factoryCache;

$next++;

return $ulid;
};

static::createUlidsUsing(function () use (&$next, $sequence, $whenMissing) {
if (array_key_exists($next, $sequence)) {
return $sequence[$next++];
}

return $whenMissing();
});
}

/**
* Always return the same ULID when generating new ULIDs.
*
* @param Closure|null $callback
* @return Ulid
*/
public static function freezeUlids(Closure $callback = null)
{
$ulid = Str::ulid();

Str::createUlidsUsing(fn () => $ulid);

if ($callback !== null) {
try {
$callback($ulid);
} finally {
Str::createUlidsNormally();
}
}

return $ulid;
}

/**
* Remove all strings from the casing caches.
*
Expand Down
105 changes: 105 additions & 0 deletions tests/Support/SupportStrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,111 @@ public function testItCanSpecifyAFallbackForASequence()
}
}

public function testItCanFreezeUlids()
{
$this->assertNotSame((string) Str::ulid(), (string) Str::ulid());
$this->assertNotSame(Str::ulid(), Str::ulid());

$ulid = Str::freezeUlids();

$this->assertSame($ulid, Str::ulid());
$this->assertSame(Str::ulid(), Str::ulid());
$this->assertSame((string) $ulid, (string) Str::ulid());
$this->assertSame((string) Str::ulid(), (string) Str::ulid());

Str::createUlidsNormally();

$this->assertNotSame(Str::ulid(), Str::ulid());
$this->assertNotSame((string) Str::ulid(), (string) Str::ulid());
}

public function testItCanFreezeUlidsInAClosure()
{
$ulids = [];

$ulid = Str::freezeUlids(function ($ulid) use (&$ulids) {
$ulids[] = $ulid;
$ulids[] = Str::ulid();
$ulids[] = Str::ulid();
});

$this->assertSame($ulid, $ulids[0]);
$this->assertSame((string) $ulid, (string) $ulids[0]);
$this->assertSame((string) $ulids[0], (string) $ulids[1]);
$this->assertSame($ulids[0], $ulids[1]);
$this->assertSame((string) $ulids[0], (string) $ulids[1]);
$this->assertSame($ulids[1], $ulids[2]);
$this->assertSame((string) $ulids[1], (string) $ulids[2]);
$this->assertNotSame(Str::ulid(), Str::ulid());
$this->assertNotSame((string) Str::ulid(), (string) Str::ulid());

Str::createUlidsNormally();
}

public function testItCreatesUlidsNormallyAfterFailureWithinFreezeMethod()
{
try {
Str::freezeUlids(function () {
Str::createUlidsUsing(fn () => Str::of('1234'));
$this->assertSame('1234', (string) Str::ulid());
throw new \Exception('Something failed');
});
} catch (\Exception) {
$this->assertNotSame('1234', (string) Str::ulid());
}
}

public function testItCanSpecifyASequenceOfUlidsToUtilise()
{
Str::createUlidsUsingSequence([
0 => ($zeroth = Str::ulid()),
1 => ($first = Str::ulid()),
// just generate a random one here...
3 => ($third = Str::ulid()),
// continue to generate random ulids...
]);

$retrieved = Str::ulid();
$this->assertSame($zeroth, $retrieved);
$this->assertSame((string) $zeroth, (string) $retrieved);

$retrieved = Str::ulid();
$this->assertSame($first, $retrieved);
$this->assertSame((string) $first, (string) $retrieved);

$retrieved = Str::ulid();
$this->assertFalse(in_array($retrieved, [$zeroth, $first, $third], true));
$this->assertFalse(in_array((string) $retrieved, [(string) $zeroth, (string) $first, (string) $third], true));

$retrieved = Str::ulid();
$this->assertSame($third, $retrieved);
$this->assertSame((string) $third, (string) $retrieved);

$retrieved = Str::ulid();
$this->assertFalse(in_array($retrieved, [$zeroth, $first, $third], true));
$this->assertFalse(in_array((string) $retrieved, [(string) $zeroth, (string) $first, (string) $third], true));

Str::createUlidsNormally();
}

public function testItCanSpecifyAFallbackForAUlidSequence()
{
Str::createUlidsUsingSequence(
[Str::ulid(), Str::ulid()],
fn () => throw new Exception('Out of Ulids'),
);
Str::ulid();
Str::ulid();

try {
$this->expectExceptionMessage('Out of Ulids');
Str::ulid();
$this->fail();
} finally {
Str::createUlidsNormally();
}
}

public function testPasswordCreation()
{
$this->assertTrue(strlen(Str::password()) === 32);
Expand Down

0 comments on commit c02a064

Please sign in to comment.