From 92a2699abe49698e83751c912ad3fa8af041835b Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 18 Jan 2017 20:10:07 -0700 Subject: [PATCH 1/3] refactor integration-test feature-generator to match v2 feature structure, e.g. \LaunchDarkly\Tests\FeatureFlagTest::$json1 and \LaunchDarkly\Tests\FeatureFlagTest::$json2. --- integration-tests/LDDFeatureRequesterTest.php | 61 +++++++++++++++---- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 602b87717..64ac40eaf 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -47,19 +47,54 @@ public function testGetApc() { } private function gen_feature($key, $val) { - $data = << 'Feature ' . $key, + 'key' => $key, + 'kind' => 'flag', + 'salt' => 'Zm9v', + 'on' => true, + 'variations' => [ + $val, + false, + ], + 'commitDate' => '2015-09-08T21:24:16.712Z', + 'creationDate' => '2015-09-08T21:06:16.527Z', + 'version' => 4, + 'prerequisites' => [], + 'targets' => [ + [ + 'values' => [ + $val, + ], + 'variation' => 0, + ], + [ + 'values' => [ + false, + ], + 'variation' => 1, + ], + ], + 'rules' => [], + 'fallthrough' => [ + 'rollout' => [ + 'variations' => [ + [ + 'variation' => 0, + 'weight' => 95000, + ], + [ + 'variation' => 1, + 'weight' => 5000, + ], + ], + ], + ], + 'offVariation' => null, + 'deleted' => false, + ]; + + return \json_encode($data); } } From 66656c714171d19fc029915198ddc5810782f793 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 18 Jan 2017 20:46:17 -0700 Subject: [PATCH 2/3] split vagrant user bootstrap from root bootstrap. provisioner correctly installs php54 with APC, and switches php version. --- integration-tests/Vagrantfile | 1 + integration-tests/bootstrap.sh | 22 --------------------- integration-tests/bootstrap.user.sh | 30 +++++++++++++++++++++++++++++ src/LaunchDarkly/LDClient.php | 2 +- 4 files changed, 32 insertions(+), 23 deletions(-) create mode 100755 integration-tests/bootstrap.user.sh diff --git a/integration-tests/Vagrantfile b/integration-tests/Vagrantfile index ff73f459b..5529ac9d3 100644 --- a/integration-tests/Vagrantfile +++ b/integration-tests/Vagrantfile @@ -17,6 +17,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box_url = "https://vagrantcloud.com/ubuntu/boxes/trusty64" config.vm.provision :shell, path: "bootstrap.sh" + config.vm.provision :shell, path: "bootstrap.user.sh", privileged: false # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine. In the example below, diff --git a/integration-tests/bootstrap.sh b/integration-tests/bootstrap.sh index 3e75fe316..786182dfa 100755 --- a/integration-tests/bootstrap.sh +++ b/integration-tests/bootstrap.sh @@ -35,25 +35,3 @@ cat < /home/vagrant/.vimrc set tabstop=4 EOF chown vagrant.vagrant /home/vagrant/.vimrc - -su - vagrant -cd ~vagrant -pwd -curl -s -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew -chmod +x phpbrew -sudo mv phpbrew /usr/bin/phpbrew -phpbrew init -phpbrew known --update -phpbrew update -phpbrew install 5.4.34 +default - -echo "source $HOME/.phpbrew/bashrc" >> /home/vagrant/.bashrc -source $HOME/.bashrc -phpbrew switch php-5.4.34 -phpbrew ext install apc -echo "apc.enable_cli = 1" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini - - -cd /home/vagrant/project/integration-tests -curl -sS https://getcomposer.org/installer | php -php composer.phar install diff --git a/integration-tests/bootstrap.user.sh b/integration-tests/bootstrap.user.sh new file mode 100755 index 000000000..60145cb70 --- /dev/null +++ b/integration-tests/bootstrap.user.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +echo +echo "install phpbrew and php54" +cd ~ +curl -s -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew +chmod +x phpbrew +sudo mv phpbrew /usr/bin/phpbrew +phpbrew init +phpbrew known --update +phpbrew update +phpbrew install 5.4.34 +default + +echo +echo "switch php54" +echo "source $HOME/.phpbrew/bashrc" >> /home/vagrant/.bashrc +source $HOME/.phpbrew/bashrc +phpbrew switch 5.4.34 + +echo +echo "install php54-apc" +phpbrew ext install apc +echo "apc.enable_cli = 1" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini +echo "date.timezone =UTC" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini + +echo +echo "update project dependencies" +cd /home/vagrant/project/integration-tests +curl -sS https://getcomposer.org/installer | php +php composer.phar update diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index bc4e96ce7..d2f3551f0 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -88,7 +88,7 @@ public function __construct($sdkKey, $options = array()) { $featureRequesterClass = '\\LaunchDarkly\\GuzzleFeatureRequester'; } - if (!is_a($featureRequesterClass, FeatureRequester::class, true)) { + if (!is_a($featureRequesterClass, '\LaunchDarkly\FeatureRequester', true)) { throw new \InvalidArgumentException; } $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $sdkKey, $options); From e0efa74864ffaa35a6beb367428949bfeb0cbc2c Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 18 Jan 2017 21:04:36 -0700 Subject: [PATCH 3/3] add integration tests to CircleCI build. starts redis server on CircleCI and installs apcu extension on php56. add APCU-feature-requester which is the >=php55 version of the <=php54 APC-feature-requester. --- circle.yml | 7 ++++ integration-tests/LDDFeatureRequesterTest.php | 36 +++++++++++++++++++ integration-tests/bootstrap.sh | 4 +++ integration-tests/bootstrap.user.sh | 1 + src/LaunchDarkly/ApcLDDFeatureRequester.php | 27 ++++++++++++-- src/LaunchDarkly/ApcuLDDFeatureRequester.php | 34 ++++++++++++++++++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 src/LaunchDarkly/ApcuLDDFeatureRequester.php diff --git a/circle.yml b/circle.yml index 513e43b0a..92e5e7c01 100644 --- a/circle.yml +++ b/circle.yml @@ -2,15 +2,22 @@ machine: php: version: 5.6.17 services: + - redis - docker dependencies: pre: + - yes '' | pecl install -f apcu-4.0.10 + - echo "extension=apcu.so" | sudo tee -a /opt/circleci/php/$(phpenv global)/etc/php.ini + - echo "apc.enable_cli = 1" | sudo tee -a /opt/circleci/php/$(phpenv global)/etc/php.ini - docker pull php - docker pull nyanpass/php5.5 test: override: - vendor/bin/phpunit tests --coverage-text + - ln -s vendor integration-tests/vendor + - vendor/bin/phpunit integration-tests/LDDFeatureRequesterTest.php + - composer update && vendor/bin/phpunit tests - composer update --prefer-lowest && vendor/bin/phpunit tests diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 64ac40eaf..47229c861 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -5,6 +5,7 @@ use LaunchDarkly\LDClient; use LaunchDarkly\LDUserBuilder; +use Predis\Client; class LDDFeatureRetrieverTest extends \PHPUnit_Framework_TestCase { @@ -24,6 +25,9 @@ public function testGet() { } public function testGetApc() { + if (!extension_loaded('apc')) { + self::markTestSkipped('Install `apc` extension to run this test.'); + } $redis = new \Predis\Client(array( "scheme" => "tcp", "host" => 'localhost', @@ -46,6 +50,38 @@ public function testGetApc() { $this->assertEquals("baz", $client->variation('foo', $user, 'jim')); } + public function testGetApcu() { + if (!extension_loaded('apcu')) { + self::markTestSkipped('Install `apcu` extension to run this test.'); + } + + $redis = new Client([ + 'scheme' => 'tcp', + 'host' => 'localhost', + 'port' => 6379 + ]); + + $client = new LDClient('BOGUS_API_KEY', [ + 'feature_requester_class' => '\LaunchDarkly\ApcuLDDFeatureRequester', + 'apc_expiration' => 1 + ]); + + $builder = new LDUserBuilder(3); + $user = $builder->build(); + + $redis->del('launchdarkly:features'); + $this->assertEquals('alice', $client->variation('fiz', $user, 'alice')); + $redis->hset('launchdarkly:features', 'fiz', $this->gen_feature('fiz', 'buz')); + $this->assertEquals('buz', $client->variation('fiz', $user, 'alice')); + + # cached value so not updated + $redis->hset('launchdarkly:features', 'fiz', $this->gen_feature('fiz', 'bob')); + $this->assertEquals('buz', $client->variation('fiz', $user, 'alice')); + + \apcu_delete('launchdarkly:features.fiz'); + $this->assertEquals('bob', $client->variation('fiz', $user, 'alice')); + } + private function gen_feature($key, $val) { $data = [ 'name' => 'Feature ' . $key, diff --git a/integration-tests/bootstrap.sh b/integration-tests/bootstrap.sh index 786182dfa..81558a836 100755 --- a/integration-tests/bootstrap.sh +++ b/integration-tests/bootstrap.sh @@ -35,3 +35,7 @@ cat < /home/vagrant/.vimrc set tabstop=4 EOF chown vagrant.vagrant /home/vagrant/.vimrc + +# enable APC for php5 CLI +echo "apc.enable_cli = 1" >> /etc/php5/cli/conf.d/20-apcu.ini +php -i | grep apc diff --git a/integration-tests/bootstrap.user.sh b/integration-tests/bootstrap.user.sh index 60145cb70..56ff2b07c 100755 --- a/integration-tests/bootstrap.user.sh +++ b/integration-tests/bootstrap.user.sh @@ -21,6 +21,7 @@ echo echo "install php54-apc" phpbrew ext install apc echo "apc.enable_cli = 1" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini +php -i | grep apc echo "date.timezone =UTC" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini echo diff --git a/src/LaunchDarkly/ApcLDDFeatureRequester.php b/src/LaunchDarkly/ApcLDDFeatureRequester.php index 9ad8e7f82..ad4a36af7 100644 --- a/src/LaunchDarkly/ApcLDDFeatureRequester.php +++ b/src/LaunchDarkly/ApcLDDFeatureRequester.php @@ -4,6 +4,9 @@ /** * Feature requester from an LDD-populated redis, with APC caching + * @deprecated Per the docs (http://php.net/manual/en/intro.apc.php): + * "This extension (APC) is considered unmaintained and dead". + * Install APCu and use \LaunchDarkly\ApcuLDDFeatureRequester instead! * * @package LaunchDarkly */ @@ -18,10 +21,19 @@ function __construct($baseUri, $apiKey, $options) { } } + /** + * @param $key + * @param $success + * @return mixed + */ + protected function fetch($key, &$success = null) + { + return \apc_fetch($key, $success); + } protected function get_from_cache($key) { $key = self::make_cache_key($key); - $enabled = apc_fetch($key); + $enabled = $this->fetch($key); if ($enabled === false) { return null; } @@ -30,8 +42,19 @@ protected function get_from_cache($key) { } } + /** + * @param $key + * @param $var + * @param int $ttl + * @return mixed + */ + protected function add($key, $var, $ttl = 0) + { + return \apc_add($key, $var, $ttl); + } + protected function store_in_cache($key, $val) { - apc_add($this->make_cache_key($key), $val, $this->_expiration); + $this->add($this->make_cache_key($key), $val, $this->_expiration); } private function make_cache_key($name) { diff --git a/src/LaunchDarkly/ApcuLDDFeatureRequester.php b/src/LaunchDarkly/ApcuLDDFeatureRequester.php new file mode 100644 index 000000000..30f2fb2c9 --- /dev/null +++ b/src/LaunchDarkly/ApcuLDDFeatureRequester.php @@ -0,0 +1,34 @@ +