Files
php-uuid/tests/Generator/CombGeneratorTest.php
T
Marco Pivetta a252f29847 Import used functions and constants via use statement to disallow ambiguity for compiler/static-analysis
As documented in https://wiki.php.net/rfc/use_global_elements, the engine (by default) does a local namespace
lookup, then falls back to global namespace when first calling a global function referenced in namespaced code,
unless that function is referenced via fully qualified name (FQN).

By using the FQN, the actual symbol can be looked up at compile-time, both by the PHP engine and by static analysis
tooling, allowing for compiler (in particular) optimizations to replace known hot-path functions with specialized opcodes.

Sadly, no actual benchmark at hand: the improvements can be minimal or massive, depending on where this library is
used (tight loops being most relevant).
2020-02-03 13:15:35 -06:00

134 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
namespace Ramsey\Uuid\Test\Generator;
use Exception;
use PHPUnit\Framework\Error\Error as PHPUnitError;
use PHPUnit\Framework\MockObject\MockObject;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Generator\CombGenerator;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Test\TestCase;
use function bin2hex;
use function dechex;
use function hex2bin;
use function str_pad;
use const STR_PAD_LEFT;
class CombGeneratorTest extends TestCase
{
/**
* @var int
*/
private $timestampBytes = 6;
public function testGenerateUsesRandomGeneratorWithLengthMinusTimestampBytes(): void
{
$length = 10;
$expectedLength = $length - $this->timestampBytes;
/** @var MockObject & RandomGeneratorInterface $randomGenerator */
$randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
$randomGenerator->expects($this->once())
->method('generate')
->with($expectedLength);
/** @var MockObject & NumberConverterInterface $converter */
$converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
$generator = new CombGenerator($randomGenerator, $converter);
$generator->generate($length);
}
public function testGenerateCalculatesPaddedHexStringFromCurrentTimestamp(): void
{
/** @var MockObject & RandomGeneratorInterface $randomGenerator */
$randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
/** @var MockObject & NumberConverterInterface $converter */
$converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
$converter->expects($this->once())
->method('toHex')
->with($this->isType('string'));
$generator = new CombGenerator($randomGenerator, $converter);
$generator->generate(10);
}
public function testGenerateReturnsBinaryStringCreatedFromGeneratorAndConverter(): void
{
$length = 20;
$hash = dechex(1234567891);
$timeHash = dechex(1458147405);
/** @var MockObject & RandomGeneratorInterface $randomGenerator */
$randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
$randomGenerator->method('generate')
->with($length - $this->timestampBytes)
->willReturn($hash);
/** @var MockObject & NumberConverterInterface $converter */
$converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
$converter->method('toHex')
->with($this->isType('string'))
->willReturn($timeHash);
$time = str_pad($timeHash, 12, '0', STR_PAD_LEFT);
$expected = hex2bin(str_pad(bin2hex($hash), $length - $this->timestampBytes, '0')) . hex2bin($time);
$generator = new CombGenerator($randomGenerator, $converter);
$returned = $generator->generate($length);
$this->assertIsString($returned);
$this->assertEquals($expected, $returned);
}
/**
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification
*/
public function lengthLessThanSix(): array
{
return [[0], [1], [2], [3], [4], [5]];
}
/**
* @throws Exception
*
* @dataProvider lengthLessThanSix
*/
public function testGenerateWithLessThanTimestampBytesThrowsException(int $length): void
{
/** @var MockObject & RandomGeneratorInterface $randomGenerator */
$randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
/** @var MockObject & NumberConverterInterface $converter */
$converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
$generator = new CombGenerator($randomGenerator, $converter);
$this->expectException(InvalidArgumentException::class);
$generator->generate($length);
}
/**
* @throws Exception
*/
public function testGenerateWithOddNumberOverTimestampBytesCausesError(): void
{
/** @var MockObject & RandomGeneratorInterface $randomGenerator */
$randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
/** @var MockObject & NumberConverterInterface $converter */
$converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
$generator = new CombGenerator($randomGenerator, $converter);
$this->expectException(PHPUnitError::class);
$generator->generate(7);
}
}