diff --git a/.gitattributes b/.gitattributes index 5d184e3..2ee8814 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,6 +4,7 @@ .readthedocs.yml export-ignore .travis.yml export-ignore docs/ export-ignore +phpbench.json export-ignore phpcs.xml.dist export-ignore phpunit.xml.dist export-ignore resources/ export-ignore diff --git a/.travis.yml b/.travis.yml index 5ba1e69..5aa0eca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,6 +62,7 @@ script: - ./resources/scripts/cmd-proxy.sh composer phpcs - ./resources/scripts/cmd-proxy.sh composer phpstan - ./resources/scripts/cmd-proxy.sh composer psalm + - ./resources/scripts/cmd-proxy.sh composer phpbench - travis_wait 30 ./resources/scripts/cmd-proxy.sh ./vendor/bin/phpunit --verbose --coverage-clover build/logs/clover.xml after_success: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e53954..e659605 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Security +## [4.1.1] - 2020-08-18 + +### Fixed + +* Allow use of brick/math version 0.9 + + +## [4.1.0] - 2020-07-28 + +### Changed + +* Improve performance of `Uuid::fromString()`, `Uuid::fromBytes()`, + `UuidInterface#toString()`, and `UuidInterface#getBytes()`. See PR + [#324](https://github.com/ramsey/uuid/pull/324) for more information. + + ## [4.0.1] - 2020-03-29 ### Fixed @@ -1182,7 +1198,9 @@ versions leading up to this release.* [ramsey/uuid-doctrine]: https://github.com/ramsey/uuid-doctrine [ramsey/uuid-console]: https://github.com/ramsey/uuid-console -[unreleased]: https://github.com/ramsey/uuid/compare/4.0.1...HEAD +[unreleased]: https://github.com/ramsey/uuid/compare/4.1.1...HEAD +[4.1.1]: https://github.com/ramsey/uuid/compare/4.1.0...4.1.1 +[4.1.0]: https://github.com/ramsey/uuid/compare/4.0.1...4.1.0 [4.0.1]: https://github.com/ramsey/uuid/compare/4.0.0...4.0.1 [4.0.0]: https://github.com/ramsey/uuid/compare/4.0.0-beta2...4.0.0 [4.0.0-beta2]: https://github.com/ramsey/uuid/compare/4.0.0-beta1...4.0.0-beta2 diff --git a/composer.json b/composer.json index 5d34375..41d500b 100644 --- a/composer.json +++ b/composer.json @@ -12,13 +12,13 @@ "require": { "php": "^7.2 || ^8", "ext-json": "*", - "brick/math": "^0.8", + "brick/math": "^0.8 || ^0.9", "ramsey/collection": "^1.0", "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "codeception/aspect-mock": "^3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2", + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0", "doctrine/annotations": "^1.8", "goaop/framework": "^2", "mockery/mockery": "^1.3", @@ -27,8 +27,8 @@ "php-mock/php-mock-mockery": "^1.3", "php-mock/php-mock-phpunit": "^2.5", "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^0.17.1", "phpstan/extension-installer": "^1.0", - "phpstan/phpdoc-parser": "0.4.4", "phpstan/phpstan": "^0.12", "phpstan/phpstan-mockery": "^0.12", "phpstan/phpstan-phpunit": "^0.12", @@ -67,12 +67,14 @@ }, "autoload-dev": { "psr-4": { + "Ramsey\\Uuid\\Benchmark\\": "tests/benchmark/", "Ramsey\\Uuid\\StaticAnalysis\\": "tests/static-analysis/", "Ramsey\\Uuid\\Test\\": "tests/" } }, "scripts": { "lint": "parallel-lint src tests", + "phpbench": "phpbench run", "phpcbf": "phpcbf -vpw --cache=build/cache/phpcs.cache", "phpcs": "phpcs --cache=build/cache/phpcs.cache", "phpstan": [ @@ -84,6 +86,7 @@ "phpunit-coverage": "phpunit --verbose --colors=always --coverage-html build/coverage", "test": [ "@lint", + "@phpbench", "@phpcs", "@phpstan", "@psalm", diff --git a/phpbench.json b/phpbench.json new file mode 100644 index 0000000..f1150d0 --- /dev/null +++ b/phpbench.json @@ -0,0 +1,10 @@ +{ + "bootstrap": "vendor/autoload.php", + "path": "tests/benchmark", + "retry_threshold": 5, + "reports": { + "report": { + "extends": "aggregate" + } + } +} diff --git a/src/Builder/BuilderCollection.php b/src/Builder/BuilderCollection.php index b3e5f1d..0997971 100644 --- a/src/Builder/BuilderCollection.php +++ b/src/Builder/BuilderCollection.php @@ -15,7 +15,6 @@ declare(strict_types=1); namespace Ramsey\Uuid\Builder; use Ramsey\Collection\AbstractCollection; -use Ramsey\Collection\CollectionInterface; use Ramsey\Uuid\Converter\Number\GenericNumberConverter; use Ramsey\Uuid\Converter\Time\GenericTimeConverter; use Ramsey\Uuid\Converter\Time\PhpTimeConverter; @@ -28,7 +27,7 @@ use Traversable; /** * A collection of UuidBuilderInterface objects */ -class BuilderCollection extends AbstractCollection implements CollectionInterface +class BuilderCollection extends AbstractCollection { public function getType(): string { diff --git a/src/Builder/DefaultUuidBuilder.php b/src/Builder/DefaultUuidBuilder.php index 2af4e86..7c4a6f8 100644 --- a/src/Builder/DefaultUuidBuilder.php +++ b/src/Builder/DefaultUuidBuilder.php @@ -21,6 +21,6 @@ use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder; * * @psalm-immutable */ -class DefaultUuidBuilder extends Rfc4122UuidBuilder implements UuidBuilderInterface +class DefaultUuidBuilder extends Rfc4122UuidBuilder { } diff --git a/src/Fields/SerializableFieldsTrait.php b/src/Fields/SerializableFieldsTrait.php index 90f1d49..4ae90be 100644 --- a/src/Fields/SerializableFieldsTrait.php +++ b/src/Fields/SerializableFieldsTrait.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace Ramsey\Uuid\Fields; use function base64_decode; -use function base64_encode; +use function strlen; /** * Provides common serialization functionality to fields @@ -39,7 +39,7 @@ trait SerializableFieldsTrait */ public function serialize(): string { - return base64_encode($this->getBytes()); + return $this->getBytes(); } /** @@ -51,6 +51,10 @@ trait SerializableFieldsTrait */ public function unserialize($serialized): void { - $this->__construct(base64_decode($serialized)); + if (strlen($serialized) === 16) { + $this->__construct($serialized); + } else { + $this->__construct(base64_decode($serialized)); + } } } diff --git a/src/Guid/Guid.php b/src/Guid/Guid.php index 08a0069..b3ed096 100644 --- a/src/Guid/Guid.php +++ b/src/Guid/Guid.php @@ -18,7 +18,6 @@ use Ramsey\Uuid\Codec\CodecInterface; use Ramsey\Uuid\Converter\NumberConverterInterface; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\UuidInterface; /** * Guid represents a UUID with "native" (little-endian) byte order @@ -49,7 +48,7 @@ use Ramsey\Uuid\UuidInterface; * * @psalm-immutable */ -final class Guid extends Uuid implements UuidInterface +final class Guid extends Uuid { public function __construct( Fields $fields, diff --git a/src/Lazy/LazyUuidFromString.php b/src/Lazy/LazyUuidFromString.php new file mode 100644 index 0000000..3d4ddcb --- /dev/null +++ b/src/Lazy/LazyUuidFromString.php @@ -0,0 +1,546 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Lazy; + +use DateTimeInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Exception\UnsupportedOperationException; +use Ramsey\Uuid\Fields\FieldsInterface; +use Ramsey\Uuid\Nonstandard\UuidV6; +use Ramsey\Uuid\Rfc4122\UuidV1; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\UuidFactory; +use Ramsey\Uuid\UuidInterface; + +use function assert; +use function bin2hex; +use function hex2bin; +use function str_replace; +use function substr; + +/** + * Lazy version of a UUID: its format has not been determined yet, so it is mostly only usable for string/bytes + * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of + * increased overhead for more advanced UUID operations. + * + * @internal this type is used internally for performance reasons, and is not supposed to be directly referenced + * in consumer libraries. + * + * @psalm-immutable + * + * Note: the {@see FieldsInterface} does not declare methods that deprecated API + * relies upon: the API has been ported from the {@see \Ramsey\Uuid\Uuid} definition, + * and is deprecated anyway. + * Note: the deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed + * once the deprecated API is gone from this class too. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + */ +final class LazyUuidFromString implements UuidInterface +{ + public const VALID_REGEX = '/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/ms'; + /** + * @var string + * @psalm-var non-empty-string + */ + private $uuid; + /** @var UuidInterface|null */ + private $unwrapped; + + /** @psalm-param non-empty-string $uuid */ + public function __construct(string $uuid) + { + $this->uuid = $uuid; + } + + /** @psalm-pure */ + public static function fromBytes(string $bytes): self + { + $base16Uuid = bin2hex($bytes); + + return new self( + substr($base16Uuid, 0, 8) + . '-' + . substr($base16Uuid, 8, 4) + . '-' + . substr($base16Uuid, 12, 4) + . '-' + . substr($base16Uuid, 16, 4) + . '-' + . substr($base16Uuid, 20, 12) + ); + } + + public function serialize(): string + { + return $this->uuid; + } + + /** + * {@inheritDoc} + * + * @param string $serialized + * + * @psalm-param non-empty-string $serialized + */ + public function unserialize($serialized): void + { + $this->uuid = $serialized; + } + + /** @psalm-suppress DeprecatedMethod */ + public function getNumberConverter(): NumberConverterInterface + { + return ($this->unwrapped ?? $this->unwrap()) + ->getNumberConverter(); + } + + /** + * {@inheritDoc} + * + * @psalm-suppress DeprecatedMethod + */ + public function getFieldsHex(): array + { + return ($this->unwrapped ?? $this->unwrap()) + ->getFieldsHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getClockSeqHiAndReservedHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getClockSeqHiAndReservedHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getClockSeqLowHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getClockSeqLowHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getClockSequenceHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getClockSequenceHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getDateTime(): DateTimeInterface + { + return ($this->unwrapped ?? $this->unwrap()) + ->getDateTime(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getLeastSignificantBitsHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getLeastSignificantBitsHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getMostSignificantBitsHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getMostSignificantBitsHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getNodeHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getNodeHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimeHiAndVersionHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimeHiAndVersionHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimeLowHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimeLowHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimeMidHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimeMidHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimestampHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimestampHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getUrn(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getUrn(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getVariant(): ?int + { + return ($this->unwrapped ?? $this->unwrap()) + ->getVariant(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getVersion(): ?int + { + return ($this->unwrapped ?? $this->unwrap()) + ->getVersion(); + } + + public function compareTo(UuidInterface $other): int + { + return ($this->unwrapped ?? $this->unwrap()) + ->compareTo($other); + } + + public function equals(?object $other): bool + { + if (! $other instanceof UuidInterface) { + return false; + } + + return $this->uuid === $other->toString(); + } + + /** + * {@inheritDoc} + * + * @psalm-suppress MoreSpecificReturnType + * @psalm-suppress LessSpecificReturnStatement we know that {@see self::$uuid} is a non-empty string, so + * we know that {@see hex2bin} will retrieve a non-empty string too. + */ + public function getBytes(): string + { + return (string) hex2bin(str_replace('-', '', $this->uuid)); + } + + public function getFields(): FieldsInterface + { + return ($this->unwrapped ?? $this->unwrap()) + ->getFields(); + } + + public function getHex(): Hexadecimal + { + return ($this->unwrapped ?? $this->unwrap()) + ->getHex(); + } + + public function getInteger(): IntegerObject + { + return ($this->unwrapped ?? $this->unwrap()) + ->getInteger(); + } + + public function toString(): string + { + return $this->uuid; + } + + public function __toString(): string + { + return $this->uuid; + } + + public function jsonSerialize(): string + { + return $this->uuid; + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getClockSeqHiAndReserved(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getClockSeqHiAndReserved() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getClockSeqLow(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getClockSeqLow() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getClockSequence(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getClockSeq() + ->toString() + ); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getLeastSignificantBits(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex(substr($instance->getHex()->toString(), 16)); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getMostSignificantBits(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex(substr($instance->getHex()->toString(), 0, 16)); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getNode()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getNode(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getNode() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimeHiAndVersion(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getTimeHiAndVersion() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimeLow(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getTimeLow() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimeMid(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getTimeMid() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimestamp(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + $fields = $instance->getFields(); + + if ($fields->getVersion() !== 1) { + throw new UnsupportedOperationException('Not a time-based UUID'); + } + + return $instance->getNumberConverter() + ->fromHex($fields->getTimestamp()->toString()); + } + + public function toUuidV1(): UuidV1 + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + if ($instance instanceof UuidV1) { + return $instance; + } + + assert($instance instanceof UuidV6); + + return $instance->toUuidV1(); + } + + public function toUuidV6(): UuidV6 + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + assert($instance instanceof UuidV6); + + return $instance; + } + + /** + * @psalm-suppress ImpureMethodCall the retrieval of the factory is a clear violation of purity here: this is a + * known pitfall of the design of this library, where a value object contains + * a mutable reference to a factory. We use a fixed factory here, so the violation + * will not have real-world effects, as this object is only instantiated with the + * default factory settings/features. + * @psalm-suppress InaccessibleProperty property {@see $unwrapped} is used as a cache: we don't expose it to the + * outside world, so we should be fine here. + */ + private function unwrap(): UuidInterface + { + return $this->unwrapped = (new UuidFactory()) + ->fromString($this->uuid); + } +} diff --git a/src/Nonstandard/Uuid.php b/src/Nonstandard/Uuid.php index 5a7a333..715f825 100644 --- a/src/Nonstandard/Uuid.php +++ b/src/Nonstandard/Uuid.php @@ -18,14 +18,13 @@ use Ramsey\Uuid\Codec\CodecInterface; use Ramsey\Uuid\Converter\NumberConverterInterface; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Uuid as BaseUuid; -use Ramsey\Uuid\UuidInterface; /** * Nonstandard\Uuid is a UUID that doesn't conform to RFC 4122 * * @psalm-immutable */ -final class Uuid extends BaseUuid implements UuidInterface +final class Uuid extends BaseUuid { public function __construct( Fields $fields, diff --git a/src/Nonstandard/UuidV6.php b/src/Nonstandard/UuidV6.php index 454d04c..05586b3 100644 --- a/src/Nonstandard/UuidV6.php +++ b/src/Nonstandard/UuidV6.php @@ -21,6 +21,7 @@ use Ramsey\Uuid\Converter\NumberConverterInterface; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Exception\DateTimeException; use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Lazy\LazyUuidFromString; use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Rfc4122\UuidInterface; use Ramsey\Uuid\Rfc4122\UuidV1; @@ -106,10 +107,10 @@ final class UuidV6 extends Uuid implements UuidInterface . '1' . substr($hex, 0, 3) . substr($hex, 16); - /** @var UuidV1 $uuid */ + /** @var LazyUuidFromString $uuid */ $uuid = Uuid::fromBytes((string) hex2bin($hex)); - return $uuid; + return $uuid->toUuidV1(); } /** @@ -124,9 +125,9 @@ final class UuidV6 extends Uuid implements UuidInterface . '6' . substr($hex, 5, 3) . substr($hex, 16); - /** @var UuidV6 $uuid */ + /** @var LazyUuidFromString $uuid */ $uuid = Uuid::fromBytes((string) hex2bin($hex)); - return $uuid; + return $uuid->toUuidV6(); } } diff --git a/src/Provider/Node/NodeProviderCollection.php b/src/Provider/Node/NodeProviderCollection.php index 89d0917..c49398e 100644 --- a/src/Provider/Node/NodeProviderCollection.php +++ b/src/Provider/Node/NodeProviderCollection.php @@ -15,14 +15,13 @@ declare(strict_types=1); namespace Ramsey\Uuid\Provider\Node; use Ramsey\Collection\AbstractCollection; -use Ramsey\Collection\CollectionInterface; use Ramsey\Uuid\Provider\NodeProviderInterface; use Ramsey\Uuid\Type\Hexadecimal; /** * A collection of NodeProviderInterface objects */ -class NodeProviderCollection extends AbstractCollection implements CollectionInterface +class NodeProviderCollection extends AbstractCollection { public function getType(): string { diff --git a/src/Rfc4122/Validator.php b/src/Rfc4122/Validator.php index 7dcf078..ed43c98 100644 --- a/src/Rfc4122/Validator.php +++ b/src/Rfc4122/Validator.php @@ -27,8 +27,8 @@ use function str_replace; */ final class Validator implements ValidatorInterface { - private const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-' - . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'; + private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-' + . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z'; /** * @psalm-return non-empty-string @@ -44,6 +44,6 @@ final class Validator implements ValidatorInterface { $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid); - return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/D', $uuid); + return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid); } } diff --git a/src/Uuid.php b/src/Uuid.php index 0f86cdd..762dfdb 100644 --- a/src/Uuid.php +++ b/src/Uuid.php @@ -19,12 +19,18 @@ use Ramsey\Uuid\Codec\CodecInterface; use Ramsey\Uuid\Converter\NumberConverterInterface; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Fields\FieldsInterface; +use Ramsey\Uuid\Lazy\LazyUuidFromString; use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Type\Hexadecimal; use Ramsey\Uuid\Type\Integer as IntegerObject; +use function bin2hex; +use function preg_match; use function str_replace; use function strcmp; +use function strlen; +use function strtolower; +use function substr; /** * Uuid provides constants and static methods for working with and generating UUIDs @@ -194,6 +200,12 @@ class Uuid implements UuidInterface */ private static $factory = null; + /** + * @var bool flag to detect if the UUID factory was replaced internally, which disables all optimizations + * for the default/happy path internal scenarios + */ + private static $factoryReplaced = false; + /** * @var CodecInterface */ @@ -273,7 +285,7 @@ class Uuid implements UuidInterface */ public function serialize(): string { - return $this->toString(); + return $this->getBytes(); } /** @@ -286,8 +298,14 @@ class Uuid implements UuidInterface */ public function unserialize($serialized): void { - /** @var \Ramsey\Uuid\Uuid $uuid */ - $uuid = self::fromString($serialized); + if (strlen($serialized) === 16) { + /** @var Uuid $uuid */ + $uuid = self::getFactory()->fromBytes($serialized); + } else { + /** @var Uuid $uuid */ + $uuid = self::getFactory()->fromString($serialized); + } + $this->codec = $uuid->codec; $this->numberConverter = $uuid->numberConverter; $this->fields = $uuid->fields; @@ -369,6 +387,11 @@ class Uuid implements UuidInterface */ public static function setFactory(UuidFactoryInterface $factory): void { + // Note: non-strict equality is intentional here. If the factory is configured differently, every assumption + // around purity is broken, and we have to internally decide everything differently. + // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator + self::$factoryReplaced = ($factory != new UuidFactory()); + self::$factory = $factory; } @@ -382,9 +405,31 @@ class Uuid implements UuidInterface * * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, * but under constant factory setups, this method operates in functionally pure manners + * + * @psalm-suppress ImpureStaticProperty we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. */ public static function fromBytes(string $bytes): UuidInterface { + if (! self::$factoryReplaced && strlen($bytes) === 16) { + $base16Uuid = bin2hex($bytes); + + // Note: we are calling `fromString` internally because we don't know if the given `$bytes` is a valid UUID + return self::fromString( + substr($base16Uuid, 0, 8) + . '-' + . substr($base16Uuid, 8, 4) + . '-' + . substr($base16Uuid, 12, 4) + . '-' + . substr($base16Uuid, 16, 4) + . '-' + . substr($base16Uuid, 20, 12) + ); + } + return self::getFactory()->fromBytes($bytes); } @@ -398,9 +443,18 @@ class Uuid implements UuidInterface * * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, * but under constant factory setups, this method operates in functionally pure manners + * + * @psalm-suppress ImpureStaticProperty we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. */ public static function fromString(string $uuid): UuidInterface { + if (! self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) { + return new LazyUuidFromString(strtolower($uuid)); + } + return self::getFactory()->fromString($uuid); } @@ -514,6 +568,11 @@ class Uuid implements UuidInterface * @return UuidInterface A UuidInterface instance that represents a * version 3 UUID * + * @psalm-suppress ImpureMethodCall we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. + * * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, * but under constant factory setups, this method operates in functionally pure manners */ @@ -545,6 +604,11 @@ class Uuid implements UuidInterface * * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, * but under constant factory setups, this method operates in functionally pure manners + * + * @psalm-suppress ImpureMethodCall we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. */ public static function uuid5($ns, string $name): UuidInterface { diff --git a/src/UuidFactory.php b/src/UuidFactory.php index 2d8b3a1..feddef8 100644 --- a/src/UuidFactory.php +++ b/src/UuidFactory.php @@ -24,6 +24,7 @@ use Ramsey\Uuid\Generator\DefaultTimeGenerator; use Ramsey\Uuid\Generator\NameGeneratorInterface; use Ramsey\Uuid\Generator\RandomGeneratorInterface; use Ramsey\Uuid\Generator\TimeGeneratorInterface; +use Ramsey\Uuid\Lazy\LazyUuidFromString; use Ramsey\Uuid\Provider\NodeProviderInterface; use Ramsey\Uuid\Provider\Time\FixedTimeProvider; use Ramsey\Uuid\Type\Hexadecimal; @@ -94,11 +95,16 @@ class UuidFactory implements UuidFactoryInterface */ private $validator; + /** @var bool whether the feature set was provided from outside, or we can operate under "default" assumptions */ + private $isDefaultFeatureSet; + /** * @param FeatureSet $features A set of available features in the current environment */ public function __construct(?FeatureSet $features = null) { + $this->isDefaultFeatureSet = $features === null; + $features = $features ?: new FeatureSet(); $this->codec = $features->getCodec(); @@ -128,6 +134,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setCodec(CodecInterface $codec): void { + $this->isDefaultFeatureSet = false; + $this->codec = $codec; } @@ -147,6 +155,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setNameGenerator(NameGeneratorInterface $nameGenerator): void { + $this->isDefaultFeatureSet = false; + $this->nameGenerator = $nameGenerator; } @@ -182,6 +192,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setTimeGenerator(TimeGeneratorInterface $generator): void { + $this->isDefaultFeatureSet = false; + $this->timeGenerator = $generator; } @@ -201,6 +213,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setDceSecurityGenerator(DceSecurityGeneratorInterface $generator): void { + $this->isDefaultFeatureSet = false; + $this->dceSecurityGenerator = $generator; } @@ -220,6 +234,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setRandomGenerator(RandomGeneratorInterface $generator): void { + $this->isDefaultFeatureSet = false; + $this->randomGenerator = $generator; } @@ -231,6 +247,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setNumberConverter(NumberConverterInterface $converter): void { + $this->isDefaultFeatureSet = false; + $this->numberConverter = $converter; } @@ -250,6 +268,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setUuidBuilder(UuidBuilderInterface $builder): void { + $this->isDefaultFeatureSet = false; + $this->uuidBuilder = $builder; } @@ -269,6 +289,8 @@ class UuidFactory implements UuidFactoryInterface */ public function setValidator(ValidatorInterface $validator): void { + $this->isDefaultFeatureSet = false; + $this->validator = $validator; } @@ -458,6 +480,10 @@ class UuidFactory implements UuidFactoryInterface $bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2); $bytes = substr_replace($bytes, $clockSeqHiAndReserved, 8, 2); + if ($this->isDefaultFeatureSet) { + return LazyUuidFromString::fromBytes($bytes); + } + return $this->uuid($bytes); } } diff --git a/src/Validator/GenericValidator.php b/src/Validator/GenericValidator.php index f6a6010..fd60955 100644 --- a/src/Validator/GenericValidator.php +++ b/src/Validator/GenericValidator.php @@ -29,7 +29,7 @@ final class GenericValidator implements ValidatorInterface /** * Regular expression pattern for matching a UUID of any variant. */ - private const 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}$'; + private const VALID_PATTERN = '\A[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}\z'; /** * @psalm-return non-empty-string @@ -45,6 +45,6 @@ final class GenericValidator implements ValidatorInterface { $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid); - return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/D', $uuid); + return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid); } } diff --git a/tests/Builder/FallbackBuilderTest.php b/tests/Builder/FallbackBuilderTest.php index b9f55b1..7b63b6c 100644 --- a/tests/Builder/FallbackBuilderTest.php +++ b/tests/Builder/FallbackBuilderTest.php @@ -24,7 +24,6 @@ use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder; use Ramsey\Uuid\Rfc4122\UuidV1; use Ramsey\Uuid\Rfc4122\UuidV2; use Ramsey\Uuid\Test\TestCase; -use Ramsey\Uuid\UuidInterface; use Ramsey\Uuid\Validator\GenericValidator; class FallbackBuilderTest extends TestCase @@ -112,7 +111,6 @@ class FallbackBuilderTest extends TestCase try { $uuid = $builder->build($codec, $bytes); - $this->assertInstanceOf(UuidInterface::class, $uuid); if (($uuid instanceof UuidV1) || ($uuid instanceof UuidV2) || ($uuid instanceof UuidV6)) { $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); diff --git a/tests/Codec/GuidStringCodecTest.php b/tests/Codec/GuidStringCodecTest.php index c70d572..4394586 100644 --- a/tests/Codec/GuidStringCodecTest.php +++ b/tests/Codec/GuidStringCodecTest.php @@ -106,7 +106,7 @@ class GuidStringCodecTest extends TestCase $codec = new GuidStringCodec($this->builder); $result = $codec->decode($string); - $this->assertEquals($this->uuid, $result); + $this->assertSame($this->uuid, $result); } public function testDecodeBytesReturnsUuid(): void @@ -117,6 +117,6 @@ class GuidStringCodecTest extends TestCase $this->builder->method('build') ->willReturn($this->uuid); $result = $codec->decodeBytes($bytes); - $this->assertEquals($this->uuid, $result); + $this->assertSame($this->uuid, $result); } } diff --git a/tests/Codec/OrderedTimeCodecTest.php b/tests/Codec/OrderedTimeCodecTest.php index fbdddaf..1cf0d44 100644 --- a/tests/Codec/OrderedTimeCodecTest.php +++ b/tests/Codec/OrderedTimeCodecTest.php @@ -83,7 +83,7 @@ class OrderedTimeCodecTest extends TestCase ->willReturn($this->fields); $codec = new OrderedTimeCodec($this->builder); $result = $codec->encode($this->uuid); - $this->assertEquals($this->uuidString, $result); + $this->assertSame($this->uuidString, $result); } public function testEncodeBinary(): void @@ -121,7 +121,7 @@ class OrderedTimeCodecTest extends TestCase ->willReturn($this->uuid); $codec = new OrderedTimeCodec($this->builder); $result = $codec->decode($string); - $this->assertEquals($this->uuid, $result); + $this->assertSame($this->uuid, $result); } public function testDecodeBytesRearrangesFields(): void diff --git a/tests/Codec/StringCodecTest.php b/tests/Codec/StringCodecTest.php index 3ded53c..7aa71f9 100644 --- a/tests/Codec/StringCodecTest.php +++ b/tests/Codec/StringCodecTest.php @@ -68,7 +68,7 @@ class StringCodecTest extends TestCase ->willReturn($this->fields); $codec = new StringCodec($this->builder); $result = $codec->encode($this->uuid); - $this->assertEquals($this->uuidString, $result); + $this->assertSame($this->uuidString, $result); } public function testEncodeBinaryReturnsBinaryString(): void @@ -123,7 +123,7 @@ class StringCodecTest extends TestCase ->willReturn($this->uuid); $codec = new StringCodec($this->builder); $result = $codec->decode($string); - $this->assertEquals($this->uuid, $result); + $this->assertSame($this->uuid, $result); } public function testDecodeBytesThrowsExceptionWhenBytesStringNotSixteenCharacters(): void @@ -145,6 +145,6 @@ class StringCodecTest extends TestCase $this->builder->method('build') ->willReturn($this->uuid); $result = $codec->decodeBytes($bytes); - $this->assertEquals($this->uuid, $result); + $this->assertSame($this->uuid, $result); } } diff --git a/tests/Generator/CombGeneratorTest.php b/tests/Generator/CombGeneratorTest.php index ee0de3f..6649b49 100644 --- a/tests/Generator/CombGeneratorTest.php +++ b/tests/Generator/CombGeneratorTest.php @@ -84,7 +84,7 @@ class CombGeneratorTest extends TestCase $generator = new CombGenerator($randomGenerator, $converter); $returned = $generator->generate($length); $this->assertIsString($returned); - $this->assertEquals($expected, $returned); + $this->assertSame($expected, $returned); } /** diff --git a/tests/Generator/PeclUuidRandomGeneratorTest.php b/tests/Generator/PeclUuidRandomGeneratorTest.php index 3a8e133..aaa5d2e 100644 --- a/tests/Generator/PeclUuidRandomGeneratorTest.php +++ b/tests/Generator/PeclUuidRandomGeneratorTest.php @@ -28,7 +28,7 @@ class PeclUuidRandomGeneratorTest extends PeclUuidTestCase $generator = new PeclUuidRandomGenerator(); $uuid = $generator->generate($this->length); - $this->assertEquals($this->uuidBinary, $uuid); + $this->assertSame($this->uuidBinary, $uuid); $create->verifyInvoked([UUID_TYPE_RANDOM]); $parse->verifyInvoked([$this->uuidString]); } @@ -44,7 +44,7 @@ class PeclUuidRandomGeneratorTest extends PeclUuidTestCase $generator = new PeclUuidRandomGenerator(); $uuid = $generator->generate($this->length); - $this->assertEquals($this->uuidBinary, $uuid); + $this->assertSame($this->uuidBinary, $uuid); $create->verifyInvoked([UUID_TYPE_RANDOM]); $parse->verifyInvoked([$this->uuidString]); } diff --git a/tests/Generator/PeclUuidTimeGeneratorTest.php b/tests/Generator/PeclUuidTimeGeneratorTest.php index 61fe8ac..b404e5f 100644 --- a/tests/Generator/PeclUuidTimeGeneratorTest.php +++ b/tests/Generator/PeclUuidTimeGeneratorTest.php @@ -23,7 +23,7 @@ class PeclUuidTimeGeneratorTest extends PeclUuidTestCase $generator = new PeclUuidTimeGenerator(); $uuid = $generator->generate(); - $this->assertEquals($this->uuidBinary, $uuid); + $this->assertSame($this->uuidBinary, $uuid); $create->verifyInvoked([UUID_TYPE_TIME]); $parse->verifyInvoked([$this->uuidString]); } @@ -39,7 +39,7 @@ class PeclUuidTimeGeneratorTest extends PeclUuidTestCase $generator = new PeclUuidTimeGenerator(); $uuid = $generator->generate(); - $this->assertEquals($this->uuidBinary, $uuid); + $this->assertSame($this->uuidBinary, $uuid); $create->verifyInvoked([UUID_TYPE_TIME]); $parse->verifyInvoked([$this->uuidString]); } diff --git a/tests/Generator/RandomBytesGeneratorTest.php b/tests/Generator/RandomBytesGeneratorTest.php index 83b8fbc..dca6618 100644 --- a/tests/Generator/RandomBytesGeneratorTest.php +++ b/tests/Generator/RandomBytesGeneratorTest.php @@ -55,7 +55,7 @@ class RandomBytesGeneratorTest extends TestCase $bytes = hex2bin($hex); AspectMock::func('Ramsey\Uuid\Generator', 'random_bytes', $bytes); $generator = new RandomBytesGenerator(); - $this->assertEquals($bytes, $generator->generate($length)); + $this->assertSame($bytes, $generator->generate($length)); } /** diff --git a/tests/Generator/RandomLibAdapterTest.php b/tests/Generator/RandomLibAdapterTest.php index 55a8924..438f6f1 100644 --- a/tests/Generator/RandomLibAdapterTest.php +++ b/tests/Generator/RandomLibAdapterTest.php @@ -66,6 +66,6 @@ class RandomLibAdapterTest extends TestCase $adapter = new RandomLibAdapter($generator); $result = $adapter->generate(1); - $this->assertEquals('random-string', $result); + $this->assertSame('random-string', $result); } } diff --git a/tests/Guid/FieldsTest.php b/tests/Guid/FieldsTest.php index 2df25f6..d55f4b1 100644 --- a/tests/Guid/FieldsTest.php +++ b/tests/Guid/FieldsTest.php @@ -199,6 +199,6 @@ class FieldsTest extends TestCase $serializedFields = serialize($fields); $unserializedFields = unserialize($serializedFields); - $this->assertEquals($fields, $unserializedFields); + $this->assertSame($fields->getBytes(), $unserializedFields->getBytes()); } } diff --git a/tests/Nonstandard/FieldsTest.php b/tests/Nonstandard/FieldsTest.php index 842cd8a..119196a 100644 --- a/tests/Nonstandard/FieldsTest.php +++ b/tests/Nonstandard/FieldsTest.php @@ -75,6 +75,6 @@ class FieldsTest extends TestCase $serializedFields = serialize($fields); $unserializedFields = unserialize($serializedFields); - $this->assertEquals($fields, $unserializedFields); + $this->assertSame($fields->getBytes(), $unserializedFields->getBytes()); } } diff --git a/tests/Nonstandard/UuidV6Test.php b/tests/Nonstandard/UuidV6Test.php index 3c0300e..899f032 100644 --- a/tests/Nonstandard/UuidV6Test.php +++ b/tests/Nonstandard/UuidV6Test.php @@ -11,9 +11,9 @@ use Ramsey\Uuid\Converter\NumberConverterInterface; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Exception\DateTimeException; use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Lazy\LazyUuidFromString; use Ramsey\Uuid\Nonstandard\UuidV6; use Ramsey\Uuid\Rfc4122\FieldsInterface; -use Ramsey\Uuid\Rfc4122\UuidV1; use Ramsey\Uuid\Test\TestCase; use Ramsey\Uuid\Type\Hexadecimal; use Ramsey\Uuid\Type\Time; @@ -123,8 +123,9 @@ class UuidV6Test extends TestCase */ public function testFromUuidV1(string $uuidv6, string $uuidv1): void { - /** @var UuidV1 $uuid1 */ - $uuid1 = Uuid::fromString($uuidv1); + /** @var LazyUuidFromString $uuid */ + $uuid = Uuid::fromString($uuidv1); + $uuid1 = $uuid->toUuidV1(); $uuid6 = UuidV6::fromUuidV1($uuid1); $this->assertSame($uuidv1, $uuid1->toString()); diff --git a/tests/Provider/Node/FallbackNodeProviderTest.php b/tests/Provider/Node/FallbackNodeProviderTest.php index a2b8baf..e8aa13a 100644 --- a/tests/Provider/Node/FallbackNodeProviderTest.php +++ b/tests/Provider/Node/FallbackNodeProviderTest.php @@ -50,7 +50,7 @@ class FallbackNodeProviderTest extends TestCase )); $node = $provider->getNode(); - $this->assertEquals('57764a07f756', $node); + $this->assertSame('57764a07f756', $node->toString()); } public function testGetNodeThrowsExceptionWhenNoNodesFound(): void diff --git a/tests/Provider/Node/SystemNodeProviderTest.php b/tests/Provider/Node/SystemNodeProviderTest.php index bc27d1d..4e98e78 100644 --- a/tests/Provider/Node/SystemNodeProviderTest.php +++ b/tests/Provider/Node/SystemNodeProviderTest.php @@ -151,7 +151,7 @@ class SystemNodeProviderTest extends TestCase /* Assert */ $this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], ['PHP_OS'], ['disable_functions']); - $this->assertEquals($expected, $node->toString()); + $this->assertSame($expected, $node->toString()); } /** @@ -211,7 +211,7 @@ class SystemNodeProviderTest extends TestCase /* Assert */ $this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], ['PHP_OS'], ['disable_functions']); - $this->assertEquals('aabbccddeeff', $node->toString()); + $this->assertSame('aabbccddeeff', $node->toString()); } /** @@ -359,7 +359,7 @@ class SystemNodeProviderTest extends TestCase /* Assert */ $this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], ['PHP_OS'], ['disable_functions']); - $this->assertEquals($node->toString(), $node2->toString()); + $this->assertSame($node->toString(), $node2->toString()); } /** @@ -387,7 +387,7 @@ class SystemNodeProviderTest extends TestCase /* Assert */ $this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], ['PHP_OS'], ['disable_functions']); - $this->assertEquals($node->toString(), $node2->toString()); + $this->assertSame($node->toString(), $node2->toString()); } /** @@ -442,7 +442,7 @@ class SystemNodeProviderTest extends TestCase $isReadableAssert ); - $this->assertEquals('010203040506', $node->toString()); + $this->assertSame('010203040506', $node->toString()); } /** @@ -475,7 +475,7 @@ class SystemNodeProviderTest extends TestCase ['disable_functions'] ); - $this->assertEquals('010203040506', $node->toString()); + $this->assertSame('010203040506', $node->toString()); } /** @@ -508,7 +508,7 @@ class SystemNodeProviderTest extends TestCase ['disable_functions'] ); - $this->assertEquals('010203040506', $node->toString()); + $this->assertSame('010203040506', $node->toString()); } /** @@ -543,7 +543,7 @@ class SystemNodeProviderTest extends TestCase ['mock address path 1', 'mock address path 2'] ); - $this->assertEquals('010203040506', $node->toString()); + $this->assertSame('010203040506', $node->toString()); } /** diff --git a/tests/Rfc4122/FieldsTest.php b/tests/Rfc4122/FieldsTest.php index 40282a6..39b36eb 100644 --- a/tests/Rfc4122/FieldsTest.php +++ b/tests/Rfc4122/FieldsTest.php @@ -210,6 +210,16 @@ class FieldsTest extends TestCase $serializedFields = serialize($fields); $unserializedFields = unserialize($serializedFields); - $this->assertEquals($fields, $unserializedFields); + $this->assertSame($fields->getBytes(), $unserializedFields->getBytes()); + } + + public function testSerializingFieldsWithOldFormat(): void + { + $fields = new Fields("\xb3\xcd\x58\x6a\xe3\xca\x44\xf3\x98\x8c\xf4\xd6\x66\xc1\xbf\x4d"); + + $serializedFields = 'C:26:"Ramsey\Uuid\Rfc4122\Fields":24:{s81YauPKRPOYjPTWZsG/TQ==}'; + $unserializedFields = unserialize($serializedFields); + + $this->assertSame($fields->getBytes(), $unserializedFields->getBytes()); } } diff --git a/tests/Rfc4122/ValidatorTest.php b/tests/Rfc4122/ValidatorTest.php index 415e20f..e8b9770 100644 --- a/tests/Rfc4122/ValidatorTest.php +++ b/tests/Rfc4122/ValidatorTest.php @@ -75,13 +75,25 @@ class ValidatorTest extends TestCase 'value' => 'ff6f8cb0-c57da-51e1-9b21-0800200c9a66', 'expected' => false, ], + [ + 'value' => "ff6f8cb0-c57d-11e1-1b21-0800200c9a66\n", + 'expected' => false, + ], + [ + 'value' => "\nff6f8cb0-c57d-11e1-1b21-0800200c9a66", + 'expected' => false, + ], + [ + 'value' => "\nff6f8cb0-c57d-11e1-1b21-0800200c9a66\n", + 'expected' => false, + ], ]); } public function testGetPattern(): void { - $expectedPattern = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-' - . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'; + $expectedPattern = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-' + . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z'; $validator = new Validator(); diff --git a/tests/UuidFactoryTest.php b/tests/UuidFactoryTest.php index 0ca2540..0102b18 100644 --- a/tests/UuidFactoryTest.php +++ b/tests/UuidFactoryTest.php @@ -20,7 +20,6 @@ use Ramsey\Uuid\Generator\NameGeneratorInterface; use Ramsey\Uuid\Generator\RandomGeneratorInterface; use Ramsey\Uuid\Generator\TimeGeneratorInterface; use Ramsey\Uuid\Provider\NodeProviderInterface; -use Ramsey\Uuid\Rfc4122\UuidV1; use Ramsey\Uuid\Type\Hexadecimal; use Ramsey\Uuid\UuidFactory; use Ramsey\Uuid\Validator\ValidatorInterface; @@ -58,7 +57,7 @@ class UuidFactoryTest extends TestCase $uuid = $factory->fromString($uuidUpper); - $this->assertEquals($uuidString, $uuid->toString()); + $this->assertSame($uuidString, $uuid->toString()); } public function testGettersReturnValueFromFeatureSet(): void @@ -120,22 +119,22 @@ class UuidFactoryTest extends TestCase /** @var MockObject & CodecInterface $codec */ $codec = $this->getMockBuilder(CodecInterface::class)->getMock(); $uuidFactory->setCodec($codec); - $this->assertEquals($codec, $uuidFactory->getCodec()); + $this->assertSame($codec, $uuidFactory->getCodec()); /** @var MockObject & TimeGeneratorInterface $timeGenerator */ $timeGenerator = $this->getMockBuilder(TimeGeneratorInterface::class)->getMock(); $uuidFactory->setTimeGenerator($timeGenerator); - $this->assertEquals($timeGenerator, $uuidFactory->getTimeGenerator()); + $this->assertSame($timeGenerator, $uuidFactory->getTimeGenerator()); /** @var MockObject & NumberConverterInterface $numberConverter */ $numberConverter = $this->getMockBuilder(NumberConverterInterface::class)->getMock(); $uuidFactory->setNumberConverter($numberConverter); - $this->assertEquals($numberConverter, $uuidFactory->getNumberConverter()); + $this->assertSame($numberConverter, $uuidFactory->getNumberConverter()); /** @var MockObject & UuidBuilderInterface $uuidBuilder */ $uuidBuilder = $this->getMockBuilder(UuidBuilderInterface::class)->getMock(); $uuidFactory->setUuidBuilder($uuidBuilder); - $this->assertEquals($uuidBuilder, $uuidFactory->getUuidBuilder()); + $this->assertSame($uuidBuilder, $uuidFactory->getUuidBuilder()); } /** @@ -150,10 +149,8 @@ class UuidFactoryTest extends TestCase ): void { $factory = new UuidFactory(); - /** @var UuidV1 $uuid */ $uuid = $factory->fromDateTime($dateTime, $node, $clockSeq); - $this->assertInstanceOf(UuidV1::class, $uuid); $this->assertStringMatchesFormat($expectedUuidFormat, $uuid->toString()); $this->assertSame($expectedTime, $uuid->getDateTime()->format('U.u')); } diff --git a/tests/UuidTest.php b/tests/UuidTest.php index a77108f..fccde37 100644 --- a/tests/UuidTest.php +++ b/tests/UuidTest.php @@ -24,17 +24,11 @@ use Ramsey\Uuid\Generator\CombGenerator; use Ramsey\Uuid\Generator\RandomGeneratorFactory; use Ramsey\Uuid\Generator\RandomGeneratorInterface; use Ramsey\Uuid\Guid\Guid; -use Ramsey\Uuid\Nonstandard\Uuid as NonstandardUuid; -use Ramsey\Uuid\Nonstandard\UuidV6; +use Ramsey\Uuid\Lazy\LazyUuidFromString; use Ramsey\Uuid\Provider\Node\RandomNodeProvider; use Ramsey\Uuid\Provider\Time\FixedTimeProvider; use Ramsey\Uuid\Rfc4122\FieldsInterface; -use Ramsey\Uuid\Rfc4122\NilUuid; use Ramsey\Uuid\Rfc4122\UuidV1; -use Ramsey\Uuid\Rfc4122\UuidV2; -use Ramsey\Uuid\Rfc4122\UuidV3; -use Ramsey\Uuid\Rfc4122\UuidV4; -use Ramsey\Uuid\Rfc4122\UuidV5; use Ramsey\Uuid\Type\Hexadecimal; use Ramsey\Uuid\Type\Time; use Ramsey\Uuid\Uuid; @@ -68,9 +62,11 @@ class UuidTest extends TestCase public function testFromString(): void { - $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertInstanceOf(Uuid::class, $uuid); - $this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); + $this->assertSame( + 'ff6f8cb0-c57d-11e1-9b21-0800200c9a66', + Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66') + ->toString() + ); } /** @@ -85,8 +81,6 @@ class UuidTest extends TestCase $guid = Guid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertInstanceOf(Uuid::class, $guid); - // UUID's and GUID's share the same textual representation. $this->assertSame($uuid->toString(), $guid->toString()); @@ -97,8 +91,7 @@ class UuidTest extends TestCase public function testFromStringWithCurlyBraces(): void { $uuid = Uuid::fromString('{ff6f8cb0-c57d-11e1-9b21-0800200c9a66}'); - $this->assertInstanceOf(Uuid::class, $uuid); - $this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); + $this->assertSame('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); } public function testFromStringWithInvalidUuidString(): void @@ -109,6 +102,14 @@ class UuidTest extends TestCase Uuid::fromString('ff6f8cb0-c57d-11e1-9b21'); } + public function testFromStringWithLeadingNewLine(): void + { + $this->expectException(InvalidUuidStringException::class); + $this->expectExceptionMessage('Invalid UUID string:'); + + Uuid::fromString("\nd0d5f586-21d1-470c-8088-55c8857728dc"); + } + public function testFromStringWithTrailingNewLine(): void { $this->expectException(InvalidUuidStringException::class); @@ -120,57 +121,56 @@ class UuidTest extends TestCase public function testFromStringWithUrn(): void { $uuid = Uuid::fromString('urn:uuid:ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertInstanceOf(Uuid::class, $uuid); - $this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); + $this->assertSame('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); } public function testGetBytes(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals(16, strlen($uuid->getBytes())); - $this->assertEquals('/2+MsMV9EeGbIQgAIAyaZg==', base64_encode($uuid->getBytes())); + $this->assertSame(16, strlen($uuid->getBytes())); + $this->assertSame('/2+MsMV9EeGbIQgAIAyaZg==', base64_encode($uuid->getBytes())); } public function testGetClockSeqHiAndReserved(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals(155, $uuid->getClockSeqHiAndReserved()); + $this->assertSame('155', $uuid->getClockSeqHiAndReserved()); } public function testGetClockSeqHiAndReservedHex(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('9b', $uuid->getClockSeqHiAndReservedHex()); + $this->assertSame('9b', $uuid->getClockSeqHiAndReservedHex()); } public function testGetClockSeqLow(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals(33, $uuid->getClockSeqLow()); + $this->assertSame('33', $uuid->getClockSeqLow()); } public function testGetClockSeqLowHex(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('21', $uuid->getClockSeqLowHex()); + $this->assertSame('21', $uuid->getClockSeqLowHex()); } public function testGetClockSequence(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals(6945, $uuid->getClockSequence()); + $this->assertSame('6945', $uuid->getClockSequence()); } public function testGetClockSequenceHex(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('1b21', $uuid->getClockSequenceHex()); + $this->assertSame('1b21', $uuid->getClockSequenceHex()); } public function testGetDateTime(): void @@ -316,7 +316,7 @@ class UuidTest extends TestCase public function testGetMostSignificantBitsHex(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('ff6f8cb0c57d11e1', $uuid->getMostSignificantBitsHex()); + $this->assertSame('ff6f8cb0c57d11e1', $uuid->getMostSignificantBitsHex()); } public function testGetNode(): void @@ -329,20 +329,20 @@ class UuidTest extends TestCase public function testGetNodeHex(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('0800200c9a66', $uuid->getNodeHex()); + $this->assertSame('0800200c9a66', $uuid->getNodeHex()); } public function testGetTimeHiAndVersion(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals(4577, $uuid->getTimeHiAndVersion()); + $this->assertSame('4577', $uuid->getTimeHiAndVersion()); } public function testGetTimeHiAndVersionHex(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('11e1', $uuid->getTimeHiAndVersionHex()); + $this->assertSame('11e1', $uuid->getTimeHiAndVersionHex()); } public function testGetTimeLow(): void @@ -355,20 +355,20 @@ class UuidTest extends TestCase public function testGetTimeLowHex(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('ff6f8cb0', $uuid->getTimeLowHex()); + $this->assertSame('ff6f8cb0', $uuid->getTimeLowHex()); } public function testGetTimeMid(): void { /** @var Uuid $uuid */ $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals(50557, $uuid->getTimeMid()); + $this->assertSame('50557', $uuid->getTimeMid()); } public function testGetTimeMidHex(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('c57d', $uuid->getTimeMidHex()); + $this->assertSame('c57d', $uuid->getTimeMidHex()); } public function testGetTimestamp(): void @@ -388,11 +388,11 @@ class UuidTest extends TestCase { // Check for a recent date $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('1e1c57dff6f8cb0', $uuid->getTimestampHex()); + $this->assertSame('1e1c57dff6f8cb0', $uuid->getTimestampHex()); // Check for an old date $uuid = Uuid::fromString('0901e600-0154-1000-9b21-0800200c9a66'); - $this->assertEquals('00001540901e600', $uuid->getTimestampHex()); + $this->assertSame('00001540901e600', $uuid->getTimestampHex()); } public function testGetTimestampFromNonVersion1Uuid(): void @@ -421,7 +421,7 @@ class UuidTest extends TestCase public function testGetUrn(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('urn:uuid:ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->getUrn()); + $this->assertSame('urn:uuid:ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->getUrn()); } /** @@ -461,79 +461,76 @@ class UuidTest extends TestCase public function testGetVersionForVersion1(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals(1, $uuid->getVersion()); + $this->assertSame(1, $uuid->getVersion()); } public function testGetVersionForVersion2(): void { $uuid = Uuid::fromString('6fa459ea-ee8a-2ca4-894e-db77e160355e'); - $this->assertEquals(2, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVersion()); } public function testGetVersionForVersion3(): void { $uuid = Uuid::fromString('6fa459ea-ee8a-3ca4-894e-db77e160355e'); - $this->assertEquals(3, $uuid->getVersion()); + $this->assertSame(3, $uuid->getVersion()); } public function testGetVersionForVersion4(): void { $uuid = Uuid::fromString('6fabf0bc-603a-42f2-925b-d9f779bd0032'); - $this->assertEquals(4, $uuid->getVersion()); + $this->assertSame(4, $uuid->getVersion()); } public function testGetVersionForVersion5(): void { $uuid = Uuid::fromString('886313e1-3b8a-5372-9b90-0c9aee199e5d'); - $this->assertEquals(5, $uuid->getVersion()); + $this->assertSame(5, $uuid->getVersion()); } public function testToString(): void { // Check with a recent date $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); - $this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', (string) $uuid); + $this->assertSame('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); + $this->assertSame('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', (string) $uuid); // Check with an old date $uuid = Uuid::fromString('0901e600-0154-1000-9b21-0800200c9a66'); - $this->assertEquals('0901e600-0154-1000-9b21-0800200c9a66', $uuid->toString()); - $this->assertEquals('0901e600-0154-1000-9b21-0800200c9a66', (string) $uuid); + $this->assertSame('0901e600-0154-1000-9b21-0800200c9a66', $uuid->toString()); + $this->assertSame('0901e600-0154-1000-9b21-0800200c9a66', (string) $uuid); } public function testUuid1(): void { $uuid = Uuid::uuid1(); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); } public function testUuid1WithNodeAndClockSequence(): void { /** @var Uuid $uuid */ $uuid = Uuid::uuid1('0800200c9a66', 0x1669); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); - $this->assertEquals(5737, $uuid->getClockSequence()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); + $this->assertSame('5737', $uuid->getClockSequence()); $this->assertSame('8796630719078', $uuid->getNode()); - $this->assertEquals('9669-0800200c9a66', substr($uuid->toString(), 19)); + $this->assertSame('9669-0800200c9a66', substr($uuid->toString(), 19)); } public function testUuid1WithHexadecimalObjectNodeAndClockSequence(): void { /** @var Uuid $uuid */ $uuid = Uuid::uuid1(new Hexadecimal('0800200c9a66'), 0x1669); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); - $this->assertEquals(5737, $uuid->getClockSequence()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); + $this->assertSame('5737', $uuid->getClockSequence()); $this->assertSame('8796630719078', $uuid->getNode()); - $this->assertEquals('9669-0800200c9a66', substr($uuid->toString(), 19)); + $this->assertSame('9669-0800200c9a66', substr($uuid->toString(), 19)); } public function testUuid1WithHexadecimalNode(): void @@ -541,11 +538,10 @@ class UuidTest extends TestCase /** @var Uuid $uuid */ $uuid = Uuid::uuid1('7160355e'); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); - $this->assertEquals('00007160355e', $uuid->getNodeHex()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); + $this->assertSame('00007160355e', $uuid->getNodeHex()); $this->assertSame('1902130526', $uuid->getNode()); } @@ -554,11 +550,10 @@ class UuidTest extends TestCase /** @var Uuid $uuid */ $uuid = Uuid::uuid1(new Hexadecimal('7160355e')); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); - $this->assertEquals('00007160355e', $uuid->getNodeHex()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); + $this->assertSame('00007160355e', $uuid->getNodeHex()); $this->assertSame('1902130526', $uuid->getNode()); } @@ -567,12 +562,11 @@ class UuidTest extends TestCase /** @var Uuid $uuid */ $uuid = Uuid::uuid1('71B0aD5e'); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); - $this->assertEquals('000071b0ad5e', $uuid->getNodeHex()); - $this->assertEquals('1907404126', $uuid->getNode()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); + $this->assertSame('000071b0ad5e', $uuid->getNodeHex()); + $this->assertSame('1907404126', $uuid->getNode()); } public function testUuid1WithOutOfBoundsNode(): void @@ -604,34 +598,30 @@ class UuidTest extends TestCase Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, false, true))); $uuid = Uuid::uuid1(); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); } public function testUuid1WithUserGeneratedRandomNode(): void { $uuid = Uuid::uuid1(new Hexadecimal((string) (new RandomNodeProvider())->getNode())); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(1, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(1, $uuid->getVersion()); } public function testUuid6(): void { $uuid = Uuid::uuid6(); - $this->assertInstanceOf(UuidV6::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(6, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(6, $uuid->getVersion()); } public function testUuid6WithNodeAndClockSequence(): void { $uuid = Uuid::uuid6(new Hexadecimal('0800200c9a66'), 0x1669); - $this->assertInstanceOf(UuidV6::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); $this->assertSame(2, $uuid->getVariant()); $this->assertSame(6, $uuid->getVersion()); @@ -644,7 +634,6 @@ class UuidTest extends TestCase { $uuid = Uuid::uuid6(new Hexadecimal('7160355e')); - $this->assertInstanceOf(UuidV6::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); $this->assertSame(2, $uuid->getVariant()); $this->assertSame(6, $uuid->getVersion()); @@ -655,7 +644,6 @@ class UuidTest extends TestCase { $uuid = Uuid::uuid6(new Hexadecimal('71B0aD5e')); - $this->assertInstanceOf(Uuid::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); $this->assertSame(2, $uuid->getVariant()); $this->assertSame(6, $uuid->getVersion()); @@ -683,19 +671,17 @@ class UuidTest extends TestCase Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, false, true))); $uuid = Uuid::uuid6(); - $this->assertInstanceOf(UuidV6::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(6, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(6, $uuid->getVersion()); } public function testUuid6WithUserGeneratedRandomNode(): void { $uuid = Uuid::uuid6(new Hexadecimal((string) (new RandomNodeProvider())->getNode())); - $this->assertInstanceOf(UuidV6::class, $uuid); $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime()); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(6, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(6, $uuid->getVersion()); } /** @@ -711,10 +697,9 @@ class UuidTest extends TestCase $uobj1 = Uuid::uuid3($ns, $name); $uobj2 = Uuid::uuid3(Uuid::fromString($ns), $name); - $this->assertEquals(2, $uobj1->getVariant()); - $this->assertEquals(3, $uobj1->getVersion()); - $this->assertEquals(Uuid::fromString($uuid), $uobj1); - $this->assertEquals((string) $uobj1, $uuid); + $this->assertSame(2, $uobj1->getVariant()); + $this->assertSame(3, $uobj1->getVersion()); + $this->assertSame(Uuid::fromString($uuid)->toString(), $uobj1->toString()); $this->assertTrue($uobj1->equals($uobj2)); } @@ -750,9 +735,8 @@ class UuidTest extends TestCase public function testUuid4(): void { $uuid = Uuid::uuid4(); - $this->assertInstanceOf(Uuid::class, $uuid); - $this->assertEquals(2, $uuid->getVariant()); - $this->assertEquals(4, $uuid->getVersion()); + $this->assertSame(2, $uuid->getVariant()); + $this->assertSame(4, $uuid->getVersion()); } /** @@ -830,7 +814,7 @@ class UuidTest extends TestCase $uuid = $factory->uuid4(); - $this->assertEquals(4, $uuid->getVersion()); + $this->assertSame(4, $uuid->getVersion()); } /** @@ -846,10 +830,9 @@ class UuidTest extends TestCase $uobj1 = Uuid::uuid5($ns, $name); $uobj2 = Uuid::uuid5(Uuid::fromString($ns), $name); - $this->assertEquals(2, $uobj1->getVariant()); - $this->assertEquals(5, $uobj1->getVersion()); - $this->assertEquals(Uuid::fromString($uuid), $uobj1); - $this->assertEquals((string) $uobj1, $uuid); + $this->assertSame(2, $uobj1->getVariant()); + $this->assertSame(5, $uobj1->getVersion()); + $this->assertSame(Uuid::fromString($uuid)->toString(), $uobj1->toString()); $this->assertTrue($uobj1->equals($uobj2)); } @@ -900,12 +883,12 @@ class UuidTest extends TestCase // msb are equal to those in $uuid3, lsb are less than in $uuid3 $uuid5 = Uuid::fromString('44cca71e-d13d-11e1-a959-c8bcc8a476f3'); - $this->assertEquals(0, $uuid1->compareTo($uuid2)); - $this->assertEquals(0, $uuid2->compareTo($uuid1)); - $this->assertEquals(-1, $uuid3->compareTo($uuid4)); - $this->assertEquals(1, $uuid4->compareTo($uuid3)); - $this->assertEquals(-1, $uuid5->compareTo($uuid3)); - $this->assertEquals(1, $uuid3->compareTo($uuid5)); + $this->assertSame(0, $uuid1->compareTo($uuid2)); + $this->assertSame(0, $uuid2->compareTo($uuid1)); + $this->assertSame(-1, $uuid3->compareTo($uuid4)); + $this->assertSame(1, $uuid4->compareTo($uuid3)); + $this->assertSame(-1, $uuid5->compareTo($uuid3)); + $this->assertSame(1, $uuid3->compareTo($uuid5)); } public function testCompareToReturnsZeroWhenDifferentCases(): void @@ -915,8 +898,8 @@ class UuidTest extends TestCase $uuid1 = Uuid::fromString($uuidString); $uuid2 = Uuid::fromString(strtoupper($uuidString)); - $this->assertEquals(0, $uuid1->compareTo($uuid2)); - $this->assertEquals(0, $uuid2->compareTo($uuid1)); + $this->assertSame(0, $uuid1->compareTo($uuid2)); + $this->assertSame(0, $uuid2->compareTo($uuid1)); } public function testEqualsReturnsTrueWhenDifferentCases(): void @@ -952,28 +935,28 @@ class UuidTest extends TestCase Uuid::setFactory(new UuidFactory($featureSet)); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); - $this->assertEquals('c4dbe7e2-097f-11e2-9669-00007ffffffe', (string) $uuidA); - $this->assertEquals('c4dbe7e2', $uuidA->getTimeLowHex()); - $this->assertEquals('097f', $uuidA->getTimeMidHex()); - $this->assertEquals('11e2', $uuidA->getTimeHiAndVersionHex()); + $this->assertSame('c4dbe7e2-097f-11e2-9669-00007ffffffe', (string) $uuidA); + $this->assertSame('c4dbe7e2', $uuidA->getTimeLowHex()); + $this->assertSame('097f', $uuidA->getTimeMidHex()); + $this->assertSame('11e2', $uuidA->getTimeHiAndVersionHex()); // For usec = 0 $timeOfDay->setUsec(0); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); - $this->assertEquals('c4b18100-097f-11e2-9669-00007ffffffe', (string) $uuidB); - $this->assertEquals('c4b18100', $uuidB->getTimeLowHex()); - $this->assertEquals('097f', $uuidB->getTimeMidHex()); - $this->assertEquals('11e2', $uuidB->getTimeHiAndVersionHex()); + $this->assertSame('c4b18100-097f-11e2-9669-00007ffffffe', (string) $uuidB); + $this->assertSame('c4b18100', $uuidB->getTimeLowHex()); + $this->assertSame('097f', $uuidB->getTimeMidHex()); + $this->assertSame('11e2', $uuidB->getTimeHiAndVersionHex()); // For usec = 999999 $timeOfDay->setUsec(999999); $uuidC = Uuid::uuid1(0x00007ffffffe, 0x1669); - $this->assertEquals('c54a1776-097f-11e2-9669-00007ffffffe', (string) $uuidC); - $this->assertEquals('c54a1776', $uuidC->getTimeLowHex()); - $this->assertEquals('097f', $uuidC->getTimeMidHex()); - $this->assertEquals('11e2', $uuidC->getTimeHiAndVersionHex()); + $this->assertSame('c54a1776-097f-11e2-9669-00007ffffffe', (string) $uuidC); + $this->assertSame('c54a1776', $uuidC->getTimeLowHex()); + $this->assertSame('097f', $uuidC->getTimeMidHex()); + $this->assertSame('11e2', $uuidC->getTimeHiAndVersionHex()); } public function testCalculateUuidTimeUpperLowerBounds(): void @@ -987,10 +970,10 @@ class UuidTest extends TestCase Uuid::setFactory(new UuidFactory($featureSet)); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); - $this->assertEquals('ff9785f6-ffff-1fff-9669-00007ffffffe', (string) $uuidA); - $this->assertEquals('ff9785f6', $uuidA->getTimeLowHex()); - $this->assertEquals('ffff', $uuidA->getTimeMidHex()); - $this->assertEquals('1fff', $uuidA->getTimeHiAndVersionHex()); + $this->assertSame('ff9785f6-ffff-1fff-9669-00007ffffffe', (string) $uuidA); + $this->assertSame('ff9785f6', $uuidA->getTimeLowHex()); + $this->assertSame('ffff', $uuidA->getTimeMidHex()); + $this->assertSame('1fff', $uuidA->getTimeHiAndVersionHex()); // 1582-10-15T00:00:00+00:00 $timeOfDay = new FixedTimeProvider(new Time('-12219292800', '0')); @@ -1000,10 +983,10 @@ class UuidTest extends TestCase Uuid::setFactory(new UuidFactory($featureSet)); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); - $this->assertEquals('00000000-0000-1000-9669-00007ffffffe', (string) $uuidB); - $this->assertEquals('00000000', $uuidB->getTimeLowHex()); - $this->assertEquals('0000', $uuidB->getTimeMidHex()); - $this->assertEquals('1000', $uuidB->getTimeHiAndVersionHex()); + $this->assertSame('00000000-0000-1000-9669-00007ffffffe', (string) $uuidB); + $this->assertSame('00000000', $uuidB->getTimeLowHex()); + $this->assertSame('0000', $uuidB->getTimeMidHex()); + $this->assertSame('1000', $uuidB->getTimeHiAndVersionHex()); } /** @@ -1044,8 +1027,8 @@ class UuidTest extends TestCase // Assert that the time matches $usecAdd = BigDecimal::of($usec)->dividedBy('1000000', 14, RoundingMode::HALF_UP); $testTime = BigDecimal::of($currentTime)->plus($usecAdd)->toScale(0, RoundingMode::DOWN); - $this->assertEquals((string) $testTime, $uuid64->getDateTime()->getTimestamp()); - $this->assertEquals((string) $testTime, $uuid32->getDateTime()->getTimestamp()); + $this->assertSame((string) $testTime, (string) $uuid64->getDateTime()->getTimestamp()); + $this->assertSame((string) $testTime, (string) $uuid32->getDateTime()->getTimestamp()); } $currentTime++; @@ -1075,8 +1058,16 @@ class UuidTest extends TestCase public function testUsingNilAsValidUuid(): void { - $this->assertInstanceOf(Uuid::class, Uuid::uuid3(Uuid::NIL, 'randomtext')); - $this->assertInstanceOf(Uuid::class, Uuid::uuid5(Uuid::NIL, 'randomtext')); + self::assertSame( + '0cb17687-6ec7-324b-833a-f1d101a7edb7', + Uuid::uuid3(Uuid::NIL, 'randomtext') + ->toString() + ); + self::assertSame( + '3b24c15b-1273-5628-ade4-fc67c6ede500', + Uuid::uuid5(Uuid::NIL, 'randomtext') + ->toString() + ); } public function testFromBytes(): void @@ -1162,7 +1153,6 @@ class UuidTest extends TestCase * as the Python UUID library. * * @param string[] $fields - * @param class-string $class * * @dataProvider providePythonTests */ @@ -1177,8 +1167,7 @@ class UuidTest extends TestCase string $time, string $clockSeq, int $variant, - ?int $version, - string $class + ?int $version ): void { $uuids = [ Uuid::fromString($string), @@ -1209,7 +1198,6 @@ class UuidTest extends TestCase $this->assertSame($clockSeq, $uuid->getClockSequenceHex()); $this->assertSame($variant, $uuid->getVariant()); $this->assertSame($version, $uuid->getVersion()); - $this->assertInstanceOf($class, $uuid); } } @@ -1242,7 +1230,6 @@ class UuidTest extends TestCase 'clock_seq' => '0000', 'variant' => Uuid::RESERVED_NCS, 'version' => null, - 'class' => NilUuid::class, ], [ 'string' => '00010203-0405-0607-0809-0a0b0c0d0e0f', @@ -1263,7 +1250,6 @@ class UuidTest extends TestCase 'clock_seq' => '0809', 'variant' => Uuid::RESERVED_NCS, 'version' => null, - 'class' => NonstandardUuid::class, ], [ 'string' => '02d9e6d5-9467-382e-8f9b-9300a64ac3cd', @@ -1284,7 +1270,6 @@ class UuidTest extends TestCase 'clock_seq' => '0f9b', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_HASH_MD5, - 'class' => UuidV3::class, ], [ 'string' => '12345678-1234-5678-1234-567812345678', @@ -1305,7 +1290,6 @@ class UuidTest extends TestCase 'clock_seq' => '1234', 'variant' => Uuid::RESERVED_NCS, 'version' => null, - 'class' => NonstandardUuid::class, ], [ 'string' => '6ba7b810-9dad-11d1-80b4-00c04fd430c8', @@ -1326,7 +1310,6 @@ class UuidTest extends TestCase 'clock_seq' => '00b4', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_TIME, - 'class' => UuidV1::class, ], [ 'string' => '6ba7b811-9dad-11d1-80b4-00c04fd430c8', @@ -1347,7 +1330,6 @@ class UuidTest extends TestCase 'clock_seq' => '00b4', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_TIME, - 'class' => UuidV1::class, ], [ 'string' => '6ba7b812-9dad-11d1-80b4-00c04fd430c8', @@ -1368,7 +1350,6 @@ class UuidTest extends TestCase 'clock_seq' => '00b4', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_TIME, - 'class' => UuidV1::class, ], [ 'string' => '6ba7b814-9dad-11d1-80b4-00c04fd430c8', @@ -1389,7 +1370,6 @@ class UuidTest extends TestCase 'clock_seq' => '00b4', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_TIME, - 'class' => UuidV1::class, ], [ 'string' => '7d444840-9dc0-11d1-b245-5ffdce74fad2', @@ -1410,7 +1390,6 @@ class UuidTest extends TestCase 'clock_seq' => '3245', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_TIME, - 'class' => UuidV1::class, ], [ 'string' => 'e902893a-9d22-3c7e-a7b8-d6e313b71d9f', @@ -1431,7 +1410,6 @@ class UuidTest extends TestCase 'clock_seq' => '27b8', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_HASH_MD5, - 'class' => UuidV3::class, ], [ 'string' => 'eb424026-6f54-4ef8-a4d0-bb658a1fc6cf', @@ -1452,7 +1430,6 @@ class UuidTest extends TestCase 'clock_seq' => '24d0', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_RANDOM, - 'class' => UuidV4::class, ], [ 'string' => 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', @@ -1473,7 +1450,6 @@ class UuidTest extends TestCase 'clock_seq' => '2765', 'variant' => Uuid::RFC_4122, 'version' => Uuid::UUID_TYPE_TIME, - 'class' => UuidV1::class, ], [ 'string' => 'fffefdfc-fffe-fffe-fffe-fffefdfcfbfa', @@ -1494,7 +1470,6 @@ class UuidTest extends TestCase 'clock_seq' => '3ffe', 'variant' => Uuid::RESERVED_FUTURE, 'version' => null, - 'class' => NonstandardUuid::class, ], [ 'string' => 'ffffffff-ffff-ffff-ffff-ffffffffffff', @@ -1515,7 +1490,6 @@ class UuidTest extends TestCase 'clock_seq' => '3fff', 'variant' => Uuid::RESERVED_FUTURE, 'version' => null, - 'class' => NonstandardUuid::class, ], ]; } @@ -1527,7 +1501,7 @@ class UuidTest extends TestCase { $uuid = Uuid::uuid1(); - $this->assertEquals('"' . $uuid->toString() . '"', json_encode($uuid)); + $this->assertSame('"' . $uuid->toString() . '"', json_encode($uuid)); } public function testSerialize(): void @@ -1538,6 +1512,16 @@ class UuidTest extends TestCase $this->assertTrue($uuid->equals($unserializedUuid)); } + public function testSerializeWithOldStringFormat(): void + { + $serialized = 'C:26:"Ramsey\Uuid\Rfc4122\UuidV4":36:{b3cd586a-e3ca-44f3-988c-f4d666c1bf4d}'; + + /** @var UuidInterface $unserializedUuid */ + $unserializedUuid = unserialize($serialized); + + $this->assertSame('b3cd586a-e3ca-44f3-988c-f4d666c1bf4d', $unserializedUuid->toString()); + } + public function testUuid3WithEmptyNamespace(): void { $this->expectException(InvalidArgumentException::class); @@ -1550,14 +1534,14 @@ class UuidTest extends TestCase { $uuid = Uuid::uuid3(Uuid::NIL, ''); - $this->assertEquals('4ae71336-e44b-39bf-b9d2-752e234818a5', $uuid->toString()); + $this->assertSame('4ae71336-e44b-39bf-b9d2-752e234818a5', $uuid->toString()); } public function testUuid3WithZeroName(): void { $uuid = Uuid::uuid3(Uuid::NIL, '0'); - $this->assertEquals('19826852-5007-3022-a72a-212f66e9fac3', $uuid->toString()); + $this->assertSame('19826852-5007-3022-a72a-212f66e9fac3', $uuid->toString()); } public function testUuid5WithEmptyNamespace(): void @@ -1572,14 +1556,14 @@ class UuidTest extends TestCase { $uuid = Uuid::uuid5(Uuid::NIL, ''); - $this->assertEquals('e129f27c-5103-5c5c-844b-cdf0a15e160d', $uuid->toString()); + $this->assertSame('e129f27c-5103-5c5c-844b-cdf0a15e160d', $uuid->toString()); } public function testUuid5WithZeroName(): void { $uuid = Uuid::uuid5(Uuid::NIL, '0'); - $this->assertEquals('b6c54489-38a0-5f50-a60a-fd8d76219cae', $uuid->toString()); + $this->assertSame('b6c54489-38a0-5f50-a60a-fd8d76219cae', $uuid->toString()); } /** @@ -1588,7 +1572,7 @@ class UuidTest extends TestCase public function testUuidVersionConstantForVersion1(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); - $this->assertEquals($uuid->getVersion(), Uuid::UUID_TYPE_TIME); + $this->assertSame($uuid->getVersion(), Uuid::UUID_TYPE_TIME); } /** @@ -1597,7 +1581,7 @@ class UuidTest extends TestCase public function testUuidVersionConstantForVersion2(): void { $uuid = Uuid::fromString('6fa459ea-ee8a-2ca4-894e-db77e160355e'); - $this->assertEquals($uuid->getVersion(), Uuid::UUID_TYPE_DCE_SECURITY); + $this->assertSame($uuid->getVersion(), Uuid::UUID_TYPE_DCE_SECURITY); } /** @@ -1606,7 +1590,7 @@ class UuidTest extends TestCase public function testUuidVersionConstantForVersion3(): void { $uuid = Uuid::fromString('6fa459ea-ee8a-3ca4-894e-db77e160355e'); - $this->assertEquals($uuid->getVersion(), Uuid::UUID_TYPE_HASH_MD5); + $this->assertSame($uuid->getVersion(), Uuid::UUID_TYPE_HASH_MD5); } /** @@ -1615,7 +1599,7 @@ class UuidTest extends TestCase public function testUuidVersionConstantForVersion4(): void { $uuid = Uuid::fromString('6fabf0bc-603a-42f2-925b-d9f779bd0032'); - $this->assertEquals($uuid->getVersion(), Uuid::UUID_TYPE_RANDOM); + $this->assertSame($uuid->getVersion(), Uuid::UUID_TYPE_RANDOM); } /** @@ -1624,13 +1608,13 @@ class UuidTest extends TestCase public function testUuidVersionConstantForVersion5(): void { $uuid = Uuid::fromString('886313e1-3b8a-5372-9b90-0c9aee199e5d'); - $this->assertEquals($uuid->getVersion(), Uuid::UUID_TYPE_HASH_SHA1); + $this->assertSame($uuid->getVersion(), Uuid::UUID_TYPE_HASH_SHA1); } public function testUuidVersionConstantForVersion6(): void { $uuid = Uuid::fromString('886313e1-3b8a-6372-9b90-0c9aee199e5d'); - $this->assertEquals($uuid->getVersion(), Uuid::UUID_TYPE_PEABODY); + $this->assertSame($uuid->getVersion(), Uuid::UUID_TYPE_PEABODY); } public function testGetDateTimeThrowsExceptionWhenDateTimeCannotParseDate(): void @@ -1661,17 +1645,49 @@ class UuidTest extends TestCase } /** - * @param class-string $expectedClass * @param mixed[] $args * * @dataProvider provideStaticMethods */ public function testStaticCreationMethodsReturnSpecificUuidInstances( - string $expectedClass, string $staticMethod, array $args = [] ): void { - $this->assertInstanceOf($expectedClass, Uuid::$staticMethod(...$args)); + $this->assertInstanceOf(LazyUuidFromString::class, Uuid::$staticMethod(...$args)); + } + + /** + * @param mixed[] $args + * + * @dataProvider provideStaticMethods + */ + public function testUuidInstancesBuiltFromStringAreEquivalentToTheirGeneratedCounterparts( + string $staticMethod, + array $args = [] + ): void { + $generated = Uuid::$staticMethod(...$args); + + self::assertSame( + (string) $generated, + (string) Uuid::fromString($generated->toString()) + ); + } + + /** + * @param mixed[] $args + * + * @dataProvider provideStaticMethods + */ + public function testUuidInstancesBuiltFromBytesAreEquivalentToTheirGeneratedCounterparts( + string $staticMethod, + array $args = [] + ): void { + $generated = Uuid::$staticMethod(...$args); + + self::assertSame( + (string) $generated, + (string) Uuid::fromBytes($generated->getBytes()) + ); } /** @@ -1680,11 +1696,11 @@ class UuidTest extends TestCase public function provideStaticMethods(): array { return [ - [UuidV1::class, 'uuid1'], - [UuidV2::class, 'uuid2', [Uuid::DCE_DOMAIN_PERSON]], - [UuidV3::class, 'uuid3', [Uuid::NIL, 'foobar']], - [UuidV4::class, 'uuid4'], - [UuidV5::class, 'uuid5', [Uuid::NIL, 'foobar']], + ['uuid1'], + ['uuid2', [Uuid::DCE_DOMAIN_PERSON]], + ['uuid3', [Uuid::NIL, 'foobar']], + ['uuid4'], + ['uuid5', [Uuid::NIL, 'foobar']], ]; } } diff --git a/tests/Validator/GenericValidatorTest.php b/tests/Validator/GenericValidatorTest.php index 5a8699b..4a41330 100644 --- a/tests/Validator/GenericValidatorTest.php +++ b/tests/Validator/GenericValidatorTest.php @@ -72,12 +72,24 @@ class GenericValidatorTest extends TestCase 'value' => 'ff6f8cb0-c57da-51e1-9b21-0800200c9a66', 'expected' => false, ], + [ + 'value' => "ff6f8cb0-c57d-11e1-1b21-0800200c9a66\n", + 'expected' => false, + ], + [ + 'value' => "\nff6f8cb0-c57d-11e1-1b21-0800200c9a66", + 'expected' => false, + ], + [ + 'value' => "\nff6f8cb0-c57d-11e1-1b21-0800200c9a66\n", + 'expected' => false, + ], ]); } public function testGetPattern(): void { - $expectedPattern = '^[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}$'; + $expectedPattern = '\A[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}\z'; $validator = new GenericValidator(); diff --git a/tests/benchmark/UuidFieldExtractionBench.php b/tests/benchmark/UuidFieldExtractionBench.php new file mode 100644 index 0000000..10bdb8a --- /dev/null +++ b/tests/benchmark/UuidFieldExtractionBench.php @@ -0,0 +1,86 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Benchmark; + +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +final class UuidFieldExtractionBench +{ + /** @var UuidInterface */ + private $uuid; + + public function __construct() + { + $this->uuid = Uuid::fromString('0ae0cac5-2a40-465c-99ed-3d331b7cf72a'); + } + + public function benchGetFields(): void + { + $this->uuid->getFields(); + } + + public function benchGetFields10Times(): void + { + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + $this->uuid->getFields(); + } + + public function benchGetHex(): void + { + $this->uuid->getHex(); + } + + public function benchGetHex10Times(): void + { + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + $this->uuid->getHex(); + } + + public function benchGetInteger(): void + { + $this->uuid->getInteger(); + } + + public function benchGetInteger10Times(): void + { + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + $this->uuid->getInteger(); + } +} diff --git a/tests/benchmark/UuidGenerationBench.php b/tests/benchmark/UuidGenerationBench.php new file mode 100644 index 0000000..6c6b5ca --- /dev/null +++ b/tests/benchmark/UuidGenerationBench.php @@ -0,0 +1,101 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Benchmark; + +use Ramsey\Uuid\Provider\Node\StaticNodeProvider; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerIdentifier; +use Ramsey\Uuid\Uuid; + +final class UuidGenerationBench +{ + /** @var Hexadecimal */ + private $node; + /** @var int */ + private $clockSequence; + /** @var IntegerIdentifier */ + private $localIdentifier; + /** @var \Ramsey\Uuid\UuidInterface */ + private $namespace; + + public function __construct() + { + $this->node = (new StaticNodeProvider(new Hexadecimal('121212121212'))) + ->getNode(); + $this->clockSequence = 16383; + $this->localIdentifier = new IntegerIdentifier(5); + $this->namespace = Uuid::fromString('c485840e-9389-4548-a276-aeecd9730e50'); + } + + public function benchUuid1GenerationWithoutParameters(): void + { + Uuid::uuid1(); + } + + public function benchUuid1GenerationWithNode(): void + { + Uuid::uuid1($this->node); + } + + public function benchUuid1GenerationWithNodeAndClockSequence(): void + { + Uuid::uuid1($this->node, $this->clockSequence); + } + + public function benchUuid2GenerationWithDomainAndLocalIdentifier(): void + { + Uuid::uuid2(Uuid::DCE_DOMAIN_ORG, $this->localIdentifier); + } + + public function benchUuid2GenerationWithDomainAndLocalIdentifierAndNode(): void + { + Uuid::uuid2(Uuid::DCE_DOMAIN_ORG, $this->localIdentifier, $this->node); + } + + public function benchUuid2GenerationWithDomainAndLocalIdentifierAndNodeAndClockSequence(): void + { + Uuid::uuid2(Uuid::DCE_DOMAIN_ORG, $this->localIdentifier, $this->node, 63); + } + + public function benchUuid3Generation(): void + { + Uuid::uuid3($this->namespace, 'name'); + } + + public function benchUuid4Generation(): void + { + Uuid::uuid4(); + } + + public function benchUuid5Generation(): void + { + Uuid::uuid5($this->namespace, 'name'); + } + + public function benchUuid6GenerationWithoutParameters(): void + { + Uuid::uuid6(); + } + + public function benchUuid6GenerationWithNode(): void + { + Uuid::uuid6($this->node); + } + + public function benchUuid6GenerationWithNodeAndClockSequence(): void + { + Uuid::uuid6($this->node, $this->clockSequence); + } +} diff --git a/tests/benchmark/UuidSerializationBench.php b/tests/benchmark/UuidSerializationBench.php new file mode 100644 index 0000000..719f32a --- /dev/null +++ b/tests/benchmark/UuidSerializationBench.php @@ -0,0 +1,206 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Benchmark; + +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +use function array_map; +use function serialize; + +final class UuidSerializationBench +{ + private const TINY_UUID = '00000000-0000-0000-0000-000000000001'; + private const HUGE_UUID = 'ffffffff-ffff-ffff-ffff-ffffffffffff'; + private const UUIDS_TO_BE_SHORTENED = [ + '0ae0cac5-2a40-465c-99ed-3d331b7cf72a', + '5759b9ce-07b5-4e89-b33a-f864317a2951', + '20c8664e-81a8-498d-9e98-444973ef3122', + '16fcbcf3-bb47-4227-90bd-3485d60510c3', + 'fa83ae94-38e0-4903-bc6a-0a3eca6e9ef5', + '51c9e011-0429-4d77-a753-702bd67dcd84', + '1bd8857a-d6d7-4bd6-8734-b3dfedbcda7b', + '7aa38b71-37c3-4561-9b2e-ca227f1c9c55', + 'e6b8854c-435c-4bb1-b6ad-1800b5d3e6bb', + '4e2b0031-8b09-46e2-8244-3814c46a2f53', + 'bedd0850-da1a-4808-95c4-25fef0abbaa7', + '516b9052-d6fb-4828-bfc1-dffdef2d56d2', + '5d60a7e7-9139-4779-9f28-e6316b9fe3b7', + '65aa3d74-c1fb-4bdd-9a00-ce88a5270c57', + '27c2e339-74ed-49a7-a3c4-1a0172e9f945', + 'e89b7727-4847-41ab-98d7-4148216eea8c', + 'd79efaf3-b5dc-43a0-b3a5-c492155a7e0d', + 'ee9ee6e7-5b7d-4e18-ab88-ce03d569305f', + 'fe90c911-c13b-4103-bf33-16757aa87ff5', + '4d7ff67a-0074-4195-95d7-cf8b84eba079', + 'abe5d378-d021-4905-93f4-0e76a7848365', + '19d21907-d121-4d85-8a34-a65d04ce8977', + 'c421b8ad-33a4-42aa-b0cc-8f5f94b2cff7', + 'f3dbbe55-3c80-453e-ab39-a6fe5001a7fc', + 'f48d3eb2-6060-458f-809f-b5e887f9a17f', + 'd189e406-de29-4889-8470-7bfa0d020c0c', + '71627018-9f21-4034-aafe-4c8b17151217', + '0c6a9278-0963-4460-9cae-6dc6f5420f4f', + 'c833ac35-cce0-4315-8df3-3ed76656a548', + '78e94126-1d0a-472a-9b99-37840784318f', + '6e684707-ce4b-42df-8a77-71e57b54b581', + '811df139-e7a3-4cd8-b778-c81494d239ee', + 'c263c5d8-c166-4599-9219-3e975e506f45', + 'b31e7c5d-95ba-41d4-bc29-e6357c96f005', + '16ae2983-7f8f-4eee-9afb-6d4617836a01', + 'ecbbfac7-f92a-4b41-996e-3e4724aa0e23', + '2c6b3db9-a5ee-4425-a837-8880a86faaa0', + '3d67a99a-b39a-4295-b7f8-0bf71ead5b2d', + 'ca421bb7-ad73-41ea-9648-70073862ad5a', + '5ba156fa-853d-460f-a884-ca8dd3a27314', + '42a4359a-1df2-4086-b454-7477dbb726ff', + '7db9517b-f6ba-4bcf-ae26-6a88a7dbb034', + 'bc758bd6-eb50-425b-ada1-07e6bb312032', + '254cf6d0-696d-4ff0-b579-ac3b633f03c0', + 'f8f34b37-4c71-4177-bac5-6b99bb1929af', + 'b0cc6179-f2b1-4ddf-8fe2-2251c3d935a3', + '333ad834-fa3b-4cf4-b9ba-fdb1c481c497', + '011fc3bc-a97d-4535-8cb0-81766e361e78', + 'acf2262b-4ccf-4f1d-b5c1-5e44641884c6', + '6bf661b1-2f85-4277-8dba-6552141e7e42', + 'a76df66b-8c50-488f-b4e7-4f4d3c05afff', + 'b5c5df47-f939-4536-a340-442bf00bd70d', + 'd4914d41-0011-49fb-a1c2-fe69108e4983', + 'efd5fa37-b0de-43b0-9fe7-1b7a7a6523f8', + '6048f863-7faa-43f2-8202-4b349ae34810', + '659a0024-fa05-4068-aed0-e61239554b6d', + '6ec80af3-0415-429e-91e9-8491ab5745c0', + '0e6f754c-0533-4336-b4f0-e2e35518efa1', + '47469672-7e55-4316-b5d4-c458e43d2404', + '0c5ad756-a823-4a3f-8449-840fac080f45', + '8f8345da-1dd9-499b-bda5-57100bb305d5', + '4a31d059-e375-4571-9d28-ea0de51740e7', + 'ed7fb50c-1b3a-4594-920b-9a461abce57c', + '3d8fe6f6-e603-44c0-b550-3568523c3224', + '809259bc-7912-427a-a975-7298ee5626db', + 'ec88d77e-5612-466c-b269-ad146abd70d0', + 'bd308a10-8073-45ae-9bfb-9a663ad5dd10', + '83a6a4cc-3079-46d8-9263-8f57af4fd4c7', + '557f0041-7e7f-447c-988c-eafa6e396915', + '6ad0fa1c-7425-41e9-9b74-19c4935750a2', + 'a9193e21-e529-43cf-9421-6ed09b59d86e', + '2a09f6e6-4fb2-4da0-97bf-6f32858ba977', + 'd66e0940-087f-4e71-8292-fc38e306d9f7', + '0dfc58b3-d591-40be-803d-e17a52e5d262', + 'a46c6902-de10-45cc-8dac-600d68860532', + '5200f9dc-b967-4d1e-ab01-51c726c152ba', + 'acd8498b-ee8b-4d58-b0ef-c353fb1b5a45', + '36adf355-cccc-406f-a814-6333ec4e31bf', + 'd6d64c6f-8388-4de3-9db1-de07f02071b6', + 'daf3fde9-41d0-422f-a0e3-8c7a93a77091', + '160f4fac-a229-4169-893e-4e9e6864c098', + '170c4be9-1fe6-4838-8a77-dee364ae9a95', + '2864fed0-868c-4bd1-a3fa-ae3bb3de20f4', + '8ea6639c-36dc-463c-8299-8f9a12b10898', + '626bef95-2f24-47c2-a792-f06e8f13a11e', + 'ede75c44-5a1d-484c-942d-87407f27db23', + '966ec42b-0bf7-4923-9672-7a41fee377bc', + '399d7ce6-b28f-4751-ac50-73e31b079f22', + 'ab2b4086-e181-4f02-aee1-a94afed40b50', + '3cfc33a6-73f7-49f7-9c01-fbcf84e604d0', + '40cf06c6-74ca-4016-b388-17dc0334770d', + '58f9ecd3-14ab-4100-b32a-cc2622f06c81', + 'a5c35e34-5d05-4724-bb6c-613b5d306a18', + '5133ae3e-e38b-47fa-a3dc-965c738be792', + '594acd2f-7100-4b2b-8b8a-6097cb1cec3d', + '08b3da92-6b32-43d8-9fdd-53eaa996d649', + '93dcdc27-ab2c-4828-9074-4876ee7ab257', + '8260a154-23cc-4510-a5df-cc5119f457fb', + '732a6571-9729-4935-92be-1a74b3242636', + 'c15f5581-e047-45b7-a36f-dfef4e7ba4bb', + ]; + /** @var UuidInterface */ + private $tinyUuid; + /** @var UuidInterface */ + private $hugeUuid; + /** @var UuidInterface */ + private $uuid; + /** + * @var UuidInterface[] + * @psalm-var non-empty-list + */ + private $promiscuousUuids; + /** @var string */ + private $serializedTinyUuid; + /** @var string */ + private $serializedHugeUuid; + /** @var string */ + private $serializedUuid; + /** + * @var string[] + * @psalm-var non-empty-list + */ + private $serializedPromiscuousUuids; + + public function __construct() + { + $this->tinyUuid = Uuid::fromString(self::TINY_UUID); + $this->hugeUuid = Uuid::fromString(self::HUGE_UUID); + $this->uuid = Uuid::fromString(self::UUIDS_TO_BE_SHORTENED[0]); + $this->promiscuousUuids = array_map([Uuid::class, 'fromString'], self::UUIDS_TO_BE_SHORTENED); + $this->serializedTinyUuid = serialize(Uuid::fromString(self::TINY_UUID)); + $this->serializedHugeUuid = serialize(Uuid::fromString(self::HUGE_UUID)); + $this->serializedUuid = serialize(Uuid::fromString(self::UUIDS_TO_BE_SHORTENED[0])); + $this->serializedPromiscuousUuids = array_map( + 'serialize', + array_map([Uuid::class, 'fromString'], self::UUIDS_TO_BE_SHORTENED) + ); + } + + public function benchSerializationOfTinyUuid(): void + { + serialize($this->tinyUuid); + } + + public function benchSerializationOfHugeUuid(): void + { + serialize($this->hugeUuid); + } + + public function benchSerializationOfUuid(): void + { + serialize($this->uuid); + } + + public function benchSerializationOfPromiscuousUuids(): void + { + array_map('serialize', $this->promiscuousUuids); + } + + public function benchDeSerializationOfTinyUuid(): void + { + unserialize($this->serializedTinyUuid); + } + + public function benchDeSerializationOfHugeUuid(): void + { + unserialize($this->serializedHugeUuid); + } + + public function benchDeSerializationOfUuid(): void + { + unserialize($this->serializedUuid); + } + + public function benchDeSerializationOfPromiscuousUuids(): void + { + array_map('unserialize', $this->serializedPromiscuousUuids); + } +} diff --git a/tests/benchmark/UuidStringConversionBench.php b/tests/benchmark/UuidStringConversionBench.php new file mode 100644 index 0000000..a15b804 --- /dev/null +++ b/tests/benchmark/UuidStringConversionBench.php @@ -0,0 +1,257 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Benchmark; + +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +use function array_map; + +final class UuidStringConversionBench +{ + private const TINY_UUID = '00000000-0000-0000-0000-000000000001'; + private const HUGE_UUID = 'ffffffff-ffff-ffff-ffff-ffffffffffff'; + private const UUIDS_TO_BE_SHORTENED = [ + '0ae0cac5-2a40-465c-99ed-3d331b7cf72a', + '5759b9ce-07b5-4e89-b33a-f864317a2951', + '20c8664e-81a8-498d-9e98-444973ef3122', + '16fcbcf3-bb47-4227-90bd-3485d60510c3', + 'fa83ae94-38e0-4903-bc6a-0a3eca6e9ef5', + '51c9e011-0429-4d77-a753-702bd67dcd84', + '1bd8857a-d6d7-4bd6-8734-b3dfedbcda7b', + '7aa38b71-37c3-4561-9b2e-ca227f1c9c55', + 'e6b8854c-435c-4bb1-b6ad-1800b5d3e6bb', + '4e2b0031-8b09-46e2-8244-3814c46a2f53', + 'bedd0850-da1a-4808-95c4-25fef0abbaa7', + '516b9052-d6fb-4828-bfc1-dffdef2d56d2', + '5d60a7e7-9139-4779-9f28-e6316b9fe3b7', + '65aa3d74-c1fb-4bdd-9a00-ce88a5270c57', + '27c2e339-74ed-49a7-a3c4-1a0172e9f945', + 'e89b7727-4847-41ab-98d7-4148216eea8c', + 'd79efaf3-b5dc-43a0-b3a5-c492155a7e0d', + 'ee9ee6e7-5b7d-4e18-ab88-ce03d569305f', + 'fe90c911-c13b-4103-bf33-16757aa87ff5', + '4d7ff67a-0074-4195-95d7-cf8b84eba079', + 'abe5d378-d021-4905-93f4-0e76a7848365', + '19d21907-d121-4d85-8a34-a65d04ce8977', + 'c421b8ad-33a4-42aa-b0cc-8f5f94b2cff7', + 'f3dbbe55-3c80-453e-ab39-a6fe5001a7fc', + 'f48d3eb2-6060-458f-809f-b5e887f9a17f', + 'd189e406-de29-4889-8470-7bfa0d020c0c', + '71627018-9f21-4034-aafe-4c8b17151217', + '0c6a9278-0963-4460-9cae-6dc6f5420f4f', + 'c833ac35-cce0-4315-8df3-3ed76656a548', + '78e94126-1d0a-472a-9b99-37840784318f', + '6e684707-ce4b-42df-8a77-71e57b54b581', + '811df139-e7a3-4cd8-b778-c81494d239ee', + 'c263c5d8-c166-4599-9219-3e975e506f45', + 'b31e7c5d-95ba-41d4-bc29-e6357c96f005', + '16ae2983-7f8f-4eee-9afb-6d4617836a01', + 'ecbbfac7-f92a-4b41-996e-3e4724aa0e23', + '2c6b3db9-a5ee-4425-a837-8880a86faaa0', + '3d67a99a-b39a-4295-b7f8-0bf71ead5b2d', + 'ca421bb7-ad73-41ea-9648-70073862ad5a', + '5ba156fa-853d-460f-a884-ca8dd3a27314', + '42a4359a-1df2-4086-b454-7477dbb726ff', + '7db9517b-f6ba-4bcf-ae26-6a88a7dbb034', + 'bc758bd6-eb50-425b-ada1-07e6bb312032', + '254cf6d0-696d-4ff0-b579-ac3b633f03c0', + 'f8f34b37-4c71-4177-bac5-6b99bb1929af', + 'b0cc6179-f2b1-4ddf-8fe2-2251c3d935a3', + '333ad834-fa3b-4cf4-b9ba-fdb1c481c497', + '011fc3bc-a97d-4535-8cb0-81766e361e78', + 'acf2262b-4ccf-4f1d-b5c1-5e44641884c6', + '6bf661b1-2f85-4277-8dba-6552141e7e42', + 'a76df66b-8c50-488f-b4e7-4f4d3c05afff', + 'b5c5df47-f939-4536-a340-442bf00bd70d', + 'd4914d41-0011-49fb-a1c2-fe69108e4983', + 'efd5fa37-b0de-43b0-9fe7-1b7a7a6523f8', + '6048f863-7faa-43f2-8202-4b349ae34810', + '659a0024-fa05-4068-aed0-e61239554b6d', + '6ec80af3-0415-429e-91e9-8491ab5745c0', + '0e6f754c-0533-4336-b4f0-e2e35518efa1', + '47469672-7e55-4316-b5d4-c458e43d2404', + '0c5ad756-a823-4a3f-8449-840fac080f45', + '8f8345da-1dd9-499b-bda5-57100bb305d5', + '4a31d059-e375-4571-9d28-ea0de51740e7', + 'ed7fb50c-1b3a-4594-920b-9a461abce57c', + '3d8fe6f6-e603-44c0-b550-3568523c3224', + '809259bc-7912-427a-a975-7298ee5626db', + 'ec88d77e-5612-466c-b269-ad146abd70d0', + 'bd308a10-8073-45ae-9bfb-9a663ad5dd10', + '83a6a4cc-3079-46d8-9263-8f57af4fd4c7', + '557f0041-7e7f-447c-988c-eafa6e396915', + '6ad0fa1c-7425-41e9-9b74-19c4935750a2', + 'a9193e21-e529-43cf-9421-6ed09b59d86e', + '2a09f6e6-4fb2-4da0-97bf-6f32858ba977', + 'd66e0940-087f-4e71-8292-fc38e306d9f7', + '0dfc58b3-d591-40be-803d-e17a52e5d262', + 'a46c6902-de10-45cc-8dac-600d68860532', + '5200f9dc-b967-4d1e-ab01-51c726c152ba', + 'acd8498b-ee8b-4d58-b0ef-c353fb1b5a45', + '36adf355-cccc-406f-a814-6333ec4e31bf', + 'd6d64c6f-8388-4de3-9db1-de07f02071b6', + 'daf3fde9-41d0-422f-a0e3-8c7a93a77091', + '160f4fac-a229-4169-893e-4e9e6864c098', + '170c4be9-1fe6-4838-8a77-dee364ae9a95', + '2864fed0-868c-4bd1-a3fa-ae3bb3de20f4', + '8ea6639c-36dc-463c-8299-8f9a12b10898', + '626bef95-2f24-47c2-a792-f06e8f13a11e', + 'ede75c44-5a1d-484c-942d-87407f27db23', + '966ec42b-0bf7-4923-9672-7a41fee377bc', + '399d7ce6-b28f-4751-ac50-73e31b079f22', + 'ab2b4086-e181-4f02-aee1-a94afed40b50', + '3cfc33a6-73f7-49f7-9c01-fbcf84e604d0', + '40cf06c6-74ca-4016-b388-17dc0334770d', + '58f9ecd3-14ab-4100-b32a-cc2622f06c81', + 'a5c35e34-5d05-4724-bb6c-613b5d306a18', + '5133ae3e-e38b-47fa-a3dc-965c738be792', + '594acd2f-7100-4b2b-8b8a-6097cb1cec3d', + '08b3da92-6b32-43d8-9fdd-53eaa996d649', + '93dcdc27-ab2c-4828-9074-4876ee7ab257', + '8260a154-23cc-4510-a5df-cc5119f457fb', + '732a6571-9729-4935-92be-1a74b3242636', + 'c15f5581-e047-45b7-a36f-dfef4e7ba4bb', + ]; + /** @var UuidInterface */ + private $tinyUuid; + /** @var UuidInterface */ + private $hugeUuid; + /** @var UuidInterface */ + private $uuid; + /** + * @var UuidInterface[] + * @psalm-var non-empty-list + */ + private $promiscuousUuids; + /** + * @var string + * @psalm-var non-empty-string + */ + private $tinyUuidBytes; + /** + * @var string + * @psalm-var non-empty-string + */ + private $hugeUuidBytes; + /** + * @var string + * @psalm-var non-empty-string + */ + private $uuidBytes; + /** + * @var string[] + * @psalm-var non-empty-list + */ + private $promiscuousUuidsBytes; + + public function __construct() + { + $this->tinyUuid = Uuid::fromString(self::TINY_UUID); + $this->hugeUuid = Uuid::fromString(self::HUGE_UUID); + $this->uuid = Uuid::fromString(self::UUIDS_TO_BE_SHORTENED[0]); + $this->promiscuousUuids = array_map([Uuid::class, 'fromString'], self::UUIDS_TO_BE_SHORTENED); + $this->tinyUuidBytes = $this->tinyUuid->getBytes(); + $this->hugeUuidBytes = $this->hugeUuid->getBytes(); + $this->uuidBytes = $this->uuid->getBytes(); + $this->promiscuousUuidsBytes = array_map(static function (UuidInterface $uuid): string { + return $uuid->getBytes(); + }, $this->promiscuousUuids); + } + + public function benchCreationOfTinyUuidFromString(): void + { + Uuid::fromString(self::TINY_UUID); + } + + public function benchCreationOfHugeUuidFromString(): void + { + Uuid::fromString(self::HUGE_UUID); + } + + public function benchCreationOfUuidFromString(): void + { + Uuid::fromString(self::UUIDS_TO_BE_SHORTENED[0]); + } + + public function benchCreationOfPromiscuousUuidsFromString(): void + { + array_map([Uuid::class, 'fromString'], self::UUIDS_TO_BE_SHORTENED); + } + + public function benchCreationOfTinyUuidFromBytes(): void + { + Uuid::fromBytes($this->tinyUuidBytes); + } + + public function benchCreationOfHugeUuidFromBytes(): void + { + Uuid::fromBytes($this->hugeUuidBytes); + } + + public function benchCreationOfUuidFromBytes(): void + { + Uuid::fromBytes($this->uuidBytes); + } + + public function benchCreationOfPromiscuousUuidsFromBytes(): void + { + array_map([Uuid::class, 'fromBytes'], $this->promiscuousUuidsBytes); + } + + public function benchStringConversionOfTinyUuid(): void + { + $this->tinyUuid->toString(); + } + + public function benchStringConversionOfHugeUuid(): void + { + $this->hugeUuid->toString(); + } + + public function benchStringConversionOfUuid(): void + { + $this->uuid->toString(); + } + + public function benchStringConversionOfPromiscuousUuids(): void + { + array_map(static function (UuidInterface $uuid): string { + return $uuid->toString(); + }, $this->promiscuousUuids); + } + + public function benchBytesConversionOfTinyUuid(): void + { + $this->tinyUuid->getBytes(); + } + + public function benchBytesConversionOfHugeUuid(): void + { + $this->hugeUuid->getBytes(); + } + + public function benchBytesConversionOfUuid(): void + { + $this->uuid->getBytes(); + } + + public function benchBytesConversionOfPromiscuousUuids(): void + { + array_map(static function (UuidInterface $uuid): string { + return $uuid->getBytes(); + }, $this->promiscuousUuids); + } +} diff --git a/tests/phpstan.neon b/tests/phpstan.neon index 0d3c590..405d2d8 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -24,3 +24,8 @@ parameters: message: '#^Comparison operation ">" between 6 and 0 is always true\.$#' count: 1 path: ../src/Generator/CombGenerator.php + - + # Legacy methods of `Ramsey\Uuid` use interface methods that are NOT defined on `FieldsInterface` + message: '#^Call to an undefined method Ramsey\\Uuid\\Fields\\FieldsInterface::get.*$#' + count: 9 + path: ../src/Lazy/LazyUuidFromString.php