PageRenderTime 14ms CodeModel.GetById 1ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/php/PHPUnit/Util/Filter.php

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