UuidV2Test.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. declare(strict_types=1);
  3. namespace Ramsey\Uuid\Test\Rfc4122;
  4. use DateTimeInterface;
  5. use Mockery;
  6. use Ramsey\Uuid\Codec\CodecInterface;
  7. use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
  8. use Ramsey\Uuid\Converter\NumberConverterInterface;
  9. use Ramsey\Uuid\Converter\Time\GenericTimeConverter;
  10. use Ramsey\Uuid\Converter\TimeConverterInterface;
  11. use Ramsey\Uuid\Exception\InvalidArgumentException;
  12. use Ramsey\Uuid\Generator\DceSecurityGenerator;
  13. use Ramsey\Uuid\Generator\DefaultTimeGenerator;
  14. use Ramsey\Uuid\Math\BrickMathCalculator;
  15. use Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider;
  16. use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
  17. use Ramsey\Uuid\Provider\Time\FixedTimeProvider;
  18. use Ramsey\Uuid\Rfc4122\FieldsInterface;
  19. use Ramsey\Uuid\Rfc4122\UuidV2;
  20. use Ramsey\Uuid\Test\TestCase;
  21. use Ramsey\Uuid\Type\Hexadecimal;
  22. use Ramsey\Uuid\Type\Integer;
  23. use Ramsey\Uuid\Type\Time;
  24. use Ramsey\Uuid\Uuid;
  25. use Ramsey\Uuid\UuidFactory;
  26. use const PHP_VERSION_ID;
  27. class UuidV2Test extends TestCase
  28. {
  29. /**
  30. * @dataProvider provideTestVersions
  31. */
  32. public function testConstructorThrowsExceptionWhenFieldsAreNotValidForType(int $version): void
  33. {
  34. $fields = Mockery::mock(FieldsInterface::class, [
  35. 'getVersion' => $version,
  36. ]);
  37. $numberConverter = Mockery::mock(NumberConverterInterface::class);
  38. $codec = Mockery::mock(CodecInterface::class);
  39. $timeConverter = Mockery::mock(TimeConverterInterface::class);
  40. $this->expectException(InvalidArgumentException::class);
  41. $this->expectExceptionMessage(
  42. 'Fields used to create a UuidV2 must represent a '
  43. . 'version 2 (DCE Security) UUID'
  44. );
  45. new UuidV2($fields, $numberConverter, $codec, $timeConverter);
  46. }
  47. /**
  48. * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification
  49. */
  50. public function provideTestVersions(): array
  51. {
  52. return [
  53. ['version' => 0],
  54. ['version' => 1],
  55. ['version' => 3],
  56. ['version' => 4],
  57. ['version' => 5],
  58. ['version' => 6],
  59. ['version' => 7],
  60. ['version' => 8],
  61. ['version' => 9],
  62. ];
  63. }
  64. /**
  65. * @dataProvider provideLocalDomainAndIdentifierForTests
  66. */
  67. public function testGetLocalDomainAndIdentifier(
  68. int $domain,
  69. Integer $identifier,
  70. Time $time,
  71. int $expectedDomain,
  72. string $expectedDomainName,
  73. string $expectedIdentifier,
  74. string $expectedTimestamp,
  75. string $expectedTime
  76. ): void {
  77. $calculator = new BrickMathCalculator();
  78. $genericConverter = new GenericTimeConverter($calculator);
  79. $numberConverter = new GenericNumberConverter($calculator);
  80. $nodeProvider = new StaticNodeProvider(new Hexadecimal('1234567890ab'));
  81. $timeProvider = new FixedTimeProvider($time);
  82. $timeGenerator = new DefaultTimeGenerator($nodeProvider, $genericConverter, $timeProvider);
  83. $dceProvider = new SystemDceSecurityProvider();
  84. $dceGenerator = new DceSecurityGenerator($numberConverter, $timeGenerator, $dceProvider);
  85. $factory = new UuidFactory();
  86. $factory->setTimeGenerator($timeGenerator);
  87. $factory->setDceSecurityGenerator($dceGenerator);
  88. /** @var UuidV2 $uuid */
  89. $uuid = $factory->uuid2($domain, $identifier);
  90. /** @var FieldsInterface $fields */
  91. $fields = $uuid->getFields();
  92. $this->assertSame($expectedDomain, $uuid->getLocalDomain());
  93. $this->assertSame($expectedDomainName, $uuid->getLocalDomainName());
  94. $this->assertInstanceOf(Integer::class, $uuid->getLocalIdentifier());
  95. $this->assertSame($expectedIdentifier, $uuid->getLocalIdentifier()->toString());
  96. $this->assertSame($expectedTimestamp, $fields->getTimestamp()->toString());
  97. $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime());
  98. $this->assertSame($expectedTime, $uuid->getDateTime()->format('U.u'));
  99. $this->assertSame('1334567890ab', $fields->getNode()->toString());
  100. }
  101. /**
  102. * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification
  103. */
  104. public function provideLocalDomainAndIdentifierForTests(): array
  105. {
  106. // https://github.com/php/php-src/issues/7758
  107. $isGH7758Fixed = PHP_VERSION_ID >= 80107;
  108. return [
  109. [
  110. 'domain' => Uuid::DCE_DOMAIN_PERSON,
  111. 'identifier' => new Integer('12345678'),
  112. 'time' => new Time(0, 0),
  113. 'expectedDomain' => 0,
  114. 'expectedDomainName' => 'person',
  115. 'expectedIdentifier' => '12345678',
  116. 'expectedTimestamp' => '1b21dd200000000',
  117. 'expectedTime' => $isGH7758Fixed ? '-33.276237' : '-32.723763',
  118. ],
  119. [
  120. 'domain' => Uuid::DCE_DOMAIN_GROUP,
  121. 'identifier' => new Integer('87654321'),
  122. 'time' => new Time(0, 0),
  123. 'expectedDomain' => 1,
  124. 'expectedDomainName' => 'group',
  125. 'expectedIdentifier' => '87654321',
  126. 'expectedTimestamp' => '1b21dd200000000',
  127. 'expectedTime' => $isGH7758Fixed ? '-33.276237' : '-32.723763',
  128. ],
  129. [
  130. 'domain' => Uuid::DCE_DOMAIN_ORG,
  131. 'identifier' => new Integer('1'),
  132. 'time' => new Time(0, 0),
  133. 'expectedDomain' => 2,
  134. 'expectedDomainName' => 'org',
  135. 'expectedIdentifier' => '1',
  136. 'expectedTimestamp' => '1b21dd200000000',
  137. 'expectedTime' => $isGH7758Fixed ? '-33.276237' : '-32.723763',
  138. ],
  139. [
  140. 'domain' => Uuid::DCE_DOMAIN_PERSON,
  141. 'identifier' => new Integer('0'),
  142. 'time' => new Time(1583208664, 444109),
  143. 'expectedDomain' => 0,
  144. 'expectedDomainName' => 'person',
  145. 'expectedIdentifier' => '0',
  146. 'expectedTimestamp' => '1ea5d0500000000',
  147. 'expectedTime' => '1583208664.444109',
  148. ],
  149. [
  150. 'domain' => Uuid::DCE_DOMAIN_PERSON,
  151. 'identifier' => new Integer('2147483647'),
  152. 'time' => new Time(1583208879, 500000),
  153. 'expectedDomain' => 0,
  154. 'expectedDomainName' => 'person',
  155. 'expectedIdentifier' => '2147483647',
  156. // This time is the same as in the previous test because of the
  157. // loss of precision by setting the lowest 32 bits to zeros.
  158. 'expectedTimestamp' => '1ea5d0500000000',
  159. 'expectedTime' => '1583208664.444109',
  160. ],
  161. [
  162. 'domain' => Uuid::DCE_DOMAIN_PERSON,
  163. 'identifier' => new Integer('4294967295'),
  164. 'time' => new Time(1583208879, 500000),
  165. 'expectedDomain' => 0,
  166. 'expectedDomainName' => 'person',
  167. 'expectedIdentifier' => '4294967295',
  168. // This time is the same as in the previous test because of the
  169. // loss of precision by setting the lowest 32 bits to zeros.
  170. 'expectedTimestamp' => '1ea5d0500000000',
  171. 'expectedTime' => '1583208664.444109',
  172. ],
  173. [
  174. 'domain' => Uuid::DCE_DOMAIN_PERSON,
  175. 'identifier' => new Integer('4294967295'),
  176. 'time' => new Time(1583209093, 940838),
  177. 'expectedDomain' => 0,
  178. 'expectedDomainName' => 'person',
  179. 'expectedIdentifier' => '4294967295',
  180. // This time is the same as in the previous test because of the
  181. // loss of precision by setting the lowest 32 bits to zeros.
  182. 'expectedTimestamp' => '1ea5d0500000000',
  183. 'expectedTime' => '1583208664.444109',
  184. ],
  185. [
  186. 'domain' => Uuid::DCE_DOMAIN_PERSON,
  187. 'identifier' => new Integer('4294967295'),
  188. 'time' => new Time(1583209093, 940839),
  189. 'expectedDomain' => 0,
  190. 'expectedDomainName' => 'person',
  191. 'expectedIdentifier' => '4294967295',
  192. 'expectedTimestamp' => '1ea5d0600000000',
  193. 'expectedTime' => '1583209093.940838',
  194. ],
  195. ];
  196. }
  197. }