PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://github.com/nevali/shindig
PHP | 550 lines | 270 code | 49 blank | 231 comment | 42 complexity | 27021e1785d3a17deafc285789dc9055 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. /**
  62. * @var boolean
  63. * @access public
  64. * @static
  65. */
  66. public static $addUncoveredFilesFromWhitelist = TRUE;
  67. /**
  68. * @var boolean
  69. * @access public
  70. * @static
  71. */
  72. public static $filterPHPUnit = TRUE;
  73. /**
  74. * @var boolean
  75. * @access protected
  76. * @static
  77. */
  78. protected static $filter = TRUE;
  79. /**
  80. * @var boolean
  81. * @access protected
  82. * @static
  83. */
  84. protected static $blackListConverstionForWindowsDone = FALSE;
  85. /**
  86. * Source files that are blacklisted.
  87. *
  88. * @var array
  89. * @access protected
  90. * @static
  91. */
  92. protected static $blacklistedFiles = array(
  93. 'DEFAULT' => array(),
  94. 'PHPUNIT' => array(),
  95. 'TESTS' => array(),
  96. 'PEAR' => array(
  97. 'Console/Getopt.php',
  98. 'Image/GraphViz.php',
  99. 'Log/composite.php',
  100. 'Log/console.php',
  101. 'Log/daemon.php',
  102. 'Log/display.php',
  103. 'Log/error_log.php',
  104. 'Log/file.php',
  105. 'Log/mail.php',
  106. 'Log/mcal.php',
  107. 'Log/mdb2.php',
  108. 'Log/null.php',
  109. 'Log/observer.php',
  110. 'Log/sql.php',
  111. 'Log/sqlite.php',
  112. 'Log/syslog.php',
  113. 'Log/win.php',
  114. 'Log.php',
  115. 'PEAR/Installer/Role/Common.php',
  116. 'PEAR/Installer/Role.php',
  117. 'PEAR/Config.php',
  118. 'PEAR/DependencyDB.php',
  119. 'PEAR/Registry.php',
  120. 'PEAR/Remote.php',
  121. 'PEAR/RunTest.php',
  122. 'PEAR/XMLParser.php',
  123. 'PEAR.php',
  124. 'System.php'
  125. )
  126. );
  127. /**
  128. * Source files that are whitelisted.
  129. *
  130. * @var array
  131. * @access protected
  132. * @static
  133. */
  134. protected static $whitelistedFiles = array();
  135. /**
  136. * Adds a directory to the blacklist (recursively).
  137. *
  138. * @param string $directory
  139. * @param string $suffix
  140. * @param string $group
  141. * @access public
  142. * @static
  143. * @since Method available since Release 3.1.5
  144. */
  145. public static function addDirectoryToFilter($directory, $suffix = '.php', $group = 'DEFAULT')
  146. {
  147. if (file_exists($directory)) {
  148. foreach (self::getIterator($directory, $suffix) as $file) {
  149. self::addFileToFilter($file->getPathName(), $group);
  150. }
  151. }
  152. }
  153. /**
  154. * Adds a new file to be filtered (blacklist).
  155. *
  156. * @param string $filename
  157. * @param string $group
  158. * @access public
  159. * @static
  160. * @since Method available since Release 2.1.0
  161. */
  162. public static function addFileToFilter($filename, $group = 'DEFAULT')
  163. {
  164. if (file_exists($filename)) {
  165. $filename = realpath($filename);
  166. if (!isset(self::$blacklistedFiles[$group])) {
  167. self::$blacklistedFiles[$group] = array($filename);
  168. }
  169. else if (!in_array($filename, self::$blacklistedFiles[$group])) {
  170. self::$blacklistedFiles[$group][] = $filename;
  171. }
  172. }
  173. }
  174. /**
  175. * Removes a directory from the blacklist (recursively).
  176. *
  177. * @param string $directory
  178. * @param string $suffix
  179. * @param string $group
  180. * @access public
  181. * @static
  182. * @since Method available since Release 3.1.5
  183. */
  184. public static function removeDirectoryFromFilter($directory, $suffix = '.php', $group = 'DEFAULT')
  185. {
  186. if (file_exists($directory)) {
  187. foreach (self::getIterator($directory, $suffix) as $file) {
  188. self::removeFileFromFilter($file->getPathName(), $group);
  189. }
  190. }
  191. }
  192. /**
  193. * Removes a file from the filter (blacklist).
  194. *
  195. * @param string $filename
  196. * @param string $group
  197. * @access public
  198. * @static
  199. * @since Method available since Release 2.1.0
  200. */
  201. public static function removeFileFromFilter($filename, $group = 'DEFAULT')
  202. {
  203. if (file_exists($filename)) {
  204. if (isset(self::$blacklistedFiles[$group])) {
  205. $filename = realpath($filename);
  206. foreach (self::$blacklistedFiles[$group] as $key => $_filename) {
  207. if ($filename == $_filename) {
  208. unset(self::$blacklistedFiles[$group][$key]);
  209. }
  210. }
  211. }
  212. }
  213. }
  214. /**
  215. * Adds a directory to the whitelist (recursively).
  216. *
  217. * @param string $directory
  218. * @param string $suffix
  219. * @access public
  220. * @static
  221. * @since Method available since Release 3.1.5
  222. */
  223. public static function addDirectoryToWhitelist($directory, $suffix = '.php')
  224. {
  225. if (file_exists($directory)) {
  226. foreach (self::getIterator($directory, $suffix) as $file) {
  227. self::addFileToWhitelist($file->getPathName());
  228. }
  229. }
  230. }
  231. /**
  232. * Adds a new file to the whitelist.
  233. *
  234. * When the whitelist is empty (default), blacklisting is used.
  235. * When the whitelist is not empty, whitelisting is used.
  236. *
  237. * @param string $filename
  238. * @access public
  239. * @static
  240. * @since Method available since Release 3.1.0
  241. */
  242. public static function addFileToWhitelist($filename)
  243. {
  244. if (file_exists($filename)) {
  245. $filename = realpath($filename);
  246. if (!in_array($filename, self::$whitelistedFiles)) {
  247. self::$whitelistedFiles[] = $filename;
  248. }
  249. }
  250. }
  251. /**
  252. * Removes a directory from the whitelist (recursively).
  253. *
  254. * @param string $directory
  255. * @param string $suffix
  256. * @access public
  257. * @static
  258. * @since Method available since Release 3.1.5
  259. */
  260. public static function removeDirectoryFromWhitelist($directory, $suffix = '.php')
  261. {
  262. if (file_exists($directory)) {
  263. foreach (self::getIterator($directory, $suffix) as $file) {
  264. self::removeFileFromWhitelist($file->getPathName());
  265. }
  266. }
  267. }
  268. /**
  269. * Removes a file from the whitelist.
  270. *
  271. * @param string $filename
  272. * @access public
  273. * @static
  274. * @since Method available since Release 3.1.0
  275. */
  276. public static function removeFileFromWhitelist($filename)
  277. {
  278. if (file_exists($filename)) {
  279. $filename = realpath($filename);
  280. foreach (self::$whitelistedFiles as $key => $_filename) {
  281. if ($filename == $_filename) {
  282. unset(self::$whitelistedFiles[$key]);
  283. }
  284. }
  285. }
  286. }
  287. /**
  288. * Returns data about files within code coverage information, specifically
  289. * which ones will be filtered out and which ones may be whitelisted but not
  290. * touched by coverage.
  291. *
  292. * Returns a two-item array. The first item is an array indexed by filenames
  293. * with a boolean payload of whether they should be filtered out.
  294. *
  295. * The second item is an array of filenames which are
  296. * whitelisted but which are absent from the coverage information.
  297. *
  298. * @param array $codeCoverageInformation
  299. * @param boolean $filterTests
  300. * @return array
  301. * @access public
  302. * @static
  303. */
  304. public static function getFileCodeCoverageDisposition(array $codeCoverageInformation, $filterTests = TRUE)
  305. {
  306. if (!self::$filter) {
  307. return array(array(), array());
  308. }
  309. $isFilteredCache = array();
  310. $coveredFiles = array();
  311. foreach ($codeCoverageInformation as $k => $test) {
  312. foreach (array_keys($test['files']) as $file) {
  313. if (!isset($isFilteredCache[$file])) {
  314. $isFilteredCache[$file] = self::isFiltered(
  315. $file, $filterTests
  316. );
  317. }
  318. }
  319. }
  320. $coveredFiles = array_keys($isFilteredCache);
  321. $missedFiles = array_diff(self::$whitelistedFiles,$coveredFiles);
  322. $missedFiles = array_filter($missedFiles,'file_exists');
  323. return array($isFilteredCache,$missedFiles);
  324. }
  325. /**
  326. * @param array $codeCoverageInformation
  327. * @param boolean $addUncoveredFilesFromWhitelist
  328. * @return array
  329. * @access public
  330. * @static
  331. */
  332. public static function getFilteredCodeCoverage(array $codeCoverageInformation, $filterTests = TRUE)
  333. {
  334. if (self::$filter) {
  335. list($isFilteredCache, $missedFiles) = self::getFileCodeCoverageDisposition(
  336. $codeCoverageInformation, $filterTests
  337. );
  338. foreach ($codeCoverageInformation as $k => $test) {
  339. foreach (array_keys($test['files']) as $file) {
  340. if ($isFilteredCache[$file]) {
  341. unset($codeCoverageInformation[$k]['files'][$file]);
  342. }
  343. }
  344. }
  345. if (self::$addUncoveredFilesFromWhitelist) {
  346. foreach ($missedFiles as $missedFile) {
  347. xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
  348. include_once $missedFile;
  349. $coverage = xdebug_get_code_coverage();
  350. xdebug_stop_code_coverage();
  351. if (isset($coverage[$missedFile])) {
  352. foreach ($coverage[$missedFile] as $line => $flag) {
  353. if ($flag > 0) {
  354. $coverage[$missedFile][$line] = -1;
  355. }
  356. }
  357. $codeCoverageInformation[] = array(
  358. 'test' => NULL,
  359. 'files' => array(
  360. $missedFile => $coverage[$missedFile]
  361. )
  362. );
  363. }
  364. }
  365. }
  366. }
  367. return $codeCoverageInformation;
  368. }
  369. /**
  370. * Filters stack frames from PHPUnit classes.
  371. *
  372. * @param Exception $e
  373. * @param boolean $filterTests
  374. * @param boolean $asString
  375. * @return string
  376. * @access public
  377. * @static
  378. */
  379. public static function getFilteredStacktrace(Exception $e, $filterTests = TRUE, $asString = TRUE)
  380. {
  381. if ($asString === TRUE) {
  382. $filteredStacktrace = '';
  383. } else {
  384. $filteredStacktrace = array();
  385. }
  386. foreach ($e->getTrace() as $frame) {
  387. if (!self::$filter || (isset($frame['file']) && !self::isFiltered($frame['file'], $filterTests, TRUE))) {
  388. if ($asString === TRUE) {
  389. $filteredStacktrace .= sprintf(
  390. "%s:%s\n",
  391. $frame['file'],
  392. isset($frame['line']) ? $frame['line'] : '?'
  393. );
  394. } else {
  395. $filteredStacktrace[] = $frame;
  396. }
  397. }
  398. }
  399. return $filteredStacktrace;
  400. }
  401. /**
  402. * Activates or deactivates filtering.
  403. *
  404. * @param boolean $filter
  405. * @throws InvalidArgumentException
  406. * @access public
  407. * @static
  408. * @since Method available since Release 3.0.0
  409. */
  410. public static function setFilter($filter)
  411. {
  412. if (is_bool($filter)) {
  413. self::$filter = $filter;
  414. } else {
  415. throw new InvalidArgumentException;
  416. }
  417. }
  418. /**
  419. * Returns a PHPUnit_Util_FilterIterator that iterates
  420. * over all files in the given directory that have the
  421. * given suffix.
  422. *
  423. * @param string $directory
  424. * @param string $suffix
  425. * @return Iterator
  426. * @access protected
  427. * @static
  428. * @since Method available since Release 3.1.5
  429. */
  430. protected static function getIterator($directory, $suffix)
  431. {
  432. return new PHPUnit_Util_FilterIterator(
  433. new RecursiveIteratorIterator(
  434. new RecursiveDirectoryIterator($directory)
  435. ),
  436. $suffix
  437. );
  438. }
  439. /**
  440. * @param string $filename
  441. * @param boolean $filterTests
  442. * @param boolean $ignoreWhitelist
  443. * @return boolean
  444. * @access protected
  445. * @static
  446. * @since Method available since Release 2.1.3
  447. */
  448. protected static function isFiltered($filename, $filterTests = TRUE, $ignoreWhitelist = FALSE)
  449. {
  450. $filename = realpath($filename);
  451. // Use blacklist.
  452. if ($ignoreWhitelist || empty(self::$whitelistedFiles)) {
  453. if (DIRECTORY_SEPARATOR == '\\' &&
  454. !self::$blackListConverstionForWindowsDone) {
  455. $count = count(self::$blacklistedFiles['PEAR']);
  456. for ($i = 0; $i < $count; $i++) {
  457. self::$blacklistedFiles['PEAR'][$i] = str_replace(
  458. '/', '\\', self::$blacklistedFiles['PEAR'][$i]
  459. );
  460. }
  461. self::$blackListConverstionForWindowsDone = TRUE;
  462. }
  463. $blacklistedFiles = array_merge(
  464. self::$blacklistedFiles['DEFAULT'],
  465. self::$blacklistedFiles['PEAR']
  466. );
  467. if ($filterTests) {
  468. $blacklistedFiles = array_merge(
  469. $blacklistedFiles,
  470. self::$blacklistedFiles['TESTS']
  471. );
  472. }
  473. if (self::$filterPHPUnit) {
  474. $blacklistedFiles = array_merge(
  475. $blacklistedFiles,
  476. self::$blacklistedFiles['PHPUNIT']
  477. );
  478. }
  479. if (in_array($filename, $blacklistedFiles)) {
  480. return TRUE;
  481. }
  482. foreach ($blacklistedFiles as $filteredFile) {
  483. if (strpos($filename, $filteredFile) !== FALSE) {
  484. return TRUE;
  485. }
  486. }
  487. return FALSE;
  488. }
  489. // Use whitelist.
  490. else
  491. {
  492. if (in_array($filename, self::$whitelistedFiles)) {
  493. return FALSE;
  494. }
  495. return TRUE;
  496. }
  497. }
  498. }
  499. PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
  500. ?>