PageRenderTime 63ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/php/external/PHPUnit/Util/Filter.php

https://github.com/anirvan/shindig-profiles
PHP | 482 lines | 202 code | 49 blank | 231 comment | 43 complexity | c33242a5fd74608ed451e10947040137 MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. /**
  3. * PHPUnit
  4. *
  5. * Copyright (c) 2002-2008, Sebastian Bergmann <sb@sebastian-bergmann.de>.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * Neither the name of Sebastian Bergmann nor the names of his
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  34. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. * @category Testing
  38. * @package PHPUnit
  39. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  40. * @copyright 2002-2008 Sebastian Bergmann <sb@sebastian-bergmann.de>
  41. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  42. * @version SVN: $Id: Filter.php 2041 2008-01-08 10:00:39Z sb $
  43. * @link http://www.phpunit.de/
  44. * @since File available since Release 2.0.0
  45. */
  46. require_once 'PHPUnit/Util/FilterIterator.php';
  47. /**
  48. * Utility class for code filtering.
  49. *
  50. * @category Testing
  51. * @package PHPUnit
  52. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  53. * @copyright 2002-2008 Sebastian Bergmann <sb@sebastian-bergmann.de>
  54. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  55. * @version Release: 3.2.9
  56. * @link http://www.phpunit.de/
  57. * @since Class available since Release 2.0.0
  58. */
  59. class PHPUnit_Util_Filter {
  60. /**
  61. * @var boolean
  62. * @access public
  63. * @static
  64. */
  65. public static $addUncoveredFilesFromWhitelist = TRUE;
  66. /**
  67. * @var boolean
  68. * @access public
  69. * @static
  70. */
  71. public static $filterPHPUnit = TRUE;
  72. /**
  73. * @var boolean
  74. * @access protected
  75. * @static
  76. */
  77. protected static $filter = TRUE;
  78. /**
  79. * @var boolean
  80. * @access protected
  81. * @static
  82. */
  83. protected static $blackListConverstionForWindowsDone = FALSE;
  84. /**
  85. * Source files that are blacklisted.
  86. *
  87. * @var array
  88. * @access protected
  89. * @static
  90. */
  91. protected static $blacklistedFiles = array('DEFAULT' => array(), 'PHPUNIT' => array(), 'TESTS' => array(),
  92. 'PEAR' => array('Console/Getopt.php', 'Image/GraphViz.php', 'Log/composite.php',
  93. 'Log/console.php', 'Log/daemon.php', 'Log/display.php',
  94. 'Log/error_log.php', 'Log/file.php', 'Log/mail.php', 'Log/mcal.php',
  95. 'Log/mdb2.php', 'Log/null.php', 'Log/observer.php', 'Log/sql.php',
  96. 'Log/sqlite.php', 'Log/syslog.php', 'Log/win.php', 'Log.php',
  97. 'PEAR/Installer/Role/Common.php', 'PEAR/Installer/Role.php',
  98. 'PEAR/Config.php', 'PEAR/DependencyDB.php', 'PEAR/Registry.php',
  99. 'PEAR/Remote.php', 'PEAR/RunTest.php', 'PEAR/XMLParser.php',
  100. 'PEAR.php', 'System.php'));
  101. /**
  102. * Source files that are whitelisted.
  103. *
  104. * @var array
  105. * @access protected
  106. * @static
  107. */
  108. protected static $whitelistedFiles = array();
  109. /**
  110. * Adds a directory to the blacklist (recursively).
  111. *
  112. * @param string $directory
  113. * @param string $suffix
  114. * @param string $group
  115. * @access public
  116. * @static
  117. * @since Method available since Release 3.1.5
  118. */
  119. public static function addDirectoryToFilter($directory, $suffix = '.php', $group = 'DEFAULT') {
  120. if (file_exists($directory)) {
  121. foreach (self::getIterator($directory, $suffix) as $file) {
  122. self::addFileToFilter($file->getPathName(), $group);
  123. }
  124. }
  125. }
  126. /**
  127. * Adds a new file to be filtered (blacklist).
  128. *
  129. * @param string $filename
  130. * @param string $group
  131. * @access public
  132. * @static
  133. * @since Method available since Release 2.1.0
  134. */
  135. public static function addFileToFilter($filename, $group = 'DEFAULT') {
  136. if (file_exists($filename)) {
  137. $filename = realpath($filename);
  138. if (! isset(self::$blacklistedFiles[$group])) {
  139. self::$blacklistedFiles[$group] = array($filename);
  140. }
  141. else if (! in_array($filename, self::$blacklistedFiles[$group])) {
  142. self::$blacklistedFiles[$group][] = $filename;
  143. }
  144. }
  145. }
  146. /**
  147. * Removes a directory from the blacklist (recursively).
  148. *
  149. * @param string $directory
  150. * @param string $suffix
  151. * @param string $group
  152. * @access public
  153. * @static
  154. * @since Method available since Release 3.1.5
  155. */
  156. public static function removeDirectoryFromFilter($directory, $suffix = '.php', $group = 'DEFAULT') {
  157. if (file_exists($directory)) {
  158. foreach (self::getIterator($directory, $suffix) as $file) {
  159. self::removeFileFromFilter($file->getPathName(), $group);
  160. }
  161. }
  162. }
  163. /**
  164. * Removes a file from the filter (blacklist).
  165. *
  166. * @param string $filename
  167. * @param string $group
  168. * @access public
  169. * @static
  170. * @since Method available since Release 2.1.0
  171. */
  172. public static function removeFileFromFilter($filename, $group = 'DEFAULT') {
  173. if (file_exists($filename)) {
  174. if (isset(self::$blacklistedFiles[$group])) {
  175. $filename = realpath($filename);
  176. foreach (self::$blacklistedFiles[$group] as $key => $_filename) {
  177. if ($filename == $_filename) {
  178. unset(self::$blacklistedFiles[$group][$key]);
  179. }
  180. }
  181. }
  182. }
  183. }
  184. /**
  185. * Adds a directory to the whitelist (recursively).
  186. *
  187. * @param string $directory
  188. * @param string $suffix
  189. * @access public
  190. * @static
  191. * @since Method available since Release 3.1.5
  192. */
  193. public static function addDirectoryToWhitelist($directory, $suffix = '.php') {
  194. if (file_exists($directory)) {
  195. foreach (self::getIterator($directory, $suffix) as $file) {
  196. self::addFileToWhitelist($file->getPathName());
  197. }
  198. }
  199. }
  200. /**
  201. * Adds a new file to the whitelist.
  202. *
  203. * When the whitelist is empty (default), blacklisting is used.
  204. * When the whitelist is not empty, whitelisting is used.
  205. *
  206. * @param string $filename
  207. * @access public
  208. * @static
  209. * @since Method available since Release 3.1.0
  210. */
  211. public static function addFileToWhitelist($filename) {
  212. if (file_exists($filename)) {
  213. $filename = realpath($filename);
  214. if (! in_array($filename, self::$whitelistedFiles)) {
  215. self::$whitelistedFiles[] = $filename;
  216. }
  217. }
  218. }
  219. /**
  220. * Removes a directory from the whitelist (recursively).
  221. *
  222. * @param string $directory
  223. * @param string $suffix
  224. * @access public
  225. * @static
  226. * @since Method available since Release 3.1.5
  227. */
  228. public static function removeDirectoryFromWhitelist($directory, $suffix = '.php') {
  229. if (file_exists($directory)) {
  230. foreach (self::getIterator($directory, $suffix) as $file) {
  231. self::removeFileFromWhitelist($file->getPathName());
  232. }
  233. }
  234. }
  235. /**
  236. * Removes a file from the whitelist.
  237. *
  238. * @param string $filename
  239. * @access public
  240. * @static
  241. * @since Method available since Release 3.1.0
  242. */
  243. public static function removeFileFromWhitelist($filename) {
  244. if (file_exists($filename)) {
  245. $filename = realpath($filename);
  246. foreach (self::$whitelistedFiles as $key => $_filename) {
  247. if ($filename == $_filename) {
  248. unset(self::$whitelistedFiles[$key]);
  249. }
  250. }
  251. }
  252. }
  253. /**
  254. * Returns data about files within code coverage information, specifically
  255. * which ones will be filtered out and which ones may be whitelisted but not
  256. * touched by coverage.
  257. *
  258. * Returns a two-item array. The first item is an array indexed by filenames
  259. * with a boolean payload of whether they should be filtered out.
  260. *
  261. * The second item is an array of filenames which are
  262. * whitelisted but which are absent from the coverage information.
  263. *
  264. * @param array $codeCoverageInformation
  265. * @param boolean $filterTests
  266. * @return array
  267. * @access public
  268. * @static
  269. */
  270. public static function getFileCodeCoverageDisposition(array $codeCoverageInformation, $filterTests = TRUE) {
  271. if (! self::$filter) {
  272. return array(array(), array());
  273. }
  274. $isFilteredCache = array();
  275. $coveredFiles = array();
  276. foreach ($codeCoverageInformation as $k => $test) {
  277. foreach (array_keys($test['files']) as $file) {
  278. if (! isset($isFilteredCache[$file])) {
  279. $isFilteredCache[$file] = self::isFiltered($file, $filterTests);
  280. }
  281. }
  282. }
  283. $coveredFiles = array_keys($isFilteredCache);
  284. $missedFiles = array_diff(self::$whitelistedFiles, $coveredFiles);
  285. $missedFiles = array_filter($missedFiles, 'file_exists');
  286. return array($isFilteredCache, $missedFiles);
  287. }
  288. /**
  289. * @param array $codeCoverageInformation
  290. * @param boolean $addUncoveredFilesFromWhitelist
  291. * @return array
  292. * @access public
  293. * @static
  294. */
  295. public static function getFilteredCodeCoverage(array $codeCoverageInformation, $filterTests = TRUE) {
  296. if (self::$filter) {
  297. list($isFilteredCache, $missedFiles) = self::getFileCodeCoverageDisposition($codeCoverageInformation, $filterTests);
  298. foreach ($codeCoverageInformation as $k => $test) {
  299. foreach (array_keys($test['files']) as $file) {
  300. if ($isFilteredCache[$file]) {
  301. unset($codeCoverageInformation[$k]['files'][$file]);
  302. }
  303. }
  304. }
  305. if (self::$addUncoveredFilesFromWhitelist) {
  306. foreach ($missedFiles as $missedFile) {
  307. xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
  308. include_once $missedFile;
  309. $coverage = xdebug_get_code_coverage();
  310. xdebug_stop_code_coverage();
  311. if (isset($coverage[$missedFile])) {
  312. foreach ($coverage[$missedFile] as $line => $flag) {
  313. if ($flag > 0) {
  314. $coverage[$missedFile][$line] = - 1;
  315. }
  316. }
  317. $codeCoverageInformation[] = array('test' => NULL,
  318. 'files' => array(
  319. $missedFile => $coverage[$missedFile]));
  320. }
  321. }
  322. }
  323. }
  324. return $codeCoverageInformation;
  325. }
  326. /**
  327. * Filters stack frames from PHPUnit classes.
  328. *
  329. * @param Exception $e
  330. * @param boolean $filterTests
  331. * @param boolean $asString
  332. * @return string
  333. * @access public
  334. * @static
  335. */
  336. public static function getFilteredStacktrace(Exception $e, $filterTests = TRUE, $asString = TRUE) {
  337. if ($asString === TRUE) {
  338. $filteredStacktrace = '';
  339. } else {
  340. $filteredStacktrace = array();
  341. }
  342. foreach ($e->getTrace() as $frame) {
  343. if (! self::$filter || (isset($frame['file']) && ! self::isFiltered($frame['file'], $filterTests, TRUE))) {
  344. if ($asString === TRUE) {
  345. $filteredStacktrace .= sprintf("%s:%s\n",
  346. $frame['file'], isset($frame['line']) ? $frame['line'] : '?');
  347. } else {
  348. $filteredStacktrace[] = $frame;
  349. }
  350. }
  351. }
  352. return $filteredStacktrace;
  353. }
  354. /**
  355. * Activates or deactivates filtering.
  356. *
  357. * @param boolean $filter
  358. * @throws InvalidArgumentException
  359. * @access public
  360. * @static
  361. * @since Method available since Release 3.0.0
  362. */
  363. public static function setFilter($filter) {
  364. if (is_bool($filter)) {
  365. self::$filter = $filter;
  366. } else {
  367. throw new InvalidArgumentException();
  368. }
  369. }
  370. /**
  371. * Returns a PHPUnit_Util_FilterIterator that iterates
  372. * over all files in the given directory that have the
  373. * given suffix.
  374. *
  375. * @param string $directory
  376. * @param string $suffix
  377. * @return Iterator
  378. * @access protected
  379. * @static
  380. * @since Method available since Release 3.1.5
  381. */
  382. protected static function getIterator($directory, $suffix) {
  383. return new PHPUnit_Util_FilterIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)), $suffix);
  384. }
  385. /**
  386. * @param string $filename
  387. * @param boolean $filterTests
  388. * @param boolean $ignoreWhitelist
  389. * @return boolean
  390. * @access protected
  391. * @static
  392. * @since Method available since Release 2.1.3
  393. */
  394. protected static function isFiltered($filename, $filterTests = TRUE, $ignoreWhitelist = FALSE) {
  395. $filename = realpath($filename);
  396. // Use blacklist.
  397. if ($ignoreWhitelist || empty(self::$whitelistedFiles)) {
  398. if (DIRECTORY_SEPARATOR == '\\' && ! self::$blackListConverstionForWindowsDone) {
  399. $count = count(self::$blacklistedFiles['PEAR']);
  400. for ($i = 0; $i < $count; $i ++) {
  401. self::$blacklistedFiles['PEAR'][$i] = str_replace('/', '\\', self::$blacklistedFiles['PEAR'][$i]);
  402. }
  403. self::$blackListConverstionForWindowsDone = TRUE;
  404. }
  405. $blacklistedFiles = array_merge(self::$blacklistedFiles['DEFAULT'], self::$blacklistedFiles['PEAR']);
  406. if ($filterTests) {
  407. $blacklistedFiles = array_merge($blacklistedFiles, self::$blacklistedFiles['TESTS']);
  408. }
  409. if (self::$filterPHPUnit) {
  410. $blacklistedFiles = array_merge($blacklistedFiles, self::$blacklistedFiles['PHPUNIT']);
  411. }
  412. if (in_array($filename, $blacklistedFiles)) {
  413. return TRUE;
  414. }
  415. foreach ($blacklistedFiles as $filteredFile) {
  416. if (strpos($filename, $filteredFile) !== FALSE) {
  417. return TRUE;
  418. }
  419. }
  420. return FALSE;
  421. }
  422. // Use whitelist.
  423. else {
  424. if (in_array($filename, self::$whitelistedFiles)) {
  425. return FALSE;
  426. }
  427. return TRUE;
  428. }
  429. }
  430. }
  431. PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
  432. ?>