run.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. error_reporting(E_ALL | E_STRICT);
  3. ini_set('short_open_tag', false);
  4. if ('cli' !== php_sapi_name()) {
  5. die('This script is designed for running on the command line.');
  6. }
  7. function showHelp($error) {
  8. die($error . "\n\n" .
  9. <<<OUTPUT
  10. This script has to be called with the following signature:
  11. php run.php [--no-progress] testType pathToTestFiles
  12. The test type can be either "Symfony" or "PHP".
  13. The following options are available:
  14. --no-progress Disables showing which file is currently tested.
  15. OUTPUT
  16. );
  17. }
  18. $options = array();
  19. $arguments = array();
  20. // remove script name from argv
  21. array_shift($argv);
  22. foreach ($argv as $arg) {
  23. if ('-' === $arg[0]) {
  24. $options[] = $arg;
  25. } else {
  26. $arguments[] = $arg;
  27. }
  28. }
  29. if (count($arguments) !== 2) {
  30. showHelp('Too little arguments passed!');
  31. }
  32. $SHOW_PROGRESS = true;
  33. if (count($options) > 0) {
  34. if (count($options) === 1 && $options[0] === '--no-progress') {
  35. $SHOW_PROGRESS = false;
  36. } else {
  37. showHelp('Invalid option passed!');
  38. }
  39. }
  40. $TEST_TYPE = $arguments[0];
  41. $DIR = $arguments[1];
  42. if ('Symfony' === $TEST_TYPE) {
  43. function filter_func($path) {
  44. return preg_match('~\.php(?:\.cache)?$~', $path) && false === strpos($path, 'skeleton');
  45. };
  46. } elseif ('PHP' === $TEST_TYPE) {
  47. function filter_func($path) {
  48. return preg_match('~\.phpt$~', $path);
  49. };
  50. } else {
  51. showHelp('Test type must be either "Symfony" or "PHP"!');
  52. }
  53. require_once dirname(__FILE__) . '/../lib/PHPParser/Autoloader.php';
  54. PHPParser_Autoloader::register();
  55. $parser = new PHPParser_Parser(new PHPParser_Lexer_Emulative);
  56. $prettyPrinter = new PHPParser_PrettyPrinter_Default;
  57. $nodeDumper = new PHPParser_NodeDumper;
  58. $parseFail = $ppFail = $compareFail = $count = 0;
  59. $readTime = $parseTime = $ppTime = $reparseTime = $compareTime = 0;
  60. $totalStartTime = microtime(true);
  61. foreach (new RecursiveIteratorIterator(
  62. new RecursiveDirectoryIterator($DIR),
  63. RecursiveIteratorIterator::LEAVES_ONLY)
  64. as $file) {
  65. if (!filter_func($file)) {
  66. continue;
  67. }
  68. $startTime = microtime(true);
  69. $code = file_get_contents($file);
  70. $readTime += microtime(true) - $startTime;
  71. if ('PHP' === $TEST_TYPE) {
  72. if (preg_match('~(?:
  73. # skeleton files
  74. ext.gmp.tests.001
  75. | ext.skeleton.tests.001
  76. # multibyte encoded files
  77. | ext.mbstring.tests.zend_multibyte-01
  78. | Zend.tests.multibyte.multibyte_encoding_001
  79. | Zend.tests.multibyte.multibyte_encoding_004
  80. | Zend.tests.multibyte.multibyte_encoding_005
  81. # token_get_all bug (https://bugs.php.net/bug.php?id=60097)
  82. | Zend.tests.bug47516
  83. # pretty print difference due to INF vs 1e1000
  84. | ext.standard.tests.general_functions.bug27678
  85. | tests.lang.bug24640
  86. )\.phpt$~x', $file)) {
  87. continue;
  88. }
  89. if (!preg_match('~--FILE--\s*(.*?)--[A-Z]+--~s', $code, $matches)) {
  90. continue;
  91. }
  92. if (preg_match('~--EXPECT(?:F|REGEX)?--\s*(?:Parse|Fatal) error~', $code)) {
  93. continue;
  94. }
  95. $code = $matches[1];
  96. }
  97. set_time_limit(10);
  98. ++$count;
  99. if ($SHOW_PROGRESS) {
  100. echo substr(str_pad('Testing file ' . $count . ': ' . substr($file, strlen($DIR)), 79), 0, 79), "\r";
  101. }
  102. try {
  103. $startTime = microtime(true);
  104. $stmts = $parser->parse($code);
  105. $parseTime += microtime(true) - $startTime;
  106. $startTime = microtime(true);
  107. $code = '<?php' . "\n" . $prettyPrinter->prettyPrint($stmts);
  108. $ppTime += microtime(true) - $startTime;
  109. try {
  110. $startTime = microtime(true);
  111. $ppStmts = $parser->parse($code);
  112. $reparseTime += microtime(true) - $startTime;
  113. $startTime = microtime(true);
  114. $same = $nodeDumper->dump($stmts) == $nodeDumper->dump($ppStmts);
  115. $compareTime += microtime(true) - $startTime;
  116. if (!$same) {
  117. echo $file, ":\n Result of initial parse and parse after pretty print differ\n";
  118. ++$compareFail;
  119. }
  120. } catch (PHPParser_Error $e) {
  121. echo $file, ":\n Parse of pretty print failed with message: {$e->getMessage()}\n";
  122. ++$ppFail;
  123. }
  124. } catch (PHPParser_Error $e) {
  125. echo $file, ":\n Parse failed with message: {$e->getMessage()}\n";
  126. ++$parseFail;
  127. }
  128. }
  129. if (0 === $parseFail && 0 === $ppFail && 0 === $compareFail) {
  130. echo "\n\n", 'All tests passed.', "\n";
  131. } else {
  132. echo "\n\n", '==========', "\n\n", 'There were: ', "\n";
  133. if (0 !== $parseFail) {
  134. echo ' ', $parseFail, ' parse failures.', "\n";
  135. }
  136. if (0 !== $ppFail) {
  137. echo ' ', $ppFail, ' pretty print failures.', "\n";
  138. }
  139. if (0 !== $compareFail) {
  140. echo ' ', $compareFail, ' compare failures.', "\n";
  141. }
  142. }
  143. echo "\n",
  144. 'Tested files: ', $count, "\n",
  145. "\n",
  146. 'Reading files took: ', $readTime, "\n",
  147. 'Parsing took: ', $parseTime, "\n",
  148. 'Pretty printing took: ', $ppTime, "\n",
  149. 'Reparsing took: ', $reparseTime, "\n",
  150. 'Comparing took: ', $compareTime, "\n",
  151. "\n",
  152. 'Total time: ', microtime(true) - $totalStartTime, "\n",
  153. 'Maximum memory usage: ', memory_get_peak_usage(true), "\n";