2008-04-23 18:25:03 +00:00
< ? php
2008-05-15 05:13:44 +00:00
/* SVN FILE: $Id$ */
2008-04-23 18:25:03 +00:00
/**
* A class to manage all aspects for Code Coverage Analysis
*
* This class
*
* PHP versions 4 and 5
*
* CakePHP ( tm ) Tests < https :// trac . cakephp . org / wiki / Developement / TestSuite >
* Copyright 2005 - 2008 , Cake Software Foundation , Inc .
* 1785 E . Sahara Avenue , Suite 490 - 204
* Las Vegas , Nevada 89104
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice .
*
* @ filesource
* @ copyright Copyright 2005 - 2008 , Cake Software Foundation , Inc .
* @ link https :// trac . cakephp . org / wiki / Developement / TestSuite CakePHP ( tm ) Tests
* @ package cake
* @ subpackage cake . cake . tests . lib
* @ since CakePHP ( tm ) v 1.2 . 0.4433
2008-05-15 05:13:44 +00:00
* @ version $Revision $
* @ modifiedby $LastChangedBy $
* @ lastmodified $Date $
2008-04-23 18:25:03 +00:00
* @ license http :// www . opensource . org / licenses / opengroup . php The Open Group Test Suite License
*/
App :: import ( 'Core' , 'Folder' );
/**
* Short description for class .
*
* @ package cake
* @ subpackage cake . cake . tests . lib
*/
class CodeCoverageManager {
/**
* Is this an app test case ?
*
* @ var string
*/
var $appTest = false ;
/**
* Is this an app test case ?
*
* @ var string
*/
var $pluginTest = false ;
2008-05-05 14:41:27 +00:00
/**
* Is this a grouptest ?
*
* @ var string
* @ access public
*/
var $groupTest = false ;
2008-04-23 18:25:03 +00:00
/**
* The test case file to analyze
*
* @ var string
*/
var $testCaseFile = '' ;
/**
* The currently used CakeTestReporter
*
* @ var string
*/
var $reporter = '' ;
2008-04-28 18:02:34 +00:00
/**
* undocumented variable
*
* @ var string
*/
var $numDiffContextLines = 7 ;
2008-04-23 18:25:03 +00:00
/**
* Returns a singleton instance
*
* @ return object
* @ access public
*/
function & getInstance () {
static $instance = array ();
if ( ! isset ( $instance [ 0 ]) || ! $instance [ 0 ]) {
$instance [ 0 ] =& new CodeCoverageManager ();
}
return $instance [ 0 ];
}
/**
* Starts a new Coverage Analyzation for a given test case file
* @ TODO : Works with $_GET now within the function body , which will make it hard when we do code coverage reports for CLI
*
2008-05-10 16:42:35 +00:00
* @ param string $testCaseFile
* @ param string $reporter
2008-04-23 18:25:03 +00:00
* @ return void
*/
function start ( $testCaseFile , & $reporter ) {
$manager =& CodeCoverageManager :: getInstance ();
$manager -> reporter = $reporter ;
2008-05-15 17:27:57 +00:00
$testCaseFile = str_replace ( DS . DS , DS , $testCaseFile );
2008-05-10 16:42:35 +00:00
$thisFile = str_replace ( '.php' , '.test.php' , basename ( __FILE__ ));
2008-05-15 17:27:57 +00:00
2008-04-23 18:25:03 +00:00
if ( strpos ( $testCaseFile , $thisFile ) !== false ) {
trigger_error ( 'Xdebug supports no parallel coverage analysis - so this is not possible.' , E_USER_ERROR );
}
if ( isset ( $_GET [ 'app' ])) {
$manager -> appTest = true ;
}
2008-05-15 17:27:57 +00:00
2008-05-05 14:41:27 +00:00
if ( isset ( $_GET [ 'group' ])) {
$manager -> groupTest = true ;
}
2008-05-15 17:27:57 +00:00
2008-04-23 18:25:03 +00:00
if ( isset ( $_GET [ 'plugin' ])) {
2008-04-29 21:03:51 +00:00
$manager -> pluginTest = Inflector :: underscore ( $_GET [ 'plugin' ]);
2008-04-23 18:25:03 +00:00
}
$manager -> testCaseFile = $testCaseFile ;
xdebug_start_code_coverage ( XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE );
}
/**
* Stops the current code coverage analyzation and dumps a nice report depending on the reporter that was passed to start ()
*
* @ return void
*/
function report ( $output = true ) {
$manager =& CodeCoverageManager :: getInstance ();
2008-05-05 14:41:27 +00:00
if ( ! $manager -> groupTest ) {
$testObjectFile = $manager -> __testObjectFileFromCaseFile ( $manager -> testCaseFile , $manager -> appTest );
2008-04-29 21:03:51 +00:00
2008-05-05 14:41:27 +00:00
if ( ! file_exists ( $testObjectFile )) {
2008-05-15 17:27:57 +00:00
trigger_error ( 'This test object file is invalid: ' . $testObjectFile );
2008-05-05 14:41:27 +00:00
return ;
}
$dump = xdebug_get_code_coverage ();
2008-05-10 17:29:28 +00:00
xdebug_stop_code_coverage ();
2008-05-05 14:41:27 +00:00
$coverageData = array ();
2008-05-15 17:27:57 +00:00
2008-05-05 14:41:27 +00:00
foreach ( $dump as $file => $data ) {
if ( $file == $testObjectFile ) {
$coverageData = $data ;
break ;
}
}
2008-05-10 16:42:35 +00:00
2008-05-05 14:41:27 +00:00
if ( empty ( $coverageData ) && $output ) {
echo 'The test object file is never loaded.' ;
2008-04-23 18:25:03 +00:00
}
2008-05-05 14:41:27 +00:00
$execCodeLines = $manager -> __getExecutableLines ( file_get_contents ( $testObjectFile ));
$result = '' ;
switch ( get_class ( $manager -> reporter )) {
case 'CakeHtmlReporter' :
$result = $manager -> reportCaseHtmlDiff ( @ file ( $testObjectFile ), $coverageData , $execCodeLines , $manager -> numDiffContextLines );
break ;
case 'CLIReporter' :
$result = $manager -> reportCaseCli ( @ file ( $testObjectFile ), $coverageData , $execCodeLines , $manager -> numDiffContextLines );
break ;
default :
trigger_error ( 'Currently only HTML and CLI reporting is supported for code coverage analysis.' );
break ;
}
} else {
$testObjectFiles = $manager -> __testObjectFilesFromGroupFile ( $manager -> testCaseFile , $manager -> appTest );
2008-04-23 18:25:03 +00:00
2008-05-05 14:41:27 +00:00
foreach ( $testObjectFiles as $file ) {
if ( ! file_exists ( $file )) {
2008-05-15 17:27:57 +00:00
trigger_error ( 'This test object file is invalid: ' . $file );
2008-05-05 14:41:27 +00:00
return ;
}
}
$dump = xdebug_get_code_coverage ();
2008-05-10 17:28:49 +00:00
xdebug_stop_code_coverage ();
2008-05-05 14:41:27 +00:00
$coverageData = array ();
foreach ( $dump as $file => $data ) {
if ( in_array ( $file , $testObjectFiles )) {
$coverageData [ $file ] = $data ;
}
}
if ( empty ( $coverageData ) && $output ) {
echo 'The test object files are never loaded.' ;
}
$execCodeLines = $manager -> __getExecutableLines ( $testObjectFiles );
$result = '' ;
switch ( get_class ( $manager -> reporter )) {
case 'CakeHtmlReporter' :
$result = $manager -> reportGroupHtml ( $testObjectFiles , $coverageData , $execCodeLines , $manager -> numDiffContextLines );
break ;
case 'CLIReporter' :
$result = $manager -> reportGroupCli ( $testObjectFiles , $coverageData , $execCodeLines , $manager -> numDiffContextLines );
break ;
default :
trigger_error ( 'Currently only HTML and CLI reporting is supported for code coverage analysis.' );
break ;
}
2008-04-23 18:25:03 +00:00
}
2008-05-05 14:41:27 +00:00
2008-04-28 18:02:34 +00:00
if ( $output ) {
echo $result ;
}
2008-04-23 18:25:03 +00:00
}
/**
* Html reporting
*
2008-05-10 16:42:35 +00:00
* @ param string $testObjectFile
* @ param string $coverageData
* @ param string $execCodeLines
* @ param string $output
2008-04-23 18:25:03 +00:00
* @ return void
*/
2008-05-05 14:41:27 +00:00
function reportCaseHtml ( $testObjectFile , $coverageData , $execCodeLines ) {
2008-04-28 18:02:34 +00:00
$manager = CodeCoverageManager :: getInstance ();
$lineCount = $coveredCount = 0 ;
$report = '' ;
foreach ( $testObjectFile as $num => $line ) {
$num ++ ;
$foundByManualFinder = array_key_exists ( $num , $execCodeLines ) && trim ( $execCodeLines [ $num ]) != '' ;
$foundByXdebug = array_key_exists ( $num , $coverageData ) && $coverageData [ $num ] !== - 2 ;
// xdebug does not find all executable lines (zend engine fault)
if ( $foundByManualFinder && $foundByXdebug ) {
$class = 'uncovered' ;
$lineCount ++ ;
if ( $coverageData [ $num ] > 0 ) {
$class = 'covered' ;
$coveredCount ++ ;
}
} else {
$class = 'ignored' ;
}
$report .= $manager -> __paintCodeline ( $class , $num , $line );;
}
return $manager -> __paintHeader ( $lineCount , $coveredCount , $report );
}
/**
* Diff reporting
*
2008-05-10 16:42:35 +00:00
* @ param string $testObjectFile
* @ param string $coverageData
* @ param string $execCodeLines
* @ param string $output
2008-04-28 18:02:34 +00:00
* @ return void
*/
2008-05-05 14:41:27 +00:00
function reportCaseHtmlDiff ( $testObjectFile , $coverageData , $execCodeLines , $numContextLines ) {
2008-04-28 18:02:34 +00:00
$manager = CodeCoverageManager :: getInstance ();
$total = count ( $testObjectFile );
$lines = array ();
for ( $i = 1 ; $i < $total + 1 ; $i ++ ) {
$foundByManualFinder = array_key_exists ( $i , $execCodeLines ) && trim ( $execCodeLines [ $i ]) != '' ;
$foundByXdebug = array_key_exists ( $i , $coverageData );
if ( ! $foundByManualFinder || ! $foundByXdebug || $coverageData [ $i ] === - 2 ) {
if ( array_key_exists ( $i , $lines )) {
2008-05-15 17:27:57 +00:00
$lines [ $i ] = 'ignored ' . $lines [ $i ];
2008-04-23 18:25:03 +00:00
} else {
2008-04-28 18:02:34 +00:00
$lines [ $i ] = 'ignored' ;
}
continue ;
}
if ( $coverageData [ $i ] !== - 1 ) {
if ( array_key_exists ( $i , $lines )) {
2008-05-15 17:27:57 +00:00
$lines [ $i ] = 'covered ' . $lines [ $i ];
2008-04-28 18:02:34 +00:00
} else {
$lines [ $i ] = 'covered' ;
}
continue ;
}
$lines [ $i ] = 'uncovered show' ;
$foundEndBlockInContextSearch = false ;
2008-05-15 17:27:57 +00:00
2008-04-28 18:02:34 +00:00
for ( $j = 1 ; $j <= $numContextLines ; $j ++ ) {
$key = $i - $j ;
if ( $key > 0 && array_key_exists ( $key , $lines )) {
if ( strpos ( $lines [ $key ], 'end' ) !== false ) {
$foundEndBlockInContextSearch = true ;
if ( $j < $numContextLines ) {
2008-05-10 16:42:35 +00:00
$lines [ $key ] = str_replace ( 'end' , '' , $lines [ $key - 1 ]);
2008-04-28 18:02:34 +00:00
}
}
2008-05-10 16:42:35 +00:00
2008-04-28 18:02:34 +00:00
if ( strpos ( $lines [ $key ], 'uncovered' ) === false ) {
if ( strpos ( $lines [ $key ], 'covered' ) !== false ) {
$lines [ $key ] .= ' show' ;
} else {
$lines [ $key ] = 'ignored show' ;
}
}
if ( $j == $numContextLines ) {
$lineBeforeIsEndBlock = strpos ( $lines [ $key - 1 ], 'end' ) !== false ;
$lineBeforeIsShown = strpos ( $lines [ $key - 1 ], 'show' ) !== false ;
$lineBeforeIsUncovered = strpos ( $lines [ $key - 1 ], 'uncovered' ) !== false ;
2008-05-10 16:42:35 +00:00
2008-04-28 18:02:34 +00:00
if ( ! $foundEndBlockInContextSearch && ! $lineBeforeIsUncovered && ( $lineBeforeIsEndBlock )) {
2008-05-10 16:42:35 +00:00
$lines [ $key - 1 ] = str_replace ( 'end' , '' , $lines [ $key - 1 ]);
2008-04-28 18:02:34 +00:00
}
if ( ! $lineBeforeIsShown && ! $lineBeforeIsUncovered ) {
$lines [ $key ] .= ' start' ;
}
}
}
$key = $i + $j ;
2008-05-15 17:27:57 +00:00
2008-04-28 18:02:34 +00:00
if ( $key < $total ) {
$lines [ $key ] = 'show' ;
2008-05-10 16:42:35 +00:00
2008-04-28 18:02:34 +00:00
if ( $j == $numContextLines ) {
$lines [ $key ] .= ' end' ;
}
2008-04-23 18:25:03 +00:00
}
}
2008-04-28 18:02:34 +00:00
}
// find the last "uncovered" or "show"n line and "end" its block
$lastShownLine = $manager -> __array_strpos ( $lines , 'show' , true );
2008-05-15 17:27:57 +00:00
2008-04-28 18:02:34 +00:00
if ( isset ( $lines [ $lastShownLine ])) {
$lines [ $lastShownLine ] .= ' end' ;
}
// give the first start line another class so we can control the top padding of the entire results
$firstShownLine = $manager -> __array_strpos ( $lines , 'show' );
if ( isset ( $lines [ $firstShownLine ])) {
$lines [ $firstShownLine ] .= ' realstart' ;
}
// get the output
$lineCount = $coveredCount = 0 ;
$report = '' ;
foreach ( $testObjectFile as $num => $line ) {
// start line count at 1
$num ++ ;
$class = $lines [ $num ];
2008-05-10 16:42:35 +00:00
2008-04-28 18:02:34 +00:00
if ( strpos ( $class , 'ignored' ) === false ) {
$lineCount ++ ;
2008-04-23 18:25:03 +00:00
2008-04-28 18:02:34 +00:00
if ( strpos ( $class , 'covered' ) !== false && strpos ( $class , 'uncovered' ) === false ) {
$coveredCount ++ ;
}
}
if ( strpos ( $class , 'show' ) !== false ) {
$report .= $manager -> __paintCodeline ( $class , $num , $line );
2008-04-23 18:25:03 +00:00
}
}
2008-04-28 18:02:34 +00:00
return $manager -> __paintHeader ( $lineCount , $coveredCount , $report );
2008-04-23 18:25:03 +00:00
}
2008-04-29 21:03:51 +00:00
/**
* CLI reporting
*
2008-05-10 16:42:35 +00:00
* @ param string $testObjectFile
* @ param string $coverageData
* @ param string $execCodeLines
* @ param string $output
2008-04-29 21:03:51 +00:00
* @ return void
*/
2008-05-05 14:41:27 +00:00
function reportCaseCli ( $testObjectFile , $coverageData , $execCodeLines ) {
2008-04-29 21:03:51 +00:00
$manager = CodeCoverageManager :: getInstance ();
$lineCount = $coveredCount = 0 ;
$report = '' ;
foreach ( $testObjectFile as $num => $line ) {
$num ++ ;
$foundByManualFinder = array_key_exists ( $num , $execCodeLines ) && trim ( $execCodeLines [ $num ]) != '' ;
$foundByXdebug = array_key_exists ( $num , $coverageData ) && $coverageData [ $num ] !== - 2 ;
if ( $foundByManualFinder && $foundByXdebug ) {
$lineCount ++ ;
if ( $coverageData [ $num ] > 0 ) {
$coveredCount ++ ;
}
}
}
return $manager -> __paintHeaderCli ( $lineCount , $coveredCount , $report );
}
2008-05-05 14:41:27 +00:00
/**
* Diff reporting
*
2008-05-10 16:42:35 +00:00
* @ param string $testObjectFile
* @ param string $coverageData
* @ param string $execCodeLines
* @ param string $output
2008-05-05 14:41:27 +00:00
* @ return void
*/
function reportGroupHtml ( $testObjectFiles , $coverageData , $execCodeLines , $numContextLines ) {
$manager = CodeCoverageManager :: getInstance ();
$report = '' ;
foreach ( $testObjectFiles as $testObjectFile ) {
$lineCount = $coveredCount = 0 ;
$objFilename = $testObjectFile ;
$testObjectFile = file ( $testObjectFile );
foreach ( $testObjectFile as $num => $line ) {
$num ++ ;
$foundByManualFinder = array_key_exists ( $num , $execCodeLines [ $objFilename ]) && trim ( $execCodeLines [ $objFilename ][ $num ]) != '' ;
$foundByXdebug = array_key_exists ( $num , $coverageData [ $objFilename ]) && $coverageData [ $objFilename ][ $num ] !== - 2 ;
if ( $foundByManualFinder && $foundByXdebug ) {
$class = 'uncovered' ;
$lineCount ++ ;
if ( $coverageData [ $objFilename ][ $num ] > 0 ) {
$class = 'covered' ;
$coveredCount ++ ;
}
} else {
$class = 'ignored' ;
}
}
$report .= $manager -> __paintGroupResultLine ( $objFilename , $lineCount , $coveredCount );
}
return $manager -> __paintGroupResultHeader ( $report );
}
/**
* CLI reporting
*
2008-05-10 16:42:35 +00:00
* @ param string $testObjectFile
* @ param string $coverageData
* @ param string $execCodeLines
* @ param string $output
2008-05-05 14:41:27 +00:00
* @ return void
*/
function reportGroupCli ( $testObjectFiles , $coverageData , $execCodeLines ) {
$manager = CodeCoverageManager :: getInstance ();
$report = '' ;
foreach ( $testObjectFiles as $testObjectFile ) {
$lineCount = $coveredCount = 0 ;
$objFilename = $testObjectFile ;
$testObjectFile = file ( $testObjectFile );
foreach ( $testObjectFile as $num => $line ) {
$num ++ ;
$foundByManualFinder = array_key_exists ( $num , $execCodeLines [ $objFilename ]) && trim ( $execCodeLines [ $objFilename ][ $num ]) != '' ;
$foundByXdebug = array_key_exists ( $num , $coverageData [ $objFilename ]) && $coverageData [ $objFilename ][ $num ] !== - 2 ;
if ( $foundByManualFinder && $foundByXdebug ) {
$lineCount ++ ;
if ( $coverageData [ $objFilename ][ $num ] > 0 ) {
$coveredCount ++ ;
}
}
}
$report .= $manager -> __paintGroupResultLineCli ( $objFilename , $lineCount , $coveredCount );
}
return $report ;
}
2008-04-23 18:25:03 +00:00
/**
* Returns the name of the test object file based on a given test case file name
*
2008-05-10 16:42:35 +00:00
* @ param string $file
* @ param string $isApp
2008-04-28 18:02:34 +00:00
* @ return string name of the test object file
* @ access private
2008-04-23 18:25:03 +00:00
*/
2008-04-28 18:02:34 +00:00
function __testObjectFileFromCaseFile ( $file , $isApp = true ) {
2008-04-29 18:24:52 +00:00
$manager = CodeCoverageManager :: getInstance ();
2008-05-05 14:41:27 +00:00
$path = $manager -> __getTestFilesPath ( $isApp );
2008-04-23 18:25:03 +00:00
$folderPrefixMap = array (
'behaviors' => 'models' ,
'components' => 'controllers' ,
'helpers' => 'views'
);
2008-05-15 17:27:57 +00:00
2008-04-23 18:25:03 +00:00
foreach ( $folderPrefixMap as $dir => $prefix ) {
if ( strpos ( $file , $dir ) === 0 ) {
2008-05-15 17:27:57 +00:00
$path .= $prefix . DS ;
2008-04-23 18:25:03 +00:00
break ;
}
}
$testManager =& new TestManager ();
2008-05-10 17:01:51 +00:00
$testFile = str_replace ( array ( '/' , $testManager -> _testExtension ), array ( DS , '.php' ), $file );
2008-05-10 16:42:35 +00:00
2008-05-10 17:01:51 +00:00
$folder =& new Folder ();
2008-05-15 17:27:57 +00:00
$folder -> cd ( ROOT . DS . CAKE_TESTS_LIB );
2008-04-23 18:25:03 +00:00
$contents = $folder -> ls ();
if ( in_array ( basename ( $testFile ), $contents [ 1 ])) {
$testFile = basename ( $testFile );
2008-05-15 17:27:57 +00:00
$path = ROOT . DS . CAKE_TESTS_LIB ;
2008-04-23 18:25:03 +00:00
}
$path .= $testFile ;
2008-05-14 15:00:28 +00:00
$realpath = realpath ( $path );
2008-05-15 17:27:57 +00:00
2008-05-14 15:00:28 +00:00
if ( $realpath ) {
return $realpath ;
}
2008-04-23 18:25:03 +00:00
return $path ;
}
2008-05-05 14:41:27 +00:00
/**
* Returns an array of names of the test object files based on a given test group file name
*
2008-05-10 16:42:35 +00:00
* @ param array $files
* @ param string $isApp
2008-05-05 14:41:27 +00:00
* @ return array names of the test object files
* @ access private
*/
function __testObjectFilesFromGroupFile ( $groupFile , $isApp = true ) {
$manager = CodeCoverageManager :: getInstance ();
$testManager =& new TestManager ();
2008-05-10 16:42:35 +00:00
2008-05-15 17:27:57 +00:00
$path = TESTS . 'groups' ;
2008-05-05 14:41:27 +00:00
if ( ! $isApp ) {
2008-05-15 17:27:57 +00:00
$path = ROOT . DS . 'cake' . DS . 'tests' . DS . 'groups' ;
2008-05-05 14:41:27 +00:00
}
2008-05-15 17:27:57 +00:00
2008-05-05 14:41:27 +00:00
if ( !! $manager -> pluginTest ) {
2008-05-15 17:27:57 +00:00
$path = APP . 'plugins' . DS . $manager -> pluginTest . DS . 'tests' . DS . 'groups' ;
2008-05-05 14:41:27 +00:00
}
2008-05-15 17:27:57 +00:00
$path .= DS . $groupFile . $testManager -> _groupExtension ;
2008-05-05 14:41:27 +00:00
if ( ! file_exists ( $path )) {
trigger_error ( 'This group file does not exist!' );
return array ();
}
2008-05-15 17:27:57 +00:00
$result = array ();
2008-05-05 14:41:27 +00:00
$groupContent = file_get_contents ( $path );
$ds = '\s*\.\s*DS\s*\.\s*' ;
2008-05-15 17:27:57 +00:00
$pluginTest = 'APP\.\'plugins\'' . $ds . '\'' . $manager -> pluginTest . '\'' . $ds . '\'tests\'' . $ds . '\'cases\'' ;
$pattern = '/\s*TestManager::addTestFile\(\s*\$this,\s*(' . $pluginTest . '|APP_TEST_CASES|CORE_TEST_CASES)' . $ds . '(.*?)\)/i' ;
2008-05-05 14:41:27 +00:00
preg_match_all ( $pattern , $groupContent , $matches );
foreach ( $matches [ 2 ] as $file ) {
$patterns = array (
'/\s*\.\s*DS\s*\.\s*/' ,
'/\s*APP_TEST_CASES\s*/' ,
'/\s*CORE_TEST_CASES\s*/' ,
);
$replacements = array ( DS , '' , '' );
$file = preg_replace ( $patterns , $replacements , $file );
2008-05-10 16:42:35 +00:00
$file = str_replace ( " ' " , '' , $file );
2008-05-15 17:27:57 +00:00
$result [] = $manager -> __testObjectFileFromCaseFile ( $file , $isApp ) . '.php' ;
2008-05-05 14:41:27 +00:00
}
return $result ;
}
2008-04-23 18:25:03 +00:00
/**
2008-04-28 18:02:34 +00:00
* Parses a given code string into an array of lines and replaces some non - executable code lines with the needed
2008-04-23 18:25:03 +00:00
* amount of new lines in order for the code line numbers to stay in sync
*
2008-05-10 16:42:35 +00:00
* @ param string $content
2008-04-23 18:25:03 +00:00
* @ return array array of lines
2008-04-28 18:02:34 +00:00
* @ access private
2008-04-23 18:25:03 +00:00
*/
2008-04-28 18:02:34 +00:00
function __getExecutableLines ( $content ) {
2008-05-05 14:41:27 +00:00
if ( is_array ( $content )) {
$manager = CodeCoverageManager :: getInstance ();
$result = array ();
foreach ( $content as $file ) {
$result [ $file ] = $manager -> __getExecutableLines ( file_get_contents ( $file ));
}
return $result ;
}
2008-04-23 18:25:03 +00:00
$content = h ( $content );
// arrays are 0-indexed, but we want 1-indexed stuff now as we are talking code lines mind you (**)
2008-05-15 17:27:57 +00:00
$content = " \n " . $content ;
2008-04-28 18:02:34 +00:00
// // strip unwanted lines
$content = preg_replace_callback ( " /(@codeCoverageIgnoreStart.*?@codeCoverageIgnoreEnd)/is " , array ( 'CodeCoverageManager' , '__replaceWithNewlines' ), $content );
2008-04-23 18:25:03 +00:00
// strip php | ?\> tag only lines
2008-04-28 18:02:34 +00:00
$content = preg_replace ( '/[ |\t]*[<\?php|\?>]+[ |\t]*/' , '' , $content );
2008-04-23 18:25:03 +00:00
2008-04-28 18:02:34 +00:00
// strip lines that contain only braces and parenthesis
2008-04-23 18:25:03 +00:00
$content = preg_replace ( '/[ |\t]*[{|}|\(|\)]+[ |\t]*/' , '' , $content );
2008-05-10 16:42:35 +00:00
$result = explode ( " \n " , $content );
2008-04-23 18:25:03 +00:00
// unset the zero line again to get the original line numbers, but starting at 1, see (**)
unset ( $result [ 0 ]);
return $result ;
}
/**
* Replaces a given arg with the number of newlines in it
*
2008-04-28 18:02:34 +00:00
* @ return string the number of newlines in a given arg
* @ access private
2008-04-23 18:25:03 +00:00
*/
2008-04-28 18:02:34 +00:00
function __replaceWithNewlines () {
2008-04-23 18:25:03 +00:00
$args = func_get_args ();
$numLineBreaks = count ( explode ( " \n " , $args [ 0 ][ 0 ]));
2008-05-15 17:27:57 +00:00
return str_pad ( '' , $numLineBreaks - 1 , " \n " );
2008-04-23 18:25:03 +00:00
}
2008-04-28 18:02:34 +00:00
/**
* Paints the headline for code coverage analysis
*
2008-05-10 16:42:35 +00:00
* @ param string $codeCoverage
* @ param string $report
2008-04-28 18:02:34 +00:00
* @ return void
* @ access private
*/
function __paintHeader ( $lineCount , $coveredCount , $report ) {
$manager =& CodeCoverageManager :: getInstance ();
$codeCoverage = $manager -> __calcCoverage ( $lineCount , $coveredCount );
2008-05-15 17:27:57 +00:00
return $report = '<h2>Code Coverage: ' . $codeCoverage . ' %</ h2 >
< div class = " code-coverage-results " >< pre > ' . $report . ' </ pre ></ div > ' ;
2008-04-28 18:02:34 +00:00
}
2008-05-05 14:41:27 +00:00
/**
* Displays a notification concerning group test results
*
* @ return void
* @ access public
*/
function __paintGroupResultHeader ( $report ) {
2008-05-15 17:27:57 +00:00
return '<div class="code-coverage-results"><p class="note">Please keep in mind that the coverage can vary a little bit depending on how much the different tests in the group interfere. If for example, TEST A calls a line from TEST OBJECT B, the coverage for TEST OBJECT B will be a little greater than if you were running the corresponding test case for TEST OBJECT B alone.</p><pre>' . $report . '</pre></div>' ;
2008-05-05 14:41:27 +00:00
}
/**
* Paints the headline for code coverage analysis
*
2008-05-10 16:42:35 +00:00
* @ param string $codeCoverage
* @ param string $report
2008-05-05 14:41:27 +00:00
* @ return void
* @ access private
*/
function __paintGroupResultLine ( $file , $lineCount , $coveredCount ) {
$manager =& CodeCoverageManager :: getInstance ();
$codeCoverage = $manager -> __calcCoverage ( $lineCount , $coveredCount );
$class = 'result-bad' ;
2008-05-15 17:27:57 +00:00
2008-05-05 14:41:27 +00:00
if ( $codeCoverage > 50 ) {
$class = 'result-ok' ;
}
if ( $codeCoverage > 80 ) {
$class = 'result-good' ;
}
2008-05-15 17:27:57 +00:00
return '<p>Code Coverage for ' . $file . ': <span class="' . $class . '">' . $codeCoverage . '%</span></p>' ;
2008-05-05 14:41:27 +00:00
}
/**
* Paints the headline for code coverage analysis
*
2008-05-10 16:42:35 +00:00
* @ param string $codeCoverage
* @ param string $report
2008-05-05 14:41:27 +00:00
* @ return void
* @ access private
*/
function __paintGroupResultLineCli ( $file , $lineCount , $coveredCount ) {
$manager =& CodeCoverageManager :: getInstance ();
$codeCoverage = $manager -> __calcCoverage ( $lineCount , $coveredCount );
$class = 'bad' ;
2008-05-15 17:27:57 +00:00
2008-05-05 14:41:27 +00:00
if ( $codeCoverage > 50 ) {
$class = 'ok' ;
}
if ( $codeCoverage > 80 ) {
$class = 'good' ;
}
2008-05-15 17:27:57 +00:00
return " \n " . 'Code Coverage for ' . $file . ': ' . $codeCoverage . '% (' . $class . ')' . " \n " ;
2008-05-05 14:41:27 +00:00
}
2008-04-29 21:03:51 +00:00
/**
* Paints the headline for code coverage analysis in the CLI
*
2008-05-10 16:42:35 +00:00
* @ param string $codeCoverage
* @ param string $report
2008-04-29 21:03:51 +00:00
* @ return void
* @ access private
*/
function __paintHeaderCli ( $lineCount , $coveredCount , $report ) {
$manager =& CodeCoverageManager :: getInstance ();
$codeCoverage = $manager -> __calcCoverage ( $lineCount , $coveredCount );
2008-05-15 17:27:57 +00:00
return $report = 'Code Coverage: ' . $codeCoverage . '%' ;
2008-04-29 21:03:51 +00:00
}
2008-04-28 18:02:34 +00:00
/**
* Paints a code line for html output
*
* @ package default
* @ access private
*/
function __paintCodeline ( $class , $num , $line ) {
2008-04-30 14:08:29 +00:00
$line = h ( $line );
2008-05-15 17:27:57 +00:00
2008-04-30 14:08:29 +00:00
if ( trim ( $line ) == '' ) {
$line = ' ' ; // Win IE fix
}
2008-05-15 17:27:57 +00:00
return '<div class="code-line ' . trim ( $class ) . '"><span class="line-num">' . $num . '</span><span class="content">' . $line . '</span></div>' ;
2008-04-28 18:02:34 +00:00
}
/**
* Calculates the coverage percentage based on a line count and a covered line count
*
2008-05-10 16:42:35 +00:00
* @ param string $lineCount
* @ param string $coveredCount
2008-04-28 18:02:34 +00:00
* @ return void
* @ access private
*/
function __calcCoverage ( $lineCount , $coveredCount ) {
if ( $coveredCount > $lineCount ) {
trigger_error ( 'Sorry, you cannot have more covered lines than total lines!' );
}
return ( $lineCount != 0 )
2008-05-15 17:27:57 +00:00
? round ( 100 * $coveredCount / $lineCount , 2 )
2008-04-28 18:02:34 +00:00
: '0.00' ;
}
2008-05-05 14:41:27 +00:00
/**
* Gets us the base path to look for the test files
*
2008-05-10 16:42:35 +00:00
* @ param string $isApp
2008-05-05 14:41:27 +00:00
* @ return void
* @ access public
*/
function __getTestFilesPath ( $isApp = true ) {
$manager = CodeCoverageManager :: getInstance ();
2008-05-15 17:27:57 +00:00
$path = ROOT . DS ;
2008-05-05 14:41:27 +00:00
if ( $isApp ) {
2008-05-15 17:27:57 +00:00
$path .= APP_DIR . DS ;
2008-05-05 14:41:27 +00:00
} elseif ( !! $manager -> pluginTest ) {
2008-05-15 17:27:57 +00:00
$path .= APP_DIR . DS . 'plugins' . DS . $manager -> pluginTest . DS ;
2008-05-05 14:41:27 +00:00
} else {
2008-05-15 17:27:57 +00:00
$path = TEST_CAKE_CORE_INCLUDE_PATH ;
2008-05-05 14:41:27 +00:00
}
return $path ;
}
2008-04-28 18:02:34 +00:00
/**
* Finds the last element of an array that contains $needle in a strpos computation
*
2008-05-10 16:42:35 +00:00
* @ param array $arr
* @ param string $needle
2008-04-28 18:02:34 +00:00
* @ return void
* @ access private
*/
function __array_strpos ( $arr , $needle , $reverse = false ) {
if ( ! is_array ( $arr ) || empty ( $arr )) {
return false ;
}
if ( $reverse ) {
$arr = array_reverse ( $arr , true );
}
2008-05-15 17:27:57 +00:00
2008-04-28 18:02:34 +00:00
foreach ( $arr as $key => $val ) {
if ( strpos ( $val , $needle ) !== false ) {
return $key ;
}
}
return false ;
}
2008-04-23 18:25:03 +00:00
}
2008-05-14 15:00:28 +00:00
?>