From 34cc28cc307461bb124339bad9e811d5802fc53b Mon Sep 17 00:00:00 2001 From: Thibaud Fabre Date: Wed, 17 Dec 2014 02:39:03 +0100 Subject: [PATCH] Add more unit tests for Pecl-based factory Do not try to install UUID ext in HHVM run --- .travis.yml | 1 + src/PeclUuidFactory.php | 49 ++++++++++++---- src/Uuid.php | 2 +- tests/PeclUuidTest.php | 124 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 156 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7dba238..69f5091 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ php: before_script: - composer self-update - composer install --dev --prefer-source + - sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then pecl install uuid; fi;' script: - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml diff --git a/src/PeclUuidFactory.php b/src/PeclUuidFactory.php index 9cf881c..35c9a11 100644 --- a/src/PeclUuidFactory.php +++ b/src/PeclUuidFactory.php @@ -2,27 +2,50 @@ namespace Rhumsaa\Uuid; +/** + * Factory relying on PECL UUID library whenever possible, otherwise defaulting + * to pure PHP factory. + * @author thibaud + * + */ class PeclUuidFactory implements UuidFactoryInterface { - + /** + * + * @var UuidFactoryInterface + */ private $factory; + /** + * + * @var boolean + */ + private $hasExt = false; + + /** + * + * @param UuidFactoryInterface $factory + */ public function __construct(UuidFactoryInterface $factory) { + $this->hasExt = extension_loaded('uuid'); $this->factory = $factory; } - /* + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid1() */ public function uuid1($node = null, $clockSeq = null) { - $uuid = uuid_create(UUID_TYPE_TIME); + if (! $this->hasExt || $node !== null || $clockSeq !== null) { + // If either param is not null, we cannot use PECL without breaking LSP. + return $this->factory->uuid1($node, $clockSeq); + } - return $this->fromString($uuid); + return $this->fromString(uuid_create(UUID_TYPE_TIME)); } - /* + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid3() */ public function uuid3($ns, $name) @@ -30,17 +53,19 @@ class PeclUuidFactory implements UuidFactoryInterface return $this->factory->uuid3($ns, $name); } - /* + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid4() */ public function uuid4() { - $uuid = uuid_create(UUID_TYPE_RANDOM); + if (! $this->hasExt) { + return $this->factory->uuid4(); + } - return $this->fromString($uuid); + return $this->fromString(uuid_create(UUID_TYPE_RANDOM)); } - /* + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid5() */ public function uuid5($ns, $name) @@ -48,7 +73,7 @@ class PeclUuidFactory implements UuidFactoryInterface return $this->factory->uuid5($ns, $name); } - /* + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::fromBytes() */ public function fromBytes($bytes) @@ -56,7 +81,7 @@ class PeclUuidFactory implements UuidFactoryInterface return $this->factory->fromBytes($bytes); } - /* + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::fromString() */ public function fromString($name) @@ -64,7 +89,7 @@ class PeclUuidFactory implements UuidFactoryInterface return $this->factory->fromString($name); } - /* + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::fromInteger() */ public function fromInteger($integer) diff --git a/src/Uuid.php b/src/Uuid.php index 74a3d5a..30589ff 100644 --- a/src/Uuid.php +++ b/src/Uuid.php @@ -719,7 +719,7 @@ class Uuid implements UuidInterface, \JsonSerializable public static function getFactory() { if (! self::$factory) { - self::$factory = new UuidFactory(); + self::$factory = new PeclUuidFactory(new UuidFactory()); } return self::$factory; diff --git a/tests/PeclUuidTest.php b/tests/PeclUuidTest.php index a5cf9f0..4ee7966 100644 --- a/tests/PeclUuidTest.php +++ b/tests/PeclUuidTest.php @@ -2,16 +2,126 @@ namespace Rhumsaa\Uuid; -use Rhumsaa\Uuid\Provider\Time\SystemTimeProvider; -use Rhumsaa\Uuid\Provider\Time\FixedTimeProvider; -use Rhumsaa\Uuid\Generator\CombGenerator; - -class PeclUuidTest extends UuidTest +class PeclUuidTest extends \PHPUnit_Framework_TestCase { + private $mockFactory; + + public static $mockNoExt = false; + protected function setUp() + { + $this->mockFactory = $this->getMock('Rhumsaa\Uuid\UuidFactoryInterface'); + + if (! function_exists('\Rhumsaa\Uuid\extension_loaded')) { + // Hackish, but allows mocking extension not avail without + // breaking the function if tests are loaded accidently in non test env. + eval('namespace Rhumsaa\Uuid { function extension_loaded($name) { + return ! PeclUuidTest::$mockNoExt; + } }'); + } + + Uuid::setFactory(new PeclUuidFactory($this->mockFactory)); + } + + public function getUuid1Params() + { + return [ + [ true, null ], + [ null, true ], + [ true, true ] + ]; + } + + /** + * @dataProvider getUuid1Params + */ + public function testUuid1WithParametersIsDelegated($node, $clockSeq) + { + $node = true; + $clockSeq = null; + + $this->mockFactory->expects($this->once()) + ->method('uuid1') + ->with($node, $clockSeq); + + Uuid::uuid1($node, $clockSeq); + } + + public function testUuid1WithoutParametersIsNotDelegated() + { + $this->mockFactory->expects($this->never()) + ->method('uuid1'); + + Uuid::uuid1(); + } + + public function testUuid1WithoutExtensionIsDelegated() + { + self::$mockNoExt = true; + + Uuid::setFactory(new PeclUuidFactory($this->mockFactory)); + + $this->mockFactory->expects($this->once()) + ->method('uuid1'); + + Uuid::uuid1(); + + self::$mockNoExt = false; + } + + public function testUuid1Version() { Uuid::setFactory(new PeclUuidFactory(new UuidFactory())); - RandomGeneratorFactory::$forceNoOpensslRandomPseudoBytes = false; + $uuid = Uuid::uuid1(); + + $this->assertEquals(1, $uuid->getVersion()); } -} + + public function testUuid3IsDelegated() + { + $this->mockFactory->expects($this->once()) + ->method('uuid3'); + + Uuid::uuid3(Uuid::NAMESPACE_DNS, str_replace('\\', '.', __NAMESPACE__)); + } + + public function testUuid4WithoutExtensionIsDelegated() + { + self::$mockNoExt = true; + + Uuid::setFactory(new PeclUuidFactory($this->mockFactory)); + + $this->mockFactory->expects($this->once()) + ->method('uuid4'); + + Uuid::uuid4(); + + self::$mockNoExt = false; + } + + public function testUuid4WithParametersIsNeverDelegated() + { + $this->mockFactory->expects($this->never()) + ->method('uuid4'); + + Uuid::uuid4(); + } + + public function testUuid4Version() + { + Uuid::setFactory(new PeclUuidFactory(new UuidFactory())); + + $uuid = Uuid::uuid4(); + + $this->assertEquals(4, $uuid->getVersion()); + } + + public function testUuid5IsDelegated() + { + $this->mockFactory->expects($this->once()) + ->method('uuid5'); + + Uuid::uuid5(Uuid::NAMESPACE_DNS, str_replace('\\', '.', __NAMESPACE__)); + } +} \ No newline at end of file