From b8fe2e4a918cbb072efea4e435f53006bfb577ee Mon Sep 17 00:00:00 2001 From: Thibaud Fabre Date: Wed, 17 Dec 2014 01:30:45 +0100 Subject: [PATCH 1/8] Extract factory interface & add basic pecl impl --- src/PeclUuidFactory.php | 74 ++++++++++++++++++++++++++++++++++++ src/UuidFactory.php | 2 +- src/UuidFactoryInterface.php | 21 ++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/PeclUuidFactory.php create mode 100644 src/UuidFactoryInterface.php diff --git a/src/PeclUuidFactory.php b/src/PeclUuidFactory.php new file mode 100644 index 0000000..9cf881c --- /dev/null +++ b/src/PeclUuidFactory.php @@ -0,0 +1,74 @@ +factory = $factory; + } + + /* + * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid1() + */ + public function uuid1($node = null, $clockSeq = null) + { + $uuid = uuid_create(UUID_TYPE_TIME); + + return $this->fromString($uuid); + } + + /* + * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid3() + */ + public function uuid3($ns, $name) + { + return $this->factory->uuid3($ns, $name); + } + + /* + * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid4() + */ + public function uuid4() + { + $uuid = uuid_create(UUID_TYPE_RANDOM); + + return $this->fromString($uuid); + } + + /* + * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid5() + */ + public function uuid5($ns, $name) + { + return $this->factory->uuid5($ns, $name); + } + + /* + * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::fromBytes() + */ + public function fromBytes($bytes) + { + return $this->factory->fromBytes($bytes); + } + + /* + * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::fromString() + */ + public function fromString($name) + { + return $this->factory->fromString($name); + } + + /* + * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::fromInteger() + */ + public function fromInteger($integer) + { + return $this->factory->fromInteger($integer); + } +} \ No newline at end of file diff --git a/src/UuidFactory.php b/src/UuidFactory.php index 5919968..9885742 100644 --- a/src/UuidFactory.php +++ b/src/UuidFactory.php @@ -8,7 +8,7 @@ use Rhumsaa\Uuid\Converter\TimeConverterInterface; use Rhumsaa\Uuid\Provider\NodeProviderInterface; use Rhumsaa\Uuid\Provider\TimeProviderInterface; -class UuidFactory +class UuidFactory implements UuidFactoryInterface { /** diff --git a/src/UuidFactoryInterface.php b/src/UuidFactoryInterface.php new file mode 100644 index 0000000..99a743e --- /dev/null +++ b/src/UuidFactoryInterface.php @@ -0,0 +1,21 @@ + Date: Wed, 17 Dec 2014 01:40:10 +0100 Subject: [PATCH 2/8] Add tests for Pecl factory --- src/Uuid.php | 4 ++-- tests/PeclUuidTest.php | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/PeclUuidTest.php diff --git a/src/Uuid.php b/src/Uuid.php index 0da5200..74a3d5a 100644 --- a/src/Uuid.php +++ b/src/Uuid.php @@ -99,7 +99,7 @@ class Uuid implements UuidInterface, \JsonSerializable /** * - * @var UuidFactory + * @var UuidFactoryInterface */ private static $factory = null; @@ -725,7 +725,7 @@ class Uuid implements UuidInterface, \JsonSerializable return self::$factory; } - public static function setFactory(UuidFactory $factory) + public static function setFactory(UuidFactoryInterface $factory) { self::$factory = $factory; } diff --git a/tests/PeclUuidTest.php b/tests/PeclUuidTest.php new file mode 100644 index 0000000..a5cf9f0 --- /dev/null +++ b/tests/PeclUuidTest.php @@ -0,0 +1,17 @@ + Date: Wed, 17 Dec 2014 02:39:03 +0100 Subject: [PATCH 3/8] 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 From 82c57cac9936d16bb06dc8c358b01f7fb295e30f Mon Sep 17 00:00:00 2001 From: Thibaud Fabre Date: Wed, 17 Dec 2014 03:17:14 +0100 Subject: [PATCH 4/8] Add UUID system library to build Use sudo to install UUID lib --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 69f5091..bde7bb3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,13 @@ php: - 5.6 - hhvm +before_install: + - sudo apt-get update && sudo apt-get install uuid-dev + before_script: - composer self-update - composer install --dev --prefer-source - - sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then pecl install uuid; fi;' + - sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then printf "\n" | pecl install uuid; fi;' script: - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml From 6047058adcb58a6ebd4bafc79b6ae224543252aa Mon Sep 17 00:00:00 2001 From: Thibaud Fabre Date: Wed, 17 Dec 2014 16:02:42 +0100 Subject: [PATCH 5/8] Enable extension Enable extension Debug for Travis build Run PECL tests only WIP --- .travis.yml | 3 ++- tests/PeclUuidTest.php | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index bde7bb3..f87070b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,9 +13,10 @@ before_script: - composer self-update - composer install --dev --prefer-source - sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then printf "\n" | pecl install uuid; fi;' + - phpenv rehash script: - - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml + - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml tests/PeclUuidTest.php - ./vendor/bin/phpcs --standard=phpcs.xml ./ after_script: php vendor/bin/coveralls diff --git a/tests/PeclUuidTest.php b/tests/PeclUuidTest.php index 4ee7966..bec3df5 100644 --- a/tests/PeclUuidTest.php +++ b/tests/PeclUuidTest.php @@ -37,9 +37,6 @@ class PeclUuidTest extends \PHPUnit_Framework_TestCase */ public function testUuid1WithParametersIsDelegated($node, $clockSeq) { - $node = true; - $clockSeq = null; - $this->mockFactory->expects($this->once()) ->method('uuid1') ->with($node, $clockSeq); From d6205aaf475504c9bb81ff03b5072f7757a431c4 Mon Sep 17 00:00:00 2001 From: Thibaud Fabre Date: Mon, 29 Dec 2014 21:57:42 +0100 Subject: [PATCH 6/8] Remove hackish extension_loaded mock --- src/PeclUuidFactory.php | 8 ++++++++ tests/PeclUuidTest.php | 24 ++++++------------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/PeclUuidFactory.php b/src/PeclUuidFactory.php index 35c9a11..5436ece 100644 --- a/src/PeclUuidFactory.php +++ b/src/PeclUuidFactory.php @@ -32,6 +32,14 @@ class PeclUuidFactory implements UuidFactoryInterface $this->factory = $factory; } + /** + * Forces factory to act as if PECL extension is not available + */ + public function disablePecl() + { + $this->hasExt = false; + } + /** * (non-PHPdoc) @see \Rhumsaa\Uuid\UuidFactoryInterface::uuid1() */ diff --git a/tests/PeclUuidTest.php b/tests/PeclUuidTest.php index bec3df5..6d0d327 100644 --- a/tests/PeclUuidTest.php +++ b/tests/PeclUuidTest.php @@ -6,20 +6,10 @@ 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)); } @@ -54,16 +44,15 @@ class PeclUuidTest extends \PHPUnit_Framework_TestCase public function testUuid1WithoutExtensionIsDelegated() { - self::$mockNoExt = true; + $factory = new PeclUuidFactory($this->mockFactory); + $factory->disablePecl(); - Uuid::setFactory(new PeclUuidFactory($this->mockFactory)); + Uuid::setFactory($factory); $this->mockFactory->expects($this->once()) ->method('uuid1'); Uuid::uuid1(); - - self::$mockNoExt = false; } public function testUuid1Version() @@ -85,16 +74,15 @@ class PeclUuidTest extends \PHPUnit_Framework_TestCase public function testUuid4WithoutExtensionIsDelegated() { - self::$mockNoExt = true; + $factory = new PeclUuidFactory($this->mockFactory); + $factory->disablePecl(); - Uuid::setFactory(new PeclUuidFactory($this->mockFactory)); + Uuid::setFactory($factory); $this->mockFactory->expects($this->once()) ->method('uuid4'); Uuid::uuid4(); - - self::$mockNoExt = false; } public function testUuid4WithParametersIsNeverDelegated() From ace0db770777859dc9e8645676e2e7c1328cbc84 Mon Sep 17 00:00:00 2001 From: Thibaud Fabre Date: Mon, 29 Dec 2014 22:06:06 +0100 Subject: [PATCH 7/8] Skip tests that cannot succeed with HHVM --- tests/PeclUuidTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/PeclUuidTest.php b/tests/PeclUuidTest.php index 6d0d327..a19024f 100644 --- a/tests/PeclUuidTest.php +++ b/tests/PeclUuidTest.php @@ -36,6 +36,10 @@ class PeclUuidTest extends \PHPUnit_Framework_TestCase public function testUuid1WithoutParametersIsNotDelegated() { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('PECL Uuid extension not available in HHVM'); + } + $this->mockFactory->expects($this->never()) ->method('uuid1'); @@ -87,6 +91,10 @@ class PeclUuidTest extends \PHPUnit_Framework_TestCase public function testUuid4WithParametersIsNeverDelegated() { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('PECL Uuid extension not available in HHVM'); + } + $this->mockFactory->expects($this->never()) ->method('uuid4'); From 01b2b0b72e9658b35f5c66e97e9139937996e0d9 Mon Sep 17 00:00:00 2001 From: Thibaud Fabre Date: Mon, 29 Dec 2014 22:09:34 +0100 Subject: [PATCH 8/8] Run all tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f87070b..b54bbf0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ before_script: - phpenv rehash script: - - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml tests/PeclUuidTest.php + - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml - ./vendor/bin/phpcs --standard=phpcs.xml ./ after_script: php vendor/bin/coveralls