From 1c4d1aa6b660844b54a071a47ffca11c8887e14b Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 29 Aug 2015 01:26:48 +0200 Subject: [PATCH] working on configuration unit test generator as described in #16 --- .gitattributes | 4 + lib/zerobin.php | 8 +- tst/configGenerator.php | 341 ++++++++++++++++++++++++++++++++++++++++ tst/configuration.php | 126 +++++++++++++++ tst/phpunit.xml | 1 + 5 files changed, 476 insertions(+), 4 deletions(-) create mode 100644 .gitattributes create mode 100755 tst/configGenerator.php create mode 100644 tst/configuration.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7bd2eb8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +doc/* export-ignore +tst/* export-ignore +.gitattributes export-ignore +.gitignore export-ignore \ No newline at end of file diff --git a/lib/zerobin.php b/lib/zerobin.php index ce10d04..ca17dc9 100644 --- a/lib/zerobin.php +++ b/lib/zerobin.php @@ -121,15 +121,15 @@ class zerobin { foreach (array('cfg', 'lib') as $dir) { - if (!is_file(PATH . $dir . '/.htaccess')) file_put_contents( - PATH . $dir . '/.htaccess', + if (!is_file(PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess')) file_put_contents( + PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess', 'Allow from none' . PHP_EOL . 'Deny from all'. PHP_EOL, LOCK_EX ); } - $this->_conf = parse_ini_file(PATH . 'cfg/conf.ini', true); + $this->_conf = parse_ini_file(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', true); foreach (array('main', 'model') as $section) { if (!array_key_exists($section, $this->_conf)) die( "ZeroBin requires configuration section [$section] to be present in configuration file." @@ -339,7 +339,7 @@ class zerobin // Generate the "delete" token. // The token is the hmac of the pasteid signed with the server salt. - // The paste can be delete by calling http://myserver.com/zerobin/?pasteid=&deletetoken= + // The paste can be delete by calling http://example.com/zerobin/?pasteid=&deletetoken= $deletetoken = hash_hmac('sha1', $dataid, serversalt::get()); // 0 = no error diff --git a/tst/configGenerator.php b/tst/configGenerator.php new file mode 100755 index 0000000..879262c --- /dev/null +++ b/tst/configGenerator.php @@ -0,0 +1,341 @@ +#!/usr/bin/env php + array( + array( + 'setting' => true, + 'tests' => array( + array( + 'type' => 'NotTag', + 'args' => array( + array( + 'id' => 'opendiscussion', + 'attributes' => array( + 'disabled' => 'disabled', + ), + ), + '$content', + 'outputs enabled discussion correctly' + ), + ), + ), + 'affects' => array('view') + ), array( + 'setting' => false, + 'tests' => array( + array( + 'type' => 'Tag', + 'args' => array( + array( + 'id' => 'opendiscussion', + 'attributes' => array( + 'disabled' => 'disabled', + ), + ), + '$content', + 'outputs disabled discussion correctly' + ), + ), + ), + 'affects' => array('view') + ), + ), + 'main/syntaxhighlighting' => array( + array( + 'setting' => true, + 'tests' => array( + array( + 'type' => 'Tag', + 'args' => array( + array( + 'tag' => 'link', + 'attributes' => array( + 'type' => 'text/css', + 'rel' => 'stylesheet', + 'href' => 'regexp:#css/prettify/prettify.css#', + ), + ), + '$content', + 'outputs stylesheet correctly', + ), + ), array( + 'type' => 'Tag', + 'args' => array( + array( + 'tag' => 'script', + 'attributes' => array( + 'type' => 'text/javascript', + 'src' => 'regexp:#js/prettify.js#' + ), + ), + '$content', + 'outputs javascript correctly', + ), + ), + ), + 'affects' => array('view'), + ), array( + 'setting' => false, + 'tests' => array( + array( + 'type' => 'NotTag', + 'args' => array( + array( + 'tag' => 'link', + 'attributes' => array( + 'type' => 'text/css', + 'rel' => 'stylesheet', + 'href' => 'regexp:#css/prettify/prettify.css#', + ), + ), + '$content', + 'removes stylesheet correctly', + ), + ), array( + 'type' => 'NotTag', + 'args' => array( + array( + 'tag' => 'script', + 'attributes' => array( + 'type' => 'text/javascript', + 'src' => 'regexp:#js/prettify.js#', + ), + ), + '$content', + 'removes javascript correctly', + ), + ), + ), + 'affects' => array('view'), + ), + ), +); + +// endless loop protection, since we're working with a recursive function, creating factorial configurations +define('MAX_ITERATIONS', 1000); + +// generate all possible combinations of configurations: (option * settings)! +$i = 0; +$configurations = array(array('options' => array(), 'tests' => array(), 'affects' => array())); +$configurations = getConfigurations($options, $configurations, $i); + +$defaultOptions = parse_ini_file(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', true); + +$code = <<<'EOT' + '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}', + 'meta' => array( + 'postdate' => 1344803344, + 'opendiscussion' => true, + ), + ); + + private $_model; + + private $_conf; + + public function setUp() + { + /* Setup Routine */ + $this->_conf = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini'; + if (!is_file($this->_conf . '.bak') && is_file($this->_conf)) + rename($this->_conf, $this->_conf . '.bak'); + + $this->_model = zerobin_data::getInstance(array('dir' => PATH . 'data')); + serversalt::setPath(PATH . 'data'); + $this->reset(); + } + + public function tearDown() + { + /* Tear Down Routine */ + rename($this->_conf . '.bak', $this->_conf); +} + + public function reset($configuration = array()) + { + $_POST = array(); + $_GET = array(); + $_SERVER = array(); + if ($this->_model->exists(self::$pasteid)) + $this->_model->delete(self::$pasteid); + + // generate configuration file + if (count($configuration)) { + @unlink($this->_conf); + $c = fopen($this->_conf, 'a'); + foreach ($configuration as $section => $options) { + fwrite($c, "[$section]" . PHP_EOL); + foreach($options as $option => $setting) { + if (is_string($setting)) { + $setting = '"' . $setting . '"'; + } else { + $setting = var_export($setting, true); + } + fwrite($c, "$option = $setting" . PHP_EOL); + } + fwrite($c, PHP_EOL); + } + fclose($c); + } + } + +EOT; + +foreach ($configurations as $key => $conf) { + $options = var_export_min(array_replace_recursive($defaultOptions, $conf['options']), true); + foreach ($conf['affects'] as $step) { + $step = ucfirst($step); + switch ($step) { + case 'Create': + // @todo + continue; + break; + case 'Read': + // @todo + continue; + break; + case 'Delete': + // @todo + continue; + break; + // view + default: + $code .= <<reset($options); + ob_start(); + new zerobin; + \$content = ob_get_contents(); + + +EOT; + } + + foreach ($conf['tests'] as $tests) { + foreach ($tests as $test) { + $args = array(); + foreach ($test['args'] as $arg) { + if ($arg == '$content') { + $args[] = $arg; + } else { + $args[] = var_export_min($arg, true); + } + } + $type = $test['type']; + $args = implode(', ', $args); + $code .= <<assert$type($args); + +EOT; + } + } + $code .= <<<'EOT' + } + + +EOT; + } +} + +$code .= '}' . PHP_EOL; + +file_put_contents('configuration.php', $code); + +// recursive factorial function +function getConfigurations(&$options, &$configurations, &$i) { + if (++$i > MAX_ITERATIONS) { + echo "max iterations reached, stopping", PHP_EOL; + return $configurations; + } + echo "getConfigurations: iteration $i", PHP_EOL; + $continue = list($path, $settings) = each($options); + if ($continue === false) { + return $configurations; + } + list($section, $option) = explode('/', $path); + for ($c = 0, $max = count($configurations); $c < $max; ++$c) { + if (!array_key_exists($section, $configurations[$c]['options'])) { + $configurations[$c]['options'][$section] = array(); + } + if (count($settings) == 0) { + throw new Exception("Check your \$options: option $option has no settings!"); + } + // set the first setting in the original configuration + $setting = current($settings); + addSetting($configurations[$c], $setting, $section, $option, $i); + + // create clones for each of the other settings + while ($setting = next($settings)) { + $clone = $configurations[$c]; + $configurations[] = addSetting($clone, $setting, $section, $option, $i); + } + reset($settings); + } + return getConfigurations($options, $configurations, $i); +} + +function addSetting(&$configuration, &$setting, &$section, &$option, &$i) { + if (++$i > MAX_ITERATIONS) { + echo "max iterations reached, stopping", PHP_EOL; + return $configuration; + } + echo "addSetting: iteration $i", PHP_EOL; + if ( + array_key_exists($option, $configuration['options'][$section]) && + $configuration['options'][$section][$option] === $setting['setting'] + ) { + $val = var_export_min($setting['setting'], true); + throw new Exception("Endless loop or error in options detected: option '$option' already exists with setting '$val' in one of the configurations!"); + } + $configuration['options'][$section][$option] = $setting['setting']; + $configuration['tests'][$option] = $setting['tests']; + foreach ($setting['affects'] as $affects) { + if (!in_array($affects, $configuration['affects'])) { + $configuration['affects'][] = $affects; + } + } + return $configuration; +} + +// by linus@flowingcreativity.net via php.net +function var_export_min($var, $return = false) { + if (is_array($var)) { + $toImplode = array(); + foreach ($var as $key => $value) { + $toImplode[] = var_export($key, true).' => '.var_export_min($value, true); + } + $code = 'array('.implode(', ', $toImplode).')'; + if ($return) { + return $code; + } else { + echo $code; + } + } else { + return var_export($var, $return); + } +} diff --git a/tst/configuration.php b/tst/configuration.php new file mode 100644 index 0000000..05dcda6 --- /dev/null +++ b/tst/configuration.php @@ -0,0 +1,126 @@ + '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}', + 'meta' => array( + 'postdate' => 1344803344, + 'opendiscussion' => true, + ), + ); + + private $_model; + + private $_conf; + + public function setUp() + { + /* Setup Routine */ + $this->_conf = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini'; + if (!is_file($this->_conf . '.bak') && is_file($this->_conf)) + rename($this->_conf, $this->_conf . '.bak'); + + $this->_model = zerobin_data::getInstance(array('dir' => PATH . 'data')); + serversalt::setPath(PATH . 'data'); + $this->reset(); + } + + public function tearDown() + { + /* Tear Down Routine */ + rename($this->_conf . '.bak', $this->_conf); +} + + public function reset($configuration = array()) + { + $_POST = array(); + $_GET = array(); + $_SERVER = array(); + if ($this->_model->exists(self::$pasteid)) + $this->_model->delete(self::$pasteid); + + // generate configuration file + if (count($configuration)) { + @unlink($this->_conf); + $c = fopen($this->_conf, 'a'); + foreach ($configuration as $section => $options) { + fwrite($c, "[$section]" . PHP_EOL); + foreach($options as $option => $setting) { + if (is_string($setting)) { + $setting = '"' . $setting . '"'; + } else { + $setting = var_export($setting, true); + } + fwrite($c, "$option = $setting" . PHP_EOL); + } + fwrite($c, PHP_EOL); + } + fclose($c); + } + } + /** + * @runInSeparateProcess + */ + public function testView0() + { + $this->reset(array('main' => array('opendiscussion' => true, 'syntaxhighlighting' => true, 'burnafterreadingselected' => '', 'sizelimit' => '2097152', 'template' => 'bootstrap', 'base64version' => '2.1.9'), 'expire' => array('default' => '1month'), 'expire_options' => array('5min' => '300', '10min' => '600', '1hour' => '3600', '1day' => '86400', '1week' => '604800', '1month' => '2592000', '1year' => '31536000', 'never' => '0'), 'expire_labels' => array('5min' => '5 minutes', '10min' => '10 minutes', '1hour' => '1 hour', '1day' => '1 day', '1week' => '1 week', '1month' => '1 month', '1year' => '1 year', 'never' => 'Never'), 'traffic' => array('limit' => '10', 'dir' => '../data'), 'model' => array('class' => 'zerobin_data'), 'model_options' => array('dir' => '../data'))); + ob_start(); + new zerobin; + $content = ob_get_contents(); + + $this->assertNotTag(array('id' => 'opendiscussion', 'attributes' => array('disabled' => 'disabled')), $content, 'outputs enabled discussion correctly'); + $this->assertTag(array('tag' => 'link', 'attributes' => array('type' => 'text/css', 'rel' => 'stylesheet', 'href' => 'regexp:#css/prettify/prettify.css#')), $content, 'outputs stylesheet correctly'); + $this->assertTag(array('tag' => 'script', 'attributes' => array('type' => 'text/javascript', 'src' => 'regexp:#js/prettify.js#')), $content, 'outputs javascript correctly'); + } + + /** + * @runInSeparateProcess + */ + public function testView1() + { + $this->reset(array('main' => array('opendiscussion' => false, 'syntaxhighlighting' => true, 'burnafterreadingselected' => '', 'sizelimit' => '2097152', 'template' => 'bootstrap', 'base64version' => '2.1.9'), 'expire' => array('default' => '1month'), 'expire_options' => array('5min' => '300', '10min' => '600', '1hour' => '3600', '1day' => '86400', '1week' => '604800', '1month' => '2592000', '1year' => '31536000', 'never' => '0'), 'expire_labels' => array('5min' => '5 minutes', '10min' => '10 minutes', '1hour' => '1 hour', '1day' => '1 day', '1week' => '1 week', '1month' => '1 month', '1year' => '1 year', 'never' => 'Never'), 'traffic' => array('limit' => '10', 'dir' => '../data'), 'model' => array('class' => 'zerobin_data'), 'model_options' => array('dir' => '../data'))); + ob_start(); + new zerobin; + $content = ob_get_contents(); + + $this->assertTag(array('id' => 'opendiscussion', 'attributes' => array('disabled' => 'disabled')), $content, 'outputs disabled discussion correctly'); + $this->assertTag(array('tag' => 'link', 'attributes' => array('type' => 'text/css', 'rel' => 'stylesheet', 'href' => 'regexp:#css/prettify/prettify.css#')), $content, 'outputs stylesheet correctly'); + $this->assertTag(array('tag' => 'script', 'attributes' => array('type' => 'text/javascript', 'src' => 'regexp:#js/prettify.js#')), $content, 'outputs javascript correctly'); + } + + /** + * @runInSeparateProcess + */ + public function testView2() + { + $this->reset(array('main' => array('opendiscussion' => true, 'syntaxhighlighting' => false, 'burnafterreadingselected' => '', 'sizelimit' => '2097152', 'template' => 'bootstrap', 'base64version' => '2.1.9'), 'expire' => array('default' => '1month'), 'expire_options' => array('5min' => '300', '10min' => '600', '1hour' => '3600', '1day' => '86400', '1week' => '604800', '1month' => '2592000', '1year' => '31536000', 'never' => '0'), 'expire_labels' => array('5min' => '5 minutes', '10min' => '10 minutes', '1hour' => '1 hour', '1day' => '1 day', '1week' => '1 week', '1month' => '1 month', '1year' => '1 year', 'never' => 'Never'), 'traffic' => array('limit' => '10', 'dir' => '../data'), 'model' => array('class' => 'zerobin_data'), 'model_options' => array('dir' => '../data'))); + ob_start(); + new zerobin; + $content = ob_get_contents(); + + $this->assertNotTag(array('id' => 'opendiscussion', 'attributes' => array('disabled' => 'disabled')), $content, 'outputs enabled discussion correctly'); + $this->assertNotTag(array('tag' => 'link', 'attributes' => array('type' => 'text/css', 'rel' => 'stylesheet', 'href' => 'regexp:#css/prettify/prettify.css#')), $content, 'removes stylesheet correctly'); + $this->assertNotTag(array('tag' => 'script', 'attributes' => array('type' => 'text/javascript', 'src' => 'regexp:#js/prettify.js#')), $content, 'removes javascript correctly'); + } + + /** + * @runInSeparateProcess + */ + public function testView3() + { + $this->reset(array('main' => array('opendiscussion' => false, 'syntaxhighlighting' => false, 'burnafterreadingselected' => '', 'sizelimit' => '2097152', 'template' => 'bootstrap', 'base64version' => '2.1.9'), 'expire' => array('default' => '1month'), 'expire_options' => array('5min' => '300', '10min' => '600', '1hour' => '3600', '1day' => '86400', '1week' => '604800', '1month' => '2592000', '1year' => '31536000', 'never' => '0'), 'expire_labels' => array('5min' => '5 minutes', '10min' => '10 minutes', '1hour' => '1 hour', '1day' => '1 day', '1week' => '1 week', '1month' => '1 month', '1year' => '1 year', 'never' => 'Never'), 'traffic' => array('limit' => '10', 'dir' => '../data'), 'model' => array('class' => 'zerobin_data'), 'model_options' => array('dir' => '../data'))); + ob_start(); + new zerobin; + $content = ob_get_contents(); + + $this->assertTag(array('id' => 'opendiscussion', 'attributes' => array('disabled' => 'disabled')), $content, 'outputs disabled discussion correctly'); + $this->assertNotTag(array('tag' => 'link', 'attributes' => array('type' => 'text/css', 'rel' => 'stylesheet', 'href' => 'regexp:#css/prettify/prettify.css#')), $content, 'removes stylesheet correctly'); + $this->assertNotTag(array('tag' => 'script', 'attributes' => array('type' => 'text/javascript', 'src' => 'regexp:#js/prettify.js#')), $content, 'removes javascript correctly'); + } + +} diff --git a/tst/phpunit.xml b/tst/phpunit.xml index eeed5e6..4ef7c2c 100644 --- a/tst/phpunit.xml +++ b/tst/phpunit.xml @@ -1,6 +1,7 @@ ./ + configGenerator.php