configGenerator.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #!/usr/bin/env php
  2. <?php
  3. /**
  4. * generates a config unit test class
  5. *
  6. * This generator is meant to test all possible configuration combinations
  7. * without having to write endless amounts of code manually.
  8. *
  9. * DANGER: Too many options/settings and too high max iteration setting may trigger
  10. * a fork bomb. Please save your work before executing this script.
  11. */
  12. include 'bootstrap.php';
  13. $options = array(
  14. 'main/opendiscussion' => array(
  15. array(
  16. 'setting' => true,
  17. 'tests' => array(
  18. array(
  19. 'type' => 'NotTag',
  20. 'args' => array(
  21. array(
  22. 'id' => 'opendiscussion',
  23. 'attributes' => array(
  24. 'disabled' => 'disabled',
  25. ),
  26. ),
  27. '$content',
  28. 'outputs enabled discussion correctly'
  29. ),
  30. ),
  31. ),
  32. 'affects' => array('view')
  33. ), array(
  34. 'setting' => false,
  35. 'tests' => array(
  36. array(
  37. 'type' => 'Tag',
  38. 'args' => array(
  39. array(
  40. 'id' => 'opendiscussion',
  41. 'attributes' => array(
  42. 'disabled' => 'disabled',
  43. ),
  44. ),
  45. '$content',
  46. 'outputs disabled discussion correctly'
  47. ),
  48. ),
  49. ),
  50. 'affects' => array('view')
  51. ),
  52. ),
  53. 'main/syntaxhighlighting' => array(
  54. array(
  55. 'setting' => true,
  56. 'tests' => array(
  57. array(
  58. 'type' => 'Tag',
  59. 'args' => array(
  60. array(
  61. 'tag' => 'link',
  62. 'attributes' => array(
  63. 'type' => 'text/css',
  64. 'rel' => 'stylesheet',
  65. 'href' => 'regexp:#css/prettify/prettify.css#',
  66. ),
  67. ),
  68. '$content',
  69. 'outputs stylesheet correctly',
  70. ),
  71. ), array(
  72. 'type' => 'Tag',
  73. 'args' => array(
  74. array(
  75. 'tag' => 'script',
  76. 'attributes' => array(
  77. 'type' => 'text/javascript',
  78. 'src' => 'regexp:#js/prettify.js#'
  79. ),
  80. ),
  81. '$content',
  82. 'outputs javascript correctly',
  83. ),
  84. ),
  85. ),
  86. 'affects' => array('view'),
  87. ), array(
  88. 'setting' => false,
  89. 'tests' => array(
  90. array(
  91. 'type' => 'NotTag',
  92. 'args' => array(
  93. array(
  94. 'tag' => 'link',
  95. 'attributes' => array(
  96. 'type' => 'text/css',
  97. 'rel' => 'stylesheet',
  98. 'href' => 'regexp:#css/prettify/prettify.css#',
  99. ),
  100. ),
  101. '$content',
  102. 'removes stylesheet correctly',
  103. ),
  104. ), array(
  105. 'type' => 'NotTag',
  106. 'args' => array(
  107. array(
  108. 'tag' => 'script',
  109. 'attributes' => array(
  110. 'type' => 'text/javascript',
  111. 'src' => 'regexp:#js/prettify.js#',
  112. ),
  113. ),
  114. '$content',
  115. 'removes javascript correctly',
  116. ),
  117. ),
  118. ),
  119. 'affects' => array('view'),
  120. ),
  121. ),
  122. );
  123. // endless loop protection, since we're working with a recursive function, creating factorial configurations
  124. define('MAX_ITERATIONS', 1000);
  125. // generate all possible combinations of configurations: (option * settings)!
  126. $i = 0;
  127. $configurations = array(array('options' => array(), 'tests' => array(), 'affects' => array()));
  128. $configurations = getConfigurations($options, $configurations, $i);
  129. $defaultOptions = parse_ini_file(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', true);
  130. $code = <<<'EOT'
  131. <?php
  132. /**
  133. * DO NOT EDIT: This file is automatically generated by configGenerator.php
  134. */
  135. class configTest extends PHPUnit_Framework_TestCase
  136. {
  137. private static $pasteid = '501f02e9eeb8bcec';
  138. private static $paste = array(
  139. 'data' => '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}',
  140. 'meta' => array(
  141. 'postdate' => 1344803344,
  142. 'opendiscussion' => true,
  143. ),
  144. );
  145. private $_model;
  146. private $_conf;
  147. public function setUp()
  148. {
  149. /* Setup Routine */
  150. $this->_conf = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini';
  151. if (!is_file($this->_conf . '.bak') && is_file($this->_conf))
  152. rename($this->_conf, $this->_conf . '.bak');
  153. $this->_model = zerobin_data::getInstance(array('dir' => PATH . 'data'));
  154. serversalt::setPath(PATH . 'data');
  155. $this->reset();
  156. }
  157. public function tearDown()
  158. {
  159. /* Tear Down Routine */
  160. rename($this->_conf . '.bak', $this->_conf);
  161. }
  162. public function reset($configuration = array())
  163. {
  164. $_POST = array();
  165. $_GET = array();
  166. $_SERVER = array();
  167. if ($this->_model->exists(self::$pasteid))
  168. $this->_model->delete(self::$pasteid);
  169. // generate configuration file
  170. if (count($configuration)) {
  171. @unlink($this->_conf);
  172. $c = fopen($this->_conf, 'a');
  173. foreach ($configuration as $section => $options) {
  174. fwrite($c, "[$section]" . PHP_EOL);
  175. foreach($options as $option => $setting) {
  176. if (is_string($setting)) {
  177. $setting = '"' . $setting . '"';
  178. } else {
  179. $setting = var_export($setting, true);
  180. }
  181. fwrite($c, "$option = $setting" . PHP_EOL);
  182. }
  183. fwrite($c, PHP_EOL);
  184. }
  185. fclose($c);
  186. }
  187. }
  188. EOT;
  189. foreach ($configurations as $key => $conf) {
  190. $options = var_export_min(array_replace_recursive($defaultOptions, $conf['options']), true);
  191. foreach ($conf['affects'] as $step) {
  192. $step = ucfirst($step);
  193. switch ($step) {
  194. case 'Create':
  195. // @todo
  196. continue;
  197. break;
  198. case 'Read':
  199. // @todo
  200. continue;
  201. break;
  202. case 'Delete':
  203. // @todo
  204. continue;
  205. break;
  206. // view
  207. default:
  208. $code .= <<<EOT
  209. /**
  210. * @runInSeparateProcess
  211. */
  212. public function test$step$key()
  213. {
  214. \$this->reset($options);
  215. ob_start();
  216. new zerobin;
  217. \$content = ob_get_contents();
  218. EOT;
  219. }
  220. foreach ($conf['tests'] as $tests) {
  221. foreach ($tests as $test) {
  222. $args = array();
  223. foreach ($test['args'] as $arg) {
  224. if ($arg == '$content') {
  225. $args[] = $arg;
  226. } else {
  227. $args[] = var_export_min($arg, true);
  228. }
  229. }
  230. $type = $test['type'];
  231. $args = implode(', ', $args);
  232. $code .= <<<EOT
  233. \$this->assert$type($args);
  234. EOT;
  235. }
  236. }
  237. $code .= <<<'EOT'
  238. }
  239. EOT;
  240. }
  241. }
  242. $code .= '}' . PHP_EOL;
  243. file_put_contents('configuration.php', $code);
  244. // recursive factorial function
  245. function getConfigurations(&$options, &$configurations, &$i) {
  246. if (++$i > MAX_ITERATIONS) {
  247. echo "max iterations reached, stopping", PHP_EOL;
  248. return $configurations;
  249. }
  250. echo "getConfigurations: iteration $i", PHP_EOL;
  251. $continue = list($path, $settings) = each($options);
  252. if ($continue === false) {
  253. return $configurations;
  254. }
  255. list($section, $option) = explode('/', $path);
  256. for ($c = 0, $max = count($configurations); $c < $max; ++$c) {
  257. if (!array_key_exists($section, $configurations[$c]['options'])) {
  258. $configurations[$c]['options'][$section] = array();
  259. }
  260. if (count($settings) == 0) {
  261. throw new Exception("Check your \$options: option $option has no settings!");
  262. }
  263. // set the first setting in the original configuration
  264. $setting = current($settings);
  265. addSetting($configurations[$c], $setting, $section, $option, $i);
  266. // create clones for each of the other settings
  267. while ($setting = next($settings)) {
  268. $clone = $configurations[$c];
  269. $configurations[] = addSetting($clone, $setting, $section, $option, $i);
  270. }
  271. reset($settings);
  272. }
  273. return getConfigurations($options, $configurations, $i);
  274. }
  275. function addSetting(&$configuration, &$setting, &$section, &$option, &$i) {
  276. if (++$i > MAX_ITERATIONS) {
  277. echo "max iterations reached, stopping", PHP_EOL;
  278. return $configuration;
  279. }
  280. echo "addSetting: iteration $i", PHP_EOL;
  281. if (
  282. array_key_exists($option, $configuration['options'][$section]) &&
  283. $configuration['options'][$section][$option] === $setting['setting']
  284. ) {
  285. $val = var_export_min($setting['setting'], true);
  286. throw new Exception("Endless loop or error in options detected: option '$option' already exists with setting '$val' in one of the configurations!");
  287. }
  288. $configuration['options'][$section][$option] = $setting['setting'];
  289. $configuration['tests'][$option] = $setting['tests'];
  290. foreach ($setting['affects'] as $affects) {
  291. if (!in_array($affects, $configuration['affects'])) {
  292. $configuration['affects'][] = $affects;
  293. }
  294. }
  295. return $configuration;
  296. }
  297. // by linus@flowingcreativity.net via php.net
  298. function var_export_min($var, $return = false) {
  299. if (is_array($var)) {
  300. $toImplode = array();
  301. foreach ($var as $key => $value) {
  302. $toImplode[] = var_export($key, true).' => '.var_export_min($value, true);
  303. }
  304. $code = 'array('.implode(', ', $toImplode).')';
  305. if ($return) {
  306. return $code;
  307. } else {
  308. echo $code;
  309. }
  310. } else {
  311. return var_export($var, $return);
  312. }
  313. }