PeclUuidNameGeneratorTest.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. declare(strict_types=1);
  3. namespace Ramsey\Uuid\Test\Generator;
  4. use Ramsey\Uuid\BinaryUtils;
  5. use Ramsey\Uuid\Exception\NameException;
  6. use Ramsey\Uuid\Generator\PeclUuidNameGenerator;
  7. use Ramsey\Uuid\Test\TestCase;
  8. use Ramsey\Uuid\Uuid;
  9. use function hash;
  10. use function pack;
  11. use function substr;
  12. use function substr_replace;
  13. use function unpack;
  14. class PeclUuidNameGeneratorTest extends TestCase
  15. {
  16. /**
  17. * @param non-empty-string $ns
  18. *
  19. * @dataProvider provideNamesForHashingTest
  20. * @requires extension uuid
  21. */
  22. public function testPeclUuidNameGeneratorHashesName(string $ns, string $name, string $algorithm): void
  23. {
  24. $namespace = Uuid::fromString($ns);
  25. $version = $algorithm === 'md5' ? 3 : 5;
  26. $expectedBytes = substr(hash($algorithm, $namespace->getBytes() . $name, true), 0, 16);
  27. // Need to add the version and variant, since ext-uuid already includes
  28. // these in the values returned.
  29. /** @var array $unpackedTime */
  30. $unpackedTime = unpack('n*', substr($expectedBytes, 6, 2));
  31. $timeHi = (int) $unpackedTime[1];
  32. $timeHiAndVersion = pack('n*', BinaryUtils::applyVersion($timeHi, $version));
  33. /** @var array $unpackedClockSeq */
  34. $unpackedClockSeq = unpack('n*', substr($expectedBytes, 8, 2));
  35. $clockSeqHi = (int) $unpackedClockSeq[1];
  36. $clockSeqHiAndReserved = pack('n*', BinaryUtils::applyVariant($clockSeqHi));
  37. $expectedBytes = substr_replace($expectedBytes, $timeHiAndVersion, 6, 2);
  38. $expectedBytes = substr_replace($expectedBytes, $clockSeqHiAndReserved, 8, 2);
  39. $generator = new PeclUuidNameGenerator();
  40. $generatedBytes = $generator->generate($namespace, $name, $algorithm);
  41. $this->assertSame(
  42. $expectedBytes,
  43. $generatedBytes,
  44. 'Expected: ' . bin2hex($expectedBytes) . '; Received: ' . bin2hex($generatedBytes)
  45. );
  46. }
  47. /**
  48. * @return array<array{ns: string, name: string, algorithm: string}>
  49. */
  50. public function provideNamesForHashingTest(): array
  51. {
  52. return [
  53. [
  54. 'ns' => Uuid::NAMESPACE_URL,
  55. 'name' => 'https://example.com/foobar',
  56. 'algorithm' => 'md5',
  57. ],
  58. [
  59. 'ns' => Uuid::NAMESPACE_URL,
  60. 'name' => 'https://example.com/foobar',
  61. 'algorithm' => 'sha1',
  62. ],
  63. [
  64. 'ns' => Uuid::NAMESPACE_OID,
  65. 'name' => '1.3.6.1.4.1.343',
  66. 'algorithm' => 'sha1',
  67. ],
  68. [
  69. 'ns' => Uuid::NAMESPACE_OID,
  70. 'name' => '1.3.6.1.4.1.52627',
  71. 'algorithm' => 'md5',
  72. ],
  73. [
  74. 'ns' => 'd988ae29-674e-48e7-b93c-2825e2a96fbe',
  75. 'name' => 'foobar',
  76. 'algorithm' => 'sha1',
  77. ],
  78. ];
  79. }
  80. public function testGenerateThrowsException(): void
  81. {
  82. $namespace = Uuid::fromString('cd998804-c661-4264-822c-00cada75a87b');
  83. $generator = new PeclUuidNameGenerator();
  84. $this->expectException(NameException::class);
  85. $this->expectExceptionMessage(
  86. 'Unable to hash namespace and name with algorithm \'aBadAlgorithm\''
  87. );
  88. /** @phpstan-ignore-next-line */
  89. $generator->generate($namespace, 'a test name', 'aBadAlgorithm');
  90. }
  91. }