ExpectedBehaviorTest.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. <?php
  2. namespace Ramsey\Uuid\Test;
  3. use Brick\Math\BigInteger;
  4. use Ramsey\Uuid\Builder\DegradedUuidBuilder;
  5. use Ramsey\Uuid\Codec\CodecInterface;
  6. use Ramsey\Uuid\Codec\OrderedTimeCodec;
  7. use Ramsey\Uuid\Codec\TimestampFirstCombCodec;
  8. use Ramsey\Uuid\Converter\Number\DegradedNumberConverter;
  9. use Ramsey\Uuid\Converter\Time\DegradedTimeConverter;
  10. use Ramsey\Uuid\Converter\TimeConverterInterface;
  11. use Ramsey\Uuid\DegradedUuid;
  12. use Ramsey\Uuid\Generator\CombGenerator;
  13. use Ramsey\Uuid\Generator\DefaultTimeGenerator;
  14. use Ramsey\Uuid\Math\BrickMathCalculator;
  15. use Ramsey\Uuid\Type\Hexadecimal;
  16. use Ramsey\Uuid\Type\Time;
  17. use Ramsey\Uuid\Uuid;
  18. use Ramsey\Uuid\UuidFactory;
  19. use stdClass;
  20. /**
  21. * These tests exist to ensure a seamless upgrade path from 3.x to 4.x. If any
  22. * of these tests fail in 4.x, then it's because we've changed functionality
  23. * in such a way that compatibility with 3.x is broken.
  24. *
  25. * Naturally, there are some BC-breaks between 3.x and 4.x, but these tests
  26. * ensure that the base-level functionality that satisfies 80% of use-cases
  27. * does not change. The remaining 20% of use-cases should refer to the README
  28. * for details on the easiest path to transition from 3.x to 4.x.
  29. *
  30. * @codingStandardsIgnoreFile
  31. */
  32. class ExpectedBehaviorTest extends TestCase
  33. {
  34. /**
  35. * @dataProvider provideStaticCreationMethods
  36. */
  37. public function testStaticCreationMethodsAndStandardBehavior($method, $args)
  38. {
  39. $uuid = call_user_func_array(['Ramsey\Uuid\Uuid', $method], $args);
  40. $this->assertInstanceOf('Ramsey\Uuid\UuidInterface', $uuid);
  41. $this->assertIsInt($uuid->compareTo(Uuid::uuid1()));
  42. $this->assertNotSame(0, $uuid->compareTo(Uuid::uuid4()));
  43. $this->assertSame(0, $uuid->compareTo(clone $uuid));
  44. $this->assertFalse($uuid->equals(new stdClass()));
  45. $this->assertTrue($uuid->equals(clone $uuid));
  46. $this->assertIsString($uuid->getBytes());
  47. $this->assertInstanceOf('Ramsey\Uuid\Converter\NumberConverterInterface', $uuid->getNumberConverter());
  48. $this->assertIsString((string) $uuid->getHex());
  49. $this->assertIsArray($uuid->getFieldsHex());
  50. $this->assertArrayHasKey('time_low', $uuid->getFieldsHex());
  51. $this->assertArrayHasKey('time_mid', $uuid->getFieldsHex());
  52. $this->assertArrayHasKey('time_hi_and_version', $uuid->getFieldsHex());
  53. $this->assertArrayHasKey('clock_seq_hi_and_reserved', $uuid->getFieldsHex());
  54. $this->assertArrayHasKey('clock_seq_low', $uuid->getFieldsHex());
  55. $this->assertArrayHasKey('node', $uuid->getFieldsHex());
  56. $this->assertIsString($uuid->getTimeLowHex());
  57. $this->assertIsString($uuid->getTimeMidHex());
  58. $this->assertIsString($uuid->getTimeHiAndVersionHex());
  59. $this->assertIsString($uuid->getClockSeqHiAndReservedHex());
  60. $this->assertIsString($uuid->getClockSeqLowHex());
  61. $this->assertIsString($uuid->getNodeHex());
  62. $this->assertSame($uuid->getFieldsHex()['time_low'], $uuid->getTimeLowHex());
  63. $this->assertSame($uuid->getFieldsHex()['time_mid'], $uuid->getTimeMidHex());
  64. $this->assertSame($uuid->getFieldsHex()['time_hi_and_version'], $uuid->getTimeHiAndVersionHex());
  65. $this->assertSame($uuid->getFieldsHex()['clock_seq_hi_and_reserved'], $uuid->getClockSeqHiAndReservedHex());
  66. $this->assertSame($uuid->getFieldsHex()['clock_seq_low'], $uuid->getClockSeqLowHex());
  67. $this->assertSame($uuid->getFieldsHex()['node'], $uuid->getNodeHex());
  68. $this->assertSame(substr((string) $uuid->getHex(), 16), $uuid->getLeastSignificantBitsHex());
  69. $this->assertSame(substr((string) $uuid->getHex(), 0, 16), $uuid->getMostSignificantBitsHex());
  70. $this->assertSame(
  71. (string) $uuid->getHex(),
  72. $uuid->getTimeLowHex()
  73. . $uuid->getTimeMidHex()
  74. . $uuid->getTimeHiAndVersionHex()
  75. . $uuid->getClockSeqHiAndReservedHex()
  76. . $uuid->getClockSeqLowHex()
  77. . $uuid->getNodeHex()
  78. );
  79. $this->assertSame(
  80. (string) $uuid->getHex(),
  81. $uuid->getFieldsHex()['time_low']
  82. . $uuid->getFieldsHex()['time_mid']
  83. . $uuid->getFieldsHex()['time_hi_and_version']
  84. . $uuid->getFieldsHex()['clock_seq_hi_and_reserved']
  85. . $uuid->getFieldsHex()['clock_seq_low']
  86. . $uuid->getFieldsHex()['node']
  87. );
  88. $this->assertIsString($uuid->getUrn());
  89. $this->assertStringStartsWith('urn:uuid:', $uuid->getUrn());
  90. $this->assertSame('urn:uuid:' . (string) $uuid->getHex(), str_replace('-', '', $uuid->getUrn()));
  91. $this->assertSame((string) $uuid->getHex(), str_replace('-', '', $uuid->toString()));
  92. $this->assertSame((string) $uuid->getHex(), str_replace('-', '', (string) $uuid));
  93. $this->assertSame(
  94. $uuid->toString(),
  95. $uuid->getTimeLowHex() . '-'
  96. . $uuid->getTimeMidHex() . '-'
  97. . $uuid->getTimeHiAndVersionHex() . '-'
  98. . $uuid->getClockSeqHiAndReservedHex()
  99. . $uuid->getClockSeqLowHex() . '-'
  100. . $uuid->getNodeHex()
  101. );
  102. $this->assertSame(
  103. (string) $uuid,
  104. $uuid->getTimeLowHex() . '-'
  105. . $uuid->getTimeMidHex() . '-'
  106. . $uuid->getTimeHiAndVersionHex() . '-'
  107. . $uuid->getClockSeqHiAndReservedHex()
  108. . $uuid->getClockSeqLowHex() . '-'
  109. . $uuid->getNodeHex()
  110. );
  111. $this->assertSame(2, $uuid->getVariant());
  112. $this->assertSame((int) substr($method, -1), $uuid->getVersion());
  113. $this->assertSame(1, preg_match('/^\d+$/', (string) $uuid->getInteger()));
  114. }
  115. public function provideStaticCreationMethods()
  116. {
  117. return [
  118. ['uuid1', []],
  119. ['uuid1', ['00000fffffff']],
  120. ['uuid1', [null, 1234]],
  121. ['uuid1', ['00000fffffff', 1234]],
  122. ['uuid1', ['00000fffffff', null]],
  123. ['uuid1', [268435455]],
  124. ['uuid1', [268435455, 1234]],
  125. ['uuid1', [268435455, null]],
  126. ['uuid3', [Uuid::NAMESPACE_URL, 'https://example.com/foo']],
  127. ['uuid4', []],
  128. ['uuid5', [Uuid::NAMESPACE_URL, 'https://example.com/foo']],
  129. ];
  130. }
  131. public function testUuidVersion1MethodBehavior()
  132. {
  133. $uuid = Uuid::uuid1('00000fffffff', 0xffff);
  134. $this->assertInstanceOf('DateTimeInterface', $uuid->getDateTime());
  135. $this->assertSame('00000fffffff', $uuid->getNodeHex());
  136. $this->assertSame('3fff', $uuid->getClockSequenceHex());
  137. $this->assertSame('16383', (string) $uuid->getClockSequence());
  138. }
  139. public function testUuidVersion1MethodBehavior64Bit()
  140. {
  141. $uuid = Uuid::uuid1('ffffffffffff', 0xffff);
  142. $this->assertInstanceOf('DateTimeInterface', $uuid->getDateTime());
  143. $this->assertSame('ffffffffffff', $uuid->getNodeHex());
  144. $this->assertSame('281474976710655', (string) $uuid->getNode());
  145. $this->assertSame('3fff', $uuid->getClockSequenceHex());
  146. $this->assertSame('16383', (string) $uuid->getClockSequence());
  147. $this->assertSame(1, preg_match('/^\d+$/', (string) $uuid->getTimestamp()));
  148. }
  149. /**
  150. * @dataProvider provideIsValid
  151. */
  152. public function testIsValid($uuid, $expected)
  153. {
  154. $this->assertSame($expected, Uuid::isValid($uuid), "{$uuid} is not a valid UUID");
  155. $this->assertSame($expected, Uuid::isValid(strtoupper($uuid)), strtoupper($uuid) . ' is not a valid UUID');
  156. }
  157. public function provideIsValid()
  158. {
  159. return [
  160. // RFC 4122 UUIDs
  161. ['00000000-0000-0000-0000-000000000000', true],
  162. ['ff6f8cb0-c57d-11e1-8b21-0800200c9a66', true],
  163. ['ff6f8cb0-c57d-11e1-9b21-0800200c9a66', true],
  164. ['ff6f8cb0-c57d-11e1-ab21-0800200c9a66', true],
  165. ['ff6f8cb0-c57d-11e1-bb21-0800200c9a66', true],
  166. ['ff6f8cb0-c57d-21e1-8b21-0800200c9a66', true],
  167. ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', true],
  168. ['ff6f8cb0-c57d-21e1-ab21-0800200c9a66', true],
  169. ['ff6f8cb0-c57d-21e1-bb21-0800200c9a66', true],
  170. ['ff6f8cb0-c57d-31e1-8b21-0800200c9a66', true],
  171. ['ff6f8cb0-c57d-31e1-9b21-0800200c9a66', true],
  172. ['ff6f8cb0-c57d-31e1-ab21-0800200c9a66', true],
  173. ['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', true],
  174. ['ff6f8cb0-c57d-41e1-8b21-0800200c9a66', true],
  175. ['ff6f8cb0-c57d-41e1-9b21-0800200c9a66', true],
  176. ['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', true],
  177. ['ff6f8cb0-c57d-41e1-bb21-0800200c9a66', true],
  178. ['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', true],
  179. ['ff6f8cb0-c57d-51e1-9b21-0800200c9a66', true],
  180. ['ff6f8cb0-c57d-51e1-ab21-0800200c9a66', true],
  181. ['ff6f8cb0-c57d-51e1-bb21-0800200c9a66', true],
  182. // Non RFC 4122 UUIDs
  183. ['ffffffff-ffff-ffff-ffff-ffffffffffff', true],
  184. ['00000000-0000-0000-0000-000000000000', true],
  185. ['ff6f8cb0-c57d-01e1-0b21-0800200c9a66', true],
  186. ['ff6f8cb0-c57d-01e1-1b21-0800200c9a66', true],
  187. ['ff6f8cb0-c57d-01e1-2b21-0800200c9a66', true],
  188. ['ff6f8cb0-c57d-01e1-3b21-0800200c9a66', true],
  189. ['ff6f8cb0-c57d-01e1-4b21-0800200c9a66', true],
  190. ['ff6f8cb0-c57d-01e1-5b21-0800200c9a66', true],
  191. ['ff6f8cb0-c57d-01e1-6b21-0800200c9a66', true],
  192. ['ff6f8cb0-c57d-01e1-7b21-0800200c9a66', true],
  193. ['ff6f8cb0-c57d-01e1-db21-0800200c9a66', true],
  194. ['ff6f8cb0-c57d-01e1-eb21-0800200c9a66', true],
  195. ['ff6f8cb0-c57d-01e1-fb21-0800200c9a66', true],
  196. // Other valid patterns
  197. ['{ff6f8cb0-c57d-01e1-fb21-0800200c9a66}', true],
  198. ['urn:uuid:ff6f8cb0-c57d-01e1-fb21-0800200c9a66', true],
  199. // Invalid UUIDs
  200. ['ffffffffffffffffffffffffffffffff', false],
  201. ['00000000000000000000000000000000', false],
  202. [0, false],
  203. ['foobar', false],
  204. ['ff6f8cb0c57d51e1bb210800200c9a66', false],
  205. ['gf6f8cb0-c57d-51e1-bb21-0800200c9a66', false],
  206. ];
  207. }
  208. /**
  209. * @dataProvider provideFromStringInteger
  210. */
  211. public function testSerialization($string)
  212. {
  213. $uuid = Uuid::fromString($string);
  214. $serialized = serialize($uuid);
  215. $unserialized = unserialize($serialized);
  216. $this->assertSame(0, $uuid->compareTo($unserialized));
  217. $this->assertTrue($uuid->equals($unserialized));
  218. $this->assertSame("\"{$string}\"", json_encode($uuid));
  219. }
  220. /**
  221. * @dataProvider provideFromStringInteger
  222. */
  223. public function testSerializationWithOrderedTimeCodec($string)
  224. {
  225. $factory = new UuidFactory();
  226. $factory->setCodec(new OrderedTimeCodec(
  227. $factory->getUuidBuilder()
  228. ));
  229. $previousFactory = Uuid::getFactory();
  230. Uuid::setFactory($factory);
  231. $uuid = Uuid::fromString($string);
  232. $serialized = serialize($uuid);
  233. $unserialized = unserialize($serialized);
  234. Uuid::setFactory($previousFactory);
  235. $this->assertSame(0, $uuid->compareTo($unserialized));
  236. $this->assertTrue($uuid->equals($unserialized));
  237. $this->assertSame("\"{$string}\"", json_encode($uuid));
  238. }
  239. /**
  240. * @dataProvider provideFromStringInteger
  241. */
  242. public function testNumericReturnValues($string)
  243. {
  244. $leastSignificantBitsHex = substr(str_replace('-', '', $string), 16);
  245. $mostSignificantBitsHex = substr(str_replace('-', '', $string), 0, 16);
  246. $leastSignificantBits = BigInteger::fromBase($leastSignificantBitsHex, 16)->__toString();
  247. $mostSignificantBits = BigInteger::fromBase($mostSignificantBitsHex, 16)->__toString();
  248. $components = explode('-', $string);
  249. array_walk($components, function (&$value) {
  250. $value = BigInteger::fromBase($value, 16)->__toString();
  251. });
  252. if (strtolower($string) === Uuid::MAX) {
  253. $clockSeq = (int) $components[3];
  254. } else {
  255. $clockSeq = (int) $components[3] & 0x3fff;
  256. }
  257. $clockSeqHiAndReserved = (int) $components[3] >> 8;
  258. $clockSeqLow = (int) $components[3] & 0x00ff;
  259. $uuid = Uuid::fromString($string);
  260. $this->assertSame($components[0], (string) $uuid->getTimeLow());
  261. $this->assertSame($components[1], (string) $uuid->getTimeMid());
  262. $this->assertSame($components[2], (string) $uuid->getTimeHiAndVersion());
  263. $this->assertSame((string) $clockSeq, (string) $uuid->getClockSequence());
  264. $this->assertSame((string) $clockSeqHiAndReserved, (string) $uuid->getClockSeqHiAndReserved());
  265. $this->assertSame((string) $clockSeqLow, (string) $uuid->getClockSeqLow());
  266. $this->assertSame($components[4], (string) $uuid->getNode());
  267. $this->assertSame($leastSignificantBits, (string) $uuid->getLeastSignificantBits());
  268. $this->assertSame($mostSignificantBits, (string) $uuid->getMostSignificantBits());
  269. }
  270. /**
  271. * @dataProvider provideFromStringInteger
  272. */
  273. public function testFromBytes($string, $version, $variant, $integer)
  274. {
  275. $bytes = hex2bin(str_replace('-', '', $string));
  276. $uuid = Uuid::fromBytes($bytes);
  277. $this->assertInstanceOf('Ramsey\Uuid\UuidInterface', $uuid);
  278. $this->assertSame($string, $uuid->toString());
  279. $this->assertSame($version, $uuid->getVersion());
  280. $this->assertSame($variant, $uuid->getVariant());
  281. $components = explode('-', $string);
  282. $this->assertSame($components[0], $uuid->getTimeLowHex());
  283. $this->assertSame($components[1], $uuid->getTimeMidHex());
  284. $this->assertSame($components[2], $uuid->getTimeHiAndVersionHex());
  285. $this->assertSame($components[3], $uuid->getClockSeqHiAndReservedHex() . $uuid->getClockSeqLowHex());
  286. $this->assertSame($components[4], $uuid->getNodeHex());
  287. $this->assertSame($integer, (string) $uuid->getInteger());
  288. $this->assertSame($bytes, $uuid->getBytes());
  289. }
  290. /**
  291. * @dataProvider provideFromStringInteger
  292. */
  293. public function testFromInteger($string, $version, $variant, $integer)
  294. {
  295. $bytes = hex2bin(str_replace('-', '', $string));
  296. $uuid = Uuid::fromInteger($integer);
  297. $this->assertInstanceOf('Ramsey\Uuid\UuidInterface', $uuid);
  298. $this->assertSame($string, $uuid->toString());
  299. $this->assertSame($version, $uuid->getVersion());
  300. $this->assertSame($variant, $uuid->getVariant());
  301. $components = explode('-', $string);
  302. $this->assertSame($components[0], $uuid->getTimeLowHex());
  303. $this->assertSame($components[1], $uuid->getTimeMidHex());
  304. $this->assertSame($components[2], $uuid->getTimeHiAndVersionHex());
  305. $this->assertSame($components[3], $uuid->getClockSeqHiAndReservedHex() . $uuid->getClockSeqLowHex());
  306. $this->assertSame($components[4], $uuid->getNodeHex());
  307. $this->assertSame($integer, (string) $uuid->getInteger());
  308. $this->assertSame($bytes, $uuid->getBytes());
  309. }
  310. /**
  311. * @dataProvider provideFromStringInteger
  312. */
  313. public function testFromString($string, $version, $variant, $integer)
  314. {
  315. $bytes = hex2bin(str_replace('-', '', $string));
  316. $uuid = Uuid::fromString($string);
  317. $this->assertInstanceOf('Ramsey\Uuid\UuidInterface', $uuid);
  318. $this->assertSame($string, $uuid->toString());
  319. $this->assertSame($version, $uuid->getVersion());
  320. $this->assertSame($variant, $uuid->getVariant());
  321. $components = explode('-', $string);
  322. $this->assertSame($components[0], $uuid->getTimeLowHex());
  323. $this->assertSame($components[1], $uuid->getTimeMidHex());
  324. $this->assertSame($components[2], $uuid->getTimeHiAndVersionHex());
  325. $this->assertSame($components[3], $uuid->getClockSeqHiAndReservedHex() . $uuid->getClockSeqLowHex());
  326. $this->assertSame($components[4], $uuid->getNodeHex());
  327. $this->assertSame($integer, (string) $uuid->getInteger());
  328. $this->assertSame($bytes, $uuid->getBytes());
  329. }
  330. public function provideFromStringInteger()
  331. {
  332. return [
  333. ['00000000-0000-0000-0000-000000000000', null, 2, '0'],
  334. ['ff6f8cb0-c57d-11e1-8b21-0800200c9a66', 1, 2, '339532337419071774304650190139318639206'],
  335. ['ff6f8cb0-c57d-11e1-9b21-0800200c9a66', 1, 2, '339532337419071774305803111643925486182'],
  336. ['ff6f8cb0-c57d-11e1-ab21-0800200c9a66', 1, 2, '339532337419071774306956033148532333158'],
  337. ['ff6f8cb0-c57d-11e1-bb21-0800200c9a66', 1, 2, '339532337419071774308108954653139180134'],
  338. ['ff6f8cb0-c57d-21e1-8b21-0800200c9a66', 2, 2, '339532337419071849862513916053642058342'],
  339. ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 2, 2, '339532337419071849863666837558248905318'],
  340. ['ff6f8cb0-c57d-21e1-ab21-0800200c9a66', 2, 2, '339532337419071849864819759062855752294'],
  341. ['ff6f8cb0-c57d-21e1-bb21-0800200c9a66', 2, 2, '339532337419071849865972680567462599270'],
  342. ['ff6f8cb0-c57d-31e1-8b21-0800200c9a66', 3, 2, '339532337419071925420377641967965477478'],
  343. ['ff6f8cb0-c57d-31e1-9b21-0800200c9a66', 3, 2, '339532337419071925421530563472572324454'],
  344. ['ff6f8cb0-c57d-31e1-ab21-0800200c9a66', 3, 2, '339532337419071925422683484977179171430'],
  345. ['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', 3, 2, '339532337419071925423836406481786018406'],
  346. ['ff6f8cb0-c57d-41e1-8b21-0800200c9a66', 4, 2, '339532337419072000978241367882288896614'],
  347. ['ff6f8cb0-c57d-41e1-9b21-0800200c9a66', 4, 2, '339532337419072000979394289386895743590'],
  348. ['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', 4, 2, '339532337419072000980547210891502590566'],
  349. ['ff6f8cb0-c57d-41e1-bb21-0800200c9a66', 4, 2, '339532337419072000981700132396109437542'],
  350. ['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', 5, 2, '339532337419072076536105093796612315750'],
  351. ['ff6f8cb0-c57d-51e1-9b21-0800200c9a66', 5, 2, '339532337419072076537258015301219162726'],
  352. ['ff6f8cb0-c57d-51e1-ab21-0800200c9a66', 5, 2, '339532337419072076538410936805826009702'],
  353. ['ff6f8cb0-c57d-51e1-bb21-0800200c9a66', 5, 2, '339532337419072076539563858310432856678'],
  354. ['ff6f8cb0-c57d-01e1-0b21-0800200c9a66', null, 0, '339532337419071698737563092188140444262'],
  355. ['ff6f8cb0-c57d-01e1-1b21-0800200c9a66', null, 0, '339532337419071698738716013692747291238'],
  356. ['ff6f8cb0-c57d-01e1-2b21-0800200c9a66', null, 0, '339532337419071698739868935197354138214'],
  357. ['ff6f8cb0-c57d-01e1-3b21-0800200c9a66', null, 0, '339532337419071698741021856701960985190'],
  358. ['ff6f8cb0-c57d-01e1-4b21-0800200c9a66', null, 0, '339532337419071698742174778206567832166'],
  359. ['ff6f8cb0-c57d-01e1-5b21-0800200c9a66', null, 0, '339532337419071698743327699711174679142'],
  360. ['ff6f8cb0-c57d-01e1-6b21-0800200c9a66', null, 0, '339532337419071698744480621215781526118'],
  361. ['ff6f8cb0-c57d-01e1-7b21-0800200c9a66', null, 0, '339532337419071698745633542720388373094'],
  362. ['ff6f8cb0-c57d-01e1-cb21-0800200c9a66', null, 6, '339532337419071698751398150243422607974'],
  363. ['ff6f8cb0-c57d-01e1-db21-0800200c9a66', null, 6, '339532337419071698752551071748029454950'],
  364. ['ff6f8cb0-c57d-01e1-eb21-0800200c9a66', null, 7, '339532337419071698753703993252636301926'],
  365. ['ff6f8cb0-c57d-01e1-fb21-0800200c9a66', null, 7, '339532337419071698754856914757243148902'],
  366. ['ffffffff-ffff-ffff-ffff-ffffffffffff', null, 2, '340282366920938463463374607431768211455'],
  367. ];
  368. }
  369. /**
  370. * @runInSeparateProcess
  371. * @preserveGlobalState disabled
  372. */
  373. public function testGetSetFactory()
  374. {
  375. $this->assertInstanceOf('Ramsey\Uuid\UuidFactory', Uuid::getFactory());
  376. $factory = \Mockery::mock('Ramsey\Uuid\UuidFactory');
  377. Uuid::setFactory($factory);
  378. $this->assertSame($factory, Uuid::getFactory());
  379. }
  380. /**
  381. * @runInSeparateProcess
  382. * @preserveGlobalState disabled
  383. */
  384. public function testFactoryProvidesFunctionality()
  385. {
  386. $uuid = \Mockery::mock('Ramsey\Uuid\UuidInterface');
  387. $factory = \Mockery::mock('Ramsey\Uuid\UuidFactoryInterface', [
  388. 'uuid1' => $uuid,
  389. 'uuid3' => $uuid,
  390. 'uuid4' => $uuid,
  391. 'uuid5' => $uuid,
  392. 'fromBytes' => $uuid,
  393. 'fromString' => $uuid,
  394. 'fromInteger' => $uuid,
  395. ]);
  396. Uuid::setFactory($factory);
  397. $this->assertSame($uuid, Uuid::uuid1('ffffffffffff', 0xffff));
  398. $this->assertSame($uuid, Uuid::uuid3(Uuid::NAMESPACE_URL, 'https://example.com/foo'));
  399. $this->assertSame($uuid, Uuid::uuid4());
  400. $this->assertSame($uuid, Uuid::uuid5(Uuid::NAMESPACE_URL, 'https://example.com/foo'));
  401. $this->assertSame($uuid, Uuid::fromBytes(hex2bin('ffffffffffffffffffffffffffffffff')));
  402. $this->assertSame($uuid, Uuid::fromString('ffffffff-ffff-ffff-ffff-ffffffffffff'));
  403. $this->assertSame($uuid, Uuid::fromInteger('340282366920938463463374607431768211455'));
  404. }
  405. /**
  406. * @runInSeparateProcess
  407. * @preserveGlobalState disabled
  408. */
  409. public function testUsingDegradedFeatures()
  410. {
  411. $numberConverter = new DegradedNumberConverter();
  412. $builder = new DegradedUuidBuilder($numberConverter);
  413. $factory = new UuidFactory();
  414. $factory->setNumberConverter($numberConverter);
  415. $factory->setUuidBuilder($builder);
  416. Uuid::setFactory($factory);
  417. $uuid = Uuid::uuid1();
  418. $this->assertInstanceOf('Ramsey\Uuid\UuidInterface', $uuid);
  419. $this->assertInstanceOf('Ramsey\Uuid\DegradedUuid', $uuid);
  420. $this->assertInstanceOf('Ramsey\Uuid\Converter\Number\DegradedNumberConverter', $uuid->getNumberConverter());
  421. }
  422. /**
  423. * @runInSeparateProcess
  424. * @preserveGlobalState disabled
  425. */
  426. public function testUsingCustomCodec()
  427. {
  428. $mockUuid = \Mockery::mock('Ramsey\Uuid\UuidInterface');
  429. $codec = \Mockery::mock('Ramsey\Uuid\Codec\CodecInterface', [
  430. 'encode' => 'abcd1234',
  431. 'encodeBinary' => hex2bin('abcd1234'),
  432. 'decode' => $mockUuid,
  433. 'decodeBytes' => $mockUuid,
  434. ]);
  435. $factory = new UuidFactory();
  436. $factory->setCodec($codec);
  437. Uuid::setFactory($factory);
  438. $uuid = Uuid::uuid4();
  439. $this->assertSame('abcd1234', $uuid->toString());
  440. $this->assertSame(hex2bin('abcd1234'), $uuid->getBytes());
  441. $this->assertSame($mockUuid, Uuid::fromString('f00ba2'));
  442. $this->assertSame($mockUuid, Uuid::fromBytes(hex2bin('f00ba2')));
  443. }
  444. /**
  445. * @runInSeparateProcess
  446. * @preserveGlobalState disabled
  447. */
  448. public function testUsingCustomRandomGenerator()
  449. {
  450. $generator = \Mockery::mock('Ramsey\Uuid\Generator\RandomGeneratorInterface', [
  451. 'generate' => hex2bin('01234567abcd5432dcba0123456789ab'),
  452. ]);
  453. $factory = new UuidFactory();
  454. $factory->setRandomGenerator($generator);
  455. Uuid::setFactory($factory);
  456. $uuid = Uuid::uuid4();
  457. $this->assertSame('01234567-abcd-4432-9cba-0123456789ab', $uuid->toString());
  458. }
  459. /**
  460. * @runInSeparateProcess
  461. * @preserveGlobalState disabled
  462. */
  463. public function testUsingCustomTimeGenerator()
  464. {
  465. $generator = \Mockery::mock('Ramsey\Uuid\Generator\TimeGeneratorInterface', [
  466. 'generate' => hex2bin('01234567abcd5432dcba0123456789ab'),
  467. ]);
  468. $factory = new UuidFactory();
  469. $factory->setTimeGenerator($generator);
  470. Uuid::setFactory($factory);
  471. $uuid = Uuid::uuid1();
  472. $this->assertSame('01234567-abcd-1432-9cba-0123456789ab', $uuid->toString());
  473. }
  474. /**
  475. * @runInSeparateProcess
  476. * @preserveGlobalState disabled
  477. */
  478. public function testUsingDefaultTimeGeneratorWithCustomProviders()
  479. {
  480. $nodeProvider = \Mockery::mock('Ramsey\Uuid\Provider\NodeProviderInterface', [
  481. 'getNode' => new Hexadecimal('0123456789ab'),
  482. ]);
  483. $timeConverter = \Mockery::mock('Ramsey\Uuid\Converter\TimeConverterInterface');
  484. $timeConverter
  485. ->shouldReceive('calculateTime')
  486. ->andReturnUsing(function ($seconds, $microseconds) {
  487. return new Hexadecimal('abcd' . dechex($microseconds) . dechex($seconds));
  488. });
  489. $timeProvider = \Mockery::mock('Ramsey\Uuid\Provider\TimeProviderInterface', [
  490. 'currentTime' => [
  491. 'sec' => 1578522046,
  492. 'usec' => 10000,
  493. ],
  494. 'getTime' => new Time(1578522046, 10000),
  495. ]);
  496. $generator = new DefaultTimeGenerator($nodeProvider, $timeConverter, $timeProvider);
  497. $factory = new UuidFactory();
  498. $factory->setTimeGenerator($generator);
  499. Uuid::setFactory($factory);
  500. $uuid = Uuid::uuid1(null, 4095);
  501. $this->assertSame('5e1655be-2710-1bcd-8fff-0123456789ab', $uuid->toString());
  502. }
  503. /**
  504. * @runInSeparateProcess
  505. * @preserveGlobalState disabled
  506. */
  507. public function testHelperFunctions()
  508. {
  509. $uuid1 = \Mockery::mock('Ramsey\Uuid\UuidInterface', [
  510. 'toString' => 'aVersion1Uuid',
  511. ]);
  512. $uuid3 = \Mockery::mock('Ramsey\Uuid\UuidInterface', [
  513. 'toString' => 'aVersion3Uuid',
  514. ]);
  515. $uuid4 = \Mockery::mock('Ramsey\Uuid\UuidInterface', [
  516. 'toString' => 'aVersion4Uuid',
  517. ]);
  518. $uuid5 = \Mockery::mock('Ramsey\Uuid\UuidInterface', [
  519. 'toString' => 'aVersion5Uuid',
  520. ]);
  521. $factory = \Mockery::mock('Ramsey\Uuid\UuidFactoryInterface', [
  522. 'uuid1' => $uuid1,
  523. 'uuid3' => $uuid3,
  524. 'uuid4' => $uuid4,
  525. 'uuid5' => $uuid5,
  526. ]);
  527. Uuid::setFactory($factory);
  528. $this->assertSame('aVersion1Uuid', \Ramsey\Uuid\v1('ffffffffffff', 0xffff));
  529. $this->assertSame('aVersion3Uuid', \Ramsey\Uuid\v3(Uuid::NAMESPACE_URL, 'https://example.com/foo'));
  530. $this->assertSame('aVersion4Uuid', \Ramsey\Uuid\v4());
  531. $this->assertSame('aVersion5Uuid', \Ramsey\Uuid\v5(Uuid::NAMESPACE_URL, 'https://example.com/foo'));
  532. }
  533. /**
  534. * @link https://git.io/JvJZo Use of TimestampFirstCombCodec in laravel/framework
  535. */
  536. public function testUseOfTimestampFirstCombCodec()
  537. {
  538. $factory = new UuidFactory();
  539. $factory->setRandomGenerator(new CombGenerator(
  540. $factory->getRandomGenerator(),
  541. $factory->getNumberConverter()
  542. ));
  543. $factory->setCodec(new TimestampFirstCombCodec(
  544. $factory->getUuidBuilder()
  545. ));
  546. $uuid = $factory->uuid4();
  547. // Swap fields according to the rules for TimestampFirstCombCodec.
  548. $fields = array_values($uuid->getFieldsHex());
  549. $last48Bits = $fields[5];
  550. $fields[5] = $fields[0] . $fields[1];
  551. $fields[0] = substr($last48Bits, 0, 8);
  552. $fields[1] = substr($last48Bits, 8, 4);
  553. $expectedHex = implode('', $fields);
  554. $expectedBytes = hex2bin($expectedHex);
  555. $this->assertInstanceOf('Ramsey\Uuid\UuidInterface', $uuid);
  556. $this->assertSame(2, $uuid->getVariant());
  557. $this->assertSame(4, $uuid->getVersion());
  558. $this->assertSame($expectedBytes, $uuid->getBytes());
  559. $this->assertSame($expectedHex, (string) $uuid->getHex());
  560. }
  561. /**
  562. * @dataProvider provideUuidConstantTests
  563. */
  564. public function testUuidConstants($constantName, $expected)
  565. {
  566. $this->assertSame($expected, constant("Ramsey\\Uuid\\Uuid::{$constantName}"));
  567. }
  568. public function provideUuidConstantTests()
  569. {
  570. return [
  571. ['NAMESPACE_DNS', '6ba7b810-9dad-11d1-80b4-00c04fd430c8'],
  572. ['NAMESPACE_URL', '6ba7b811-9dad-11d1-80b4-00c04fd430c8'],
  573. ['NAMESPACE_OID', '6ba7b812-9dad-11d1-80b4-00c04fd430c8'],
  574. ['NAMESPACE_X500', '6ba7b814-9dad-11d1-80b4-00c04fd430c8'],
  575. ['NIL', '00000000-0000-0000-0000-000000000000'],
  576. ['MAX', 'ffffffff-ffff-ffff-ffff-ffffffffffff'],
  577. ['RESERVED_NCS', 0],
  578. ['RFC_4122', 2],
  579. ['RESERVED_MICROSOFT', 6],
  580. ['RESERVED_FUTURE', 7],
  581. ['VALID_PATTERN', '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$'],
  582. ['UUID_TYPE_TIME', 1],
  583. ['UUID_TYPE_IDENTIFIER', 2],
  584. ['UUID_TYPE_HASH_MD5', 3],
  585. ['UUID_TYPE_RANDOM', 4],
  586. ['UUID_TYPE_HASH_SHA1', 5],
  587. ['UUID_TYPE_REORDERED_TIME', 6],
  588. ['UUID_TYPE_UNIX_TIME', 7],
  589. ];
  590. }
  591. }