CombGeneratorTest.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <?php
  2. declare(strict_types=1);
  3. namespace Ramsey\Uuid\Test\Generator;
  4. use Exception;
  5. use PHPUnit\Framework\MockObject\MockObject;
  6. use Ramsey\Uuid\Converter\NumberConverterInterface;
  7. use Ramsey\Uuid\Exception\InvalidArgumentException;
  8. use Ramsey\Uuid\Generator\CombGenerator;
  9. use Ramsey\Uuid\Generator\RandomGeneratorInterface;
  10. use Ramsey\Uuid\Test\TestCase;
  11. use function bin2hex;
  12. use function dechex;
  13. use function hex2bin;
  14. use function str_pad;
  15. use const STR_PAD_LEFT;
  16. class CombGeneratorTest extends TestCase
  17. {
  18. /**
  19. * @var int
  20. */
  21. private $timestampBytes = 6;
  22. public function testGenerateUsesRandomGeneratorWithLengthMinusTimestampBytes(): void
  23. {
  24. $length = 10;
  25. $expectedLength = $length - $this->timestampBytes;
  26. /** @var MockObject & RandomGeneratorInterface $randomGenerator */
  27. $randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
  28. $randomGenerator->expects($this->once())
  29. ->method('generate')
  30. ->with($expectedLength);
  31. /** @var MockObject & NumberConverterInterface $converter */
  32. $converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
  33. $generator = new CombGenerator($randomGenerator, $converter);
  34. $generator->generate($length);
  35. }
  36. public function testGenerateCalculatesPaddedHexStringFromCurrentTimestamp(): void
  37. {
  38. /** @var MockObject & RandomGeneratorInterface $randomGenerator */
  39. $randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
  40. /** @var MockObject & NumberConverterInterface $converter */
  41. $converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
  42. $converter->expects($this->once())
  43. ->method('toHex')
  44. ->with($this->isType('string'));
  45. $generator = new CombGenerator($randomGenerator, $converter);
  46. $generator->generate(10);
  47. }
  48. public function testGenerateReturnsBinaryStringCreatedFromGeneratorAndConverter(): void
  49. {
  50. $length = 20;
  51. $hash = dechex(1234567891);
  52. $timeHash = dechex(1458147405);
  53. /** @var MockObject & RandomGeneratorInterface $randomGenerator */
  54. $randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
  55. $randomGenerator->method('generate')
  56. ->with($length - $this->timestampBytes)
  57. ->willReturn($hash);
  58. /** @var MockObject & NumberConverterInterface $converter */
  59. $converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
  60. $converter->method('toHex')
  61. ->with($this->isType('string'))
  62. ->willReturn($timeHash);
  63. $time = str_pad($timeHash, 12, '0', STR_PAD_LEFT);
  64. $expected = hex2bin(str_pad(bin2hex($hash), $length - $this->timestampBytes, '0')) . hex2bin($time);
  65. $generator = new CombGenerator($randomGenerator, $converter);
  66. $returned = $generator->generate($length);
  67. $this->assertIsString($returned);
  68. $this->assertSame($expected, $returned);
  69. }
  70. /**
  71. * @return array<array{0: int}>
  72. */
  73. public function lengthLessThanSix(): array
  74. {
  75. return [[0], [1], [2], [3], [4], [5]];
  76. }
  77. /**
  78. * @param int<1, max> $length
  79. *
  80. * @throws Exception
  81. *
  82. * @dataProvider lengthLessThanSix
  83. */
  84. public function testGenerateWithLessThanTimestampBytesThrowsException(int $length): void
  85. {
  86. /** @var MockObject & RandomGeneratorInterface $randomGenerator */
  87. $randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
  88. /** @var MockObject & NumberConverterInterface $converter */
  89. $converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
  90. $generator = new CombGenerator($randomGenerator, $converter);
  91. $this->expectException(InvalidArgumentException::class);
  92. $generator->generate($length);
  93. }
  94. /**
  95. * @throws Exception
  96. */
  97. public function testGenerateWithOddNumberOverTimestampBytesCausesError(): void
  98. {
  99. /** @var MockObject & RandomGeneratorInterface $randomGenerator */
  100. $randomGenerator = $this->getMockBuilder(RandomGeneratorInterface::class)->getMock();
  101. /** @var MockObject & NumberConverterInterface $converter */
  102. $converter = $this->getMockBuilder(NumberConverterInterface::class)->getMock();
  103. $generator = new CombGenerator($randomGenerator, $converter);
  104. $this->expectError();
  105. $generator->generate(7);
  106. }
  107. }