FallbackBuilderTest.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. declare(strict_types=1);
  3. namespace Ramsey\Uuid\Test\Builder;
  4. use DateTimeInterface;
  5. use Mockery;
  6. use Ramsey\Uuid\Builder\FallbackBuilder;
  7. use Ramsey\Uuid\Builder\UuidBuilderInterface;
  8. use Ramsey\Uuid\Codec\CodecInterface;
  9. use Ramsey\Uuid\Codec\StringCodec;
  10. use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
  11. use Ramsey\Uuid\Converter\Time\GenericTimeConverter;
  12. use Ramsey\Uuid\Converter\Time\PhpTimeConverter;
  13. use Ramsey\Uuid\Exception\BuilderNotFoundException;
  14. use Ramsey\Uuid\Exception\UnableToBuildUuidException;
  15. use Ramsey\Uuid\Guid\GuidBuilder;
  16. use Ramsey\Uuid\Math\BrickMathCalculator;
  17. use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
  18. use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
  19. use Ramsey\Uuid\Rfc4122\UuidV1;
  20. use Ramsey\Uuid\Rfc4122\UuidV2;
  21. use Ramsey\Uuid\Rfc4122\UuidV6;
  22. use Ramsey\Uuid\Test\TestCase;
  23. class FallbackBuilderTest extends TestCase
  24. {
  25. public function testBuildThrowsExceptionAfterAllConfiguredBuildersHaveErrored(): void
  26. {
  27. $codec = Mockery::mock(CodecInterface::class);
  28. $bytes = 'foobar';
  29. $builder1 = Mockery::mock(UuidBuilderInterface::class);
  30. $builder1
  31. ->shouldReceive('build')
  32. ->once()
  33. ->with($codec, $bytes)
  34. ->andThrow(UnableToBuildUuidException::class);
  35. $builder2 = Mockery::mock(UuidBuilderInterface::class);
  36. $builder2
  37. ->shouldReceive('build')
  38. ->once()
  39. ->with($codec, $bytes)
  40. ->andThrow(UnableToBuildUuidException::class);
  41. $builder3 = Mockery::mock(UuidBuilderInterface::class);
  42. $builder3
  43. ->shouldReceive('build')
  44. ->once()
  45. ->with($codec, $bytes)
  46. ->andThrow(UnableToBuildUuidException::class);
  47. $fallbackBuilder = new FallbackBuilder([$builder1, $builder2, $builder3]);
  48. $this->expectException(BuilderNotFoundException::class);
  49. $this->expectExceptionMessage(
  50. 'Could not find a suitable builder for the provided codec and fields'
  51. );
  52. $fallbackBuilder->build($codec, $bytes);
  53. }
  54. /**
  55. * @dataProvider provideBytes
  56. */
  57. public function testSerializationOfBuilderCollection(string $bytes): void
  58. {
  59. $calculator = new BrickMathCalculator();
  60. $genericNumberConverter = new GenericNumberConverter($calculator);
  61. $genericTimeConverter = new GenericTimeConverter($calculator);
  62. $phpTimeConverter = new PhpTimeConverter($calculator, $genericTimeConverter);
  63. // Use the GenericTimeConverter.
  64. $guidBuilder = new GuidBuilder($genericNumberConverter, $genericTimeConverter);
  65. $rfc4122Builder = new Rfc4122UuidBuilder($genericNumberConverter, $genericTimeConverter);
  66. $nonstandardBuilder = new NonstandardUuidBuilder($genericNumberConverter, $genericTimeConverter);
  67. // Use the PhpTimeConverter.
  68. $guidBuilder2 = new GuidBuilder($genericNumberConverter, $phpTimeConverter);
  69. $rfc4122Builder2 = new Rfc4122UuidBuilder($genericNumberConverter, $phpTimeConverter);
  70. $nonstandardBuilder2 = new NonstandardUuidBuilder($genericNumberConverter, $phpTimeConverter);
  71. /** @var list<UuidBuilderInterface> $unserializedBuilderCollection */
  72. $unserializedBuilderCollection = unserialize(serialize([
  73. $guidBuilder,
  74. $guidBuilder2,
  75. $rfc4122Builder,
  76. $rfc4122Builder2,
  77. $nonstandardBuilder,
  78. $nonstandardBuilder2,
  79. ]));
  80. foreach ($unserializedBuilderCollection as $builder) {
  81. $codec = new StringCodec($builder);
  82. $this->assertInstanceOf(UuidBuilderInterface::class, $builder);
  83. try {
  84. $uuid = $builder->build($codec, $bytes);
  85. if (($uuid instanceof UuidV1) || ($uuid instanceof UuidV2) || ($uuid instanceof UuidV6)) {
  86. $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime());
  87. }
  88. } catch (UnableToBuildUuidException $exception) {
  89. switch ($exception->getMessage()) {
  90. case 'The byte string received does not contain a valid version':
  91. case 'The byte string received does not conform to the RFC 4122 variant':
  92. case 'The byte string received does not conform to the RFC 4122 or Microsoft Corporation variants':
  93. // This is expected; ignoring.
  94. break;
  95. default:
  96. throw $exception;
  97. }
  98. }
  99. }
  100. }
  101. /**
  102. * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification
  103. */
  104. public function provideBytes(): array
  105. {
  106. return [
  107. [
  108. // GUID bytes
  109. 'bytes' => hex2bin('b08c6fff7dc5e1110b210800200c9a66'),
  110. ],
  111. [
  112. // GUID bytes
  113. 'bytes' => hex2bin('b08c6fff7dc5e1111b210800200c9a66'),
  114. ],
  115. [
  116. // GUID bytes
  117. 'bytes' => hex2bin('b08c6fff7dc5e1112b210800200c9a66'),
  118. ],
  119. [
  120. // GUID bytes
  121. 'bytes' => hex2bin('b08c6fff7dc5e1113b210800200c9a66'),
  122. ],
  123. [
  124. // GUID bytes
  125. 'bytes' => hex2bin('b08c6fff7dc5e1114b210800200c9a66'),
  126. ],
  127. [
  128. // GUID bytes
  129. 'bytes' => hex2bin('b08c6fff7dc5e1115b210800200c9a66'),
  130. ],
  131. [
  132. // GUID bytes
  133. 'bytes' => hex2bin('b08c6fff7dc5e1116b210800200c9a66'),
  134. ],
  135. [
  136. // GUID bytes
  137. 'bytes' => hex2bin('b08c6fff7dc5e1117b210800200c9a66'),
  138. ],
  139. [
  140. // GUID bytes
  141. 'bytes' => hex2bin('b08c6fff7dc5e111eb210800200c9a66'),
  142. ],
  143. [
  144. // GUID bytes
  145. 'bytes' => hex2bin('b08c6fff7dc5e111fb210800200c9a66'),
  146. ],
  147. [
  148. // Version 1 bytes
  149. 'bytes' => hex2bin('ff6f8cb0c57d11e19b210800200c9a66'),
  150. ],
  151. [
  152. // Version 2 bytes
  153. 'bytes' => hex2bin('000001f55cde21ea84000242ac130003'),
  154. ],
  155. [
  156. // Version 3 bytes
  157. 'bytes' => hex2bin('ff6f8cb0c57d31e1bb210800200c9a66'),
  158. ],
  159. [
  160. // Version 4 bytes
  161. 'bytes' => hex2bin('ff6f8cb0c57d41e1ab210800200c9a66'),
  162. ],
  163. [
  164. // Version 5 bytes
  165. 'bytes' => hex2bin('ff6f8cb0c57d51e18b210800200c9a66'),
  166. ],
  167. [
  168. // Version 6 bytes
  169. 'bytes' => hex2bin('ff6f8cb0c57d61e18b210800200c9a66'),
  170. ],
  171. [
  172. // NIL bytes
  173. 'bytes' => hex2bin('00000000000000000000000000000000'),
  174. ],
  175. ];
  176. }
  177. }