diff --git a/.travis.yml b/.travis.yml index 2217eca46f..c0a0d66628 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,13 +16,14 @@ matrix: #- LOWEST_DEPS="" #- LOWEST_DEPS="--prefer-lowest" -#services: +services: + - memcached # - mysql # - postgres sudo: required dist: trusty -# this myy fix hhvm builds according to https://docs.travis-ci.com/user/languages/php#HHVM-versions-on-Trusty +# this fixes hhvm builds according to https://docs.travis-ci.com/user/languages/php#HHVM-versions-on-Trusty group: edge before_script: diff --git a/api/src/Cache/Base.php b/api/src/Cache/Base.php index 83f2b5e0c4..1055933ced 100644 --- a/api/src/Cache/Base.php +++ b/api/src/Cache/Base.php @@ -13,6 +13,10 @@ namespace EGroupware\Api\Cache; +/*if (isset($_SERVER['SCRIPT_FILENAME']) && realpath($_SERVER['SCRIPT_FILENAME']) == __FILE__) +{ + require_once dirname(__DIR__).'/loader/common.php'; +}*/ use EGroupware\Api; /** @@ -183,7 +187,9 @@ abstract class Base implements Provider if (isset($_SERVER['HTTP_HOST'])) echo "
\n"; foreach(array( + 'EGroupware\Api\Cache\Apcu' => array(), 'EGroupware\Api\Cache\Apc' => array(), + 'EGroupware\Api\Cache\Memcached' => array('localhost'), 'EGroupware\Api\Cache\Memcache' => array('localhost'), 'EGroupware\Api\Cache\Files' => array('/tmp'), ) as $class => $param) @@ -199,7 +205,7 @@ abstract class Base implements Provider } printf("$failed checks failed, $n iterations took %5.3f sec\n\n", microtime(true)-$start); } - catch (Exception $e) { + catch (\Exception $e) { printf($e->getMessage()."\n\n"); } } diff --git a/api/src/Cache/Files.php b/api/src/Cache/Files.php index 6d4f075c5c..ee802ab7e8 100644 --- a/api/src/Cache/Files.php +++ b/api/src/Cache/Files.php @@ -69,7 +69,7 @@ class Files extends Base implements Provider function add(array $keys,$data,$expiration=0) { // open only if file does NOT exist - if (!($ret = fopen($fname=$this->filename($keys,true), 'x'))) + if (!($ret = @fopen($fname=$this->filename($keys,true), 'x'))) { // if file exists, check if it is expired if (file_exists($fname_expiration=$fname.self::EXPIRATION_EXTENSION) && diff --git a/api/src/test/CacheTest.php b/api/src/test/CacheTest.php new file mode 100644 index 0000000000..3b0dcf946b --- /dev/null +++ b/api/src/test/CacheTest.php @@ -0,0 +1,146 @@ + + * @copyright (c) 2016 by Ralf Becker+ * @author Stylite AG + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @version $Id$ + */ + +namespace EGroupware\Api; + +require_once realpath(__DIR__.'/../loader/common.php'); // autoloader & check_load_extension + +use EGroupware\Api; +use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; + +/** + * Mail account credentials tests + * + * Only testing en&decryption of mail passwords so far. + * Further tests would need database. + */ +class CacheTest extends TestCase +{ + /** + * Test a caching provider + * + * @param string $class + * @param string $params + * @dataProvider cachingProvider + */ + public function testCache($class, $params=array()) + { + // set us up as provider for Api\Cache class + $GLOBALS['egw_info']['server']['install_id'] = md5(microtime(true).__FILE__); + unset($GLOBALS['egw_info']['server']['cache_provider_instance']); + unset($GLOBALS['egw_info']['server']['cache_provider_tree']); + Api\Cache::$default_provider = $class; + + try { + $provider = new $class($params); + $refclass = new ReflectionClass($class); + $methods = array(); + foreach(array('get','set','add','mget','delete') as $name) + { + if ($name != 'mget' || is_a($provider, 'EGroupware\Api\Cache\ProviderMultiple')) + { + $methods[$name] = $refclass->getMethod($name); + $methods[$name]->setAccessible(true); + } + } + + foreach(array( + Api\Cache::TREE => 'tree', + Api\Cache::INSTANCE => 'instance', + ) as $level => $label) + { + $locations = array(); + foreach(array('string',123,true,false,null,array(),array(1,2,3)) as $data) + { + $location = md5(microtime(true).$label.serialize($data)); + $this->assertNull($methods['get']->invokeArgs($provider, array(array($level,__CLASS__,$location))), + "$class: $label: get_before_set"); + + $this->assertTrue($methods['set']->invokeArgs($provider, array(array($level,__CLASS__,$location), $data, 10)), + "$class: $label: set"); + + $this->assertEquals($data, $methods['get']->invokeArgs($provider, array(array($level,__CLASS__,$location))), + "$class: $label: get_after_set"); + + if (is_a($provider, 'EGroupware\Api\Cache\ProviderMultiple')) + { + $this->assertEquals(array($location => $data), + $methods['mget']->invokeArgs($provider, array(array($level,__CLASS__,array($location)))), + "$class: $label: mget_after_set"); + } + $this->assertNotTrue($methods['add']->invokeArgs($provider, array(array($level,__CLASS__,$location), 'other-data')), + "$class: $label: add_after_set"); + + $this->assertTrue($methods['delete']->invokeArgs($provider, array(array($level,__CLASS__,$location))), + "$class: $label: delete"); + + $this->assertNull($methods['get']->invokeArgs($provider, array(array($level,__CLASS__,$location))), + "$class: $label: get_after_delete"); + + // prepare for mget of everything + if (is_a($provider, 'EGroupware\Api\Cache\ProviderMultiple')) + { + $locations[$location] = $data; + $mget_after_delete = $methods['mget']->invokeArgs($provider, array(array($level,__CLASS__,array($location)))); + $this->assertNotTrue(isset($mget_after_delete[$location]), + "$class: $label: mget_after_delete['$location']"); + } + elseif (!is_null($data)) // emulation can NOT distinquish between null and not set + { + $locations[$location] = $data; + } + $this->assertTrue($methods['add']->invokeArgs($provider, array(array($level,__CLASS__,$location), $data, 10)), + "$class: $label: add_after_delete"); + + $this->assertEquals($data, $methods['get']->invokeArgs($provider, array(array($level,__CLASS__,$location))), + "$class: $label: get_after_add"); + } + // get all above in one request + $keys = array_keys($locations); + $keys_bogus = array_merge(array('not-set'),array_keys($locations),array('not-set-too')); + if (is_a($provider, 'EGroupware\Api\Cache\ProviderMultiple')) + { + $this->assertEquals($locations, $methods['mget']->invokeArgs($provider, array(array($level,__CLASS__,$keys))), + "$class: $label: mget_all"); + $this->assertEquals($locations, $methods['mget']->invokeArgs($provider, array(array($level,__CLASS__,$keys_bogus))), + "$class: $label: mget_with_bogus_key"); + } + } + } + catch (\Exception $e) { + error_log($e->getMessage()); + } + } + + /** + * Caching provides to set with constructor parameters + * + * @return array of array + */ + public static function cachingProvider() + { + // create empty temp. directory + unlink($tmp_dir = tempnam('/tmp', 'tmp')); + mkdir($tmp_dir); + + return array( + array(__NAMESPACE__.'\\Cache\\Apcu'), + array(__NAMESPACE__.'\\Cache\\Apc'), + array(__NAMESPACE__.'\\Cache\\Memcache', array('localhost')), + array(__NAMESPACE__.'\\Cache\\Memcached', array('localhost')), + array(__NAMESPACE__.'\\Cache\\Files', array($tmp_dir)), + ); + } +} diff --git a/doc/test-cli.php b/doc/test-cli.php index 31d047a2ef..f196bf8750 100755 --- a/doc/test-cli.php +++ b/doc/test-cli.php @@ -1,4 +1,4 @@ -#!/usr/bin/env php +#!/usr/bin/env php -dapc.enable_cli=1