From 7ea7e4282ee0ede55000471729be4ac4f6fee3d4 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Mon, 20 Jan 2020 21:05:06 -0600 Subject: [PATCH] Validate fields passed to specific UUID version classes --- src/Rfc4122/UuidV1.php | 32 ++++++++++++++++++++ src/Rfc4122/UuidV2.php | 31 ++++++++++++++++++++ src/Rfc4122/UuidV3.php | 31 ++++++++++++++++++++ src/Rfc4122/UuidV4.php | 31 ++++++++++++++++++++ src/Rfc4122/UuidV5.php | 31 ++++++++++++++++++++ tests/Rfc4122/UuidV1Test.php | 57 ++++++++++++++++++++++++++++++++++++ tests/Rfc4122/UuidV2Test.php | 57 ++++++++++++++++++++++++++++++++++++ tests/Rfc4122/UuidV3Test.php | 57 ++++++++++++++++++++++++++++++++++++ tests/Rfc4122/UuidV4Test.php | 57 ++++++++++++++++++++++++++++++++++++ tests/Rfc4122/UuidV5Test.php | 57 ++++++++++++++++++++++++++++++++++++ 10 files changed, 441 insertions(+) create mode 100644 tests/Rfc4122/UuidV1Test.php create mode 100644 tests/Rfc4122/UuidV2Test.php create mode 100644 tests/Rfc4122/UuidV3Test.php create mode 100644 tests/Rfc4122/UuidV4Test.php create mode 100644 tests/Rfc4122/UuidV5Test.php diff --git a/src/Rfc4122/UuidV1.php b/src/Rfc4122/UuidV1.php index 40bcd8c..7356c3a 100644 --- a/src/Rfc4122/UuidV1.php +++ b/src/Rfc4122/UuidV1.php @@ -16,7 +16,12 @@ namespace Ramsey\Uuid\Rfc4122; use DateTimeImmutable; use DateTimeInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Exception\DateTimeException; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Uuid; use Throwable; @@ -28,6 +33,33 @@ use Throwable; */ final class UuidV1 extends Uuid implements UuidInterface { + /** + * Creates a version 1 (time-based) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_TIME) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV1 must represent a ' + . 'version 1 (time-based) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } + /** * Returns a DateTimeInterface object representing the timestamp associated * with the UUID diff --git a/src/Rfc4122/UuidV2.php b/src/Rfc4122/UuidV2.php index 47bf644..16477e8 100644 --- a/src/Rfc4122/UuidV2.php +++ b/src/Rfc4122/UuidV2.php @@ -14,6 +14,11 @@ declare(strict_types=1); namespace Ramsey\Uuid\Rfc4122; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Uuid; /** @@ -30,4 +35,30 @@ use Ramsey\Uuid\Uuid; */ final class UuidV2 extends Uuid implements UuidInterface { + /** + * Creates a version 2 (DCE Security) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_IDENTIFIER) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV2 must represent a ' + . 'version 2 (DCE Security) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } } diff --git a/src/Rfc4122/UuidV3.php b/src/Rfc4122/UuidV3.php index 19bc4ad..deaa54e 100644 --- a/src/Rfc4122/UuidV3.php +++ b/src/Rfc4122/UuidV3.php @@ -14,6 +14,11 @@ declare(strict_types=1); namespace Ramsey\Uuid\Rfc4122; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Uuid; /** @@ -24,4 +29,30 @@ use Ramsey\Uuid\Uuid; */ final class UuidV3 extends Uuid implements UuidInterface { + /** + * Creates a version 3 (name-based, MD5-hashed) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_MD5) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV3 must represent a ' + . 'version 3 (name-based, MD5-hashed) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } } diff --git a/src/Rfc4122/UuidV4.php b/src/Rfc4122/UuidV4.php index af67c73..2e57246 100644 --- a/src/Rfc4122/UuidV4.php +++ b/src/Rfc4122/UuidV4.php @@ -14,6 +14,11 @@ declare(strict_types=1); namespace Ramsey\Uuid\Rfc4122; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Uuid; /** @@ -24,4 +29,30 @@ use Ramsey\Uuid\Uuid; */ final class UuidV4 extends Uuid implements UuidInterface { + /** + * Creates a version 4 (random) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_RANDOM) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV4 must represent a ' + . 'version 4 (random) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } } diff --git a/src/Rfc4122/UuidV5.php b/src/Rfc4122/UuidV5.php index 7b65033..2ef6ab3 100644 --- a/src/Rfc4122/UuidV5.php +++ b/src/Rfc4122/UuidV5.php @@ -14,6 +14,11 @@ declare(strict_types=1); namespace Ramsey\Uuid\Rfc4122; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Uuid; /** @@ -24,4 +29,30 @@ use Ramsey\Uuid\Uuid; */ final class UuidV5 extends Uuid implements UuidInterface { + /** + * Creates a version 5 (name-based, SHA1-hashed) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_SHA1) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV5 must represent a ' + . 'version 5 (named-based, SHA1-hashed) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } } diff --git a/tests/Rfc4122/UuidV1Test.php b/tests/Rfc4122/UuidV1Test.php new file mode 100644 index 0000000..c6ac0a0 --- /dev/null +++ b/tests/Rfc4122/UuidV1Test.php @@ -0,0 +1,57 @@ + $version, + ]); + + $numberConverter = Mockery::mock(NumberConverterInterface::class); + $codec = Mockery::mock(CodecInterface::class); + $timeConverter = Mockery::mock(TimeConverterInterface::class); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Fields used to create a UuidV1 must represent a ' + . 'version 1 (time-based) UUID' + ); + + new UuidV1($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification + */ + public function provideTestVersions(): array + { + return [ + ['version' => 0], + ['version' => 2], + ['version' => 3], + ['version' => 4], + ['version' => 5], + ['version' => 6], + ['version' => 7], + ['version' => 8], + ['version' => 9], + ]; + } +} diff --git a/tests/Rfc4122/UuidV2Test.php b/tests/Rfc4122/UuidV2Test.php new file mode 100644 index 0000000..9a68d2b --- /dev/null +++ b/tests/Rfc4122/UuidV2Test.php @@ -0,0 +1,57 @@ + $version, + ]); + + $numberConverter = Mockery::mock(NumberConverterInterface::class); + $codec = Mockery::mock(CodecInterface::class); + $timeConverter = Mockery::mock(TimeConverterInterface::class); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Fields used to create a UuidV2 must represent a ' + . 'version 2 (DCE Security) UUID' + ); + + new UuidV2($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification + */ + public function provideTestVersions(): array + { + return [ + ['version' => 0], + ['version' => 1], + ['version' => 3], + ['version' => 4], + ['version' => 5], + ['version' => 6], + ['version' => 7], + ['version' => 8], + ['version' => 9], + ]; + } +} diff --git a/tests/Rfc4122/UuidV3Test.php b/tests/Rfc4122/UuidV3Test.php new file mode 100644 index 0000000..b9110ef --- /dev/null +++ b/tests/Rfc4122/UuidV3Test.php @@ -0,0 +1,57 @@ + $version, + ]); + + $numberConverter = Mockery::mock(NumberConverterInterface::class); + $codec = Mockery::mock(CodecInterface::class); + $timeConverter = Mockery::mock(TimeConverterInterface::class); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Fields used to create a UuidV3 must represent a ' + . 'version 3 (name-based, MD5-hashed) UUID' + ); + + new UuidV3($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification + */ + public function provideTestVersions(): array + { + return [ + ['version' => 0], + ['version' => 1], + ['version' => 2], + ['version' => 4], + ['version' => 5], + ['version' => 6], + ['version' => 7], + ['version' => 8], + ['version' => 9], + ]; + } +} diff --git a/tests/Rfc4122/UuidV4Test.php b/tests/Rfc4122/UuidV4Test.php new file mode 100644 index 0000000..f595346 --- /dev/null +++ b/tests/Rfc4122/UuidV4Test.php @@ -0,0 +1,57 @@ + $version, + ]); + + $numberConverter = Mockery::mock(NumberConverterInterface::class); + $codec = Mockery::mock(CodecInterface::class); + $timeConverter = Mockery::mock(TimeConverterInterface::class); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Fields used to create a UuidV4 must represent a ' + . 'version 4 (random) UUID' + ); + + new UuidV4($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification + */ + public function provideTestVersions(): array + { + return [ + ['version' => 0], + ['version' => 1], + ['version' => 2], + ['version' => 3], + ['version' => 5], + ['version' => 6], + ['version' => 7], + ['version' => 8], + ['version' => 9], + ]; + } +} diff --git a/tests/Rfc4122/UuidV5Test.php b/tests/Rfc4122/UuidV5Test.php new file mode 100644 index 0000000..a1270f2 --- /dev/null +++ b/tests/Rfc4122/UuidV5Test.php @@ -0,0 +1,57 @@ + $version, + ]); + + $numberConverter = Mockery::mock(NumberConverterInterface::class); + $codec = Mockery::mock(CodecInterface::class); + $timeConverter = Mockery::mock(TimeConverterInterface::class); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Fields used to create a UuidV5 must represent a ' + . 'version 5 (named-based, SHA1-hashed) UUID' + ); + + new UuidV5($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification + */ + public function provideTestVersions(): array + { + return [ + ['version' => 0], + ['version' => 1], + ['version' => 2], + ['version' => 3], + ['version' => 4], + ['version' => 6], + ['version' => 7], + ['version' => 8], + ['version' => 9], + ]; + } +}