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