diff --git a/3rdparty/simpletest/extensions/coverage/autocoverage.php b/3rdparty/simpletest/extensions/coverage/autocoverage.php new file mode 100644 index 0000000000..9fc961bf43 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/autocoverage.php @@ -0,0 +1,29 @@ +startCoverage(); + register_shutdown_function("stop_coverage"); +} + +function stop_coverage() { + # hack until i can think of a way to run tests first and w/o exiting + $autorun = function_exists("run_local_tests"); + if ($autorun) { + $result = run_local_tests(); + } + CodeCoverage::getInstance()->stopCoverage(); + if ($autorun) { + exit($result ? 0 : 1); + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/bin/php-coverage-close.php b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-close.php new file mode 100755 index 0000000000..9a5a52ba13 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-close.php @@ -0,0 +1,14 @@ +readSettings(); +$cc->writeUntouched(); +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/bin/php-coverage-open.php b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-open.php new file mode 100755 index 0000000000..c04e1fb512 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-open.php @@ -0,0 +1,31 @@ + these files should be included coverage report +# --exclude= these files should not be included in coverage report +# --maxdepth=2 when considering which file were not touched, scan directories +# +# Example: +# php-coverage-open.php --include='.*\.php$' --include='.*\.inc$' --exclude='.*/tests/.*' +/**#@+ + * include coverage files + */ +require_once(dirname(__FILE__) . '/../coverage_utils.php'); +CoverageUtils::requireSqlite(); +require_once(dirname(__FILE__) . '/../coverage.php'); +/**#@-*/ +$cc = new CodeCoverage(); +$cc->log = 'coverage.sqlite'; +$args = CoverageUtils::parseArguments($_SERVER['argv'], TRUE); +$cc->includes = CoverageUtils::issetOr($args['include[]'], array('.*\.php$')); +$cc->excludes = CoverageUtils::issetOr($args['exclude[]']); +$cc->maxDirectoryDepth = (int)CoverageUtils::issetOr($args['maxdepth'], '1'); +$cc->resetLog(); +$cc->writeSettings(); +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/bin/php-coverage-report.php b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-report.php new file mode 100755 index 0000000000..d61c822d99 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-report.php @@ -0,0 +1,29 @@ +readSettings(); +$handler = new CoverageDataHandler($cc->log); +$report = new CoverageReporter(); +$args = CoverageUtils::parseArguments($_SERVER['argv']); +$report->reportDir = CoverageUtils::issetOr($args['reportDir'], 'coverage-report'); +$report->title = CoverageUtils::issetOr($args['title'], "Simpletest Coverage"); +$report->coverage = $handler->read(); +$report->untouched = $handler->readUntouchedFiles(); +$report->generate(); +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/coverage.php b/3rdparty/simpletest/extensions/coverage/coverage.php new file mode 100644 index 0000000000..44e5b679b8 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/coverage.php @@ -0,0 +1,196 @@ +getTouchedFiles()); + $untouched = array(); + $this->getUntouchedFiles($untouched, $touched, '.', '.'); + $this->includeUntouchedFiles($untouched); + } + + function &getTouchedFiles() { + $handler = new CoverageDataHandler($this->log); + $touched = $handler->getFilenames(); + return $touched; + } + + function includeUntouchedFiles($untouched) { + $handler = new CoverageDataHandler($this->log); + foreach ($untouched as $file) { + $handler->writeUntouchedFile($file); + } + } + + function getUntouchedFiles(&$untouched, $touched, $parentPath, $rootPath, $directoryDepth = 1) { + $parent = opendir($parentPath); + while ($file = readdir($parent)) { + $path = "$parentPath/$file"; + if (is_dir($path)) { + if ($file != '.' && $file != '..') { + if ($this->isDirectoryIncluded($path, $directoryDepth)) { + $this->getUntouchedFiles($untouched, $touched, $path, $rootPath, $directoryDepth + 1); + } + } + } + else if ($this->isFileIncluded($path)) { + $relativePath = CoverageDataHandler::ltrim($rootPath .'/', $path); + if (!array_key_exists($relativePath, $touched)) { + $untouched[] = $relativePath; + } + } + } + closedir($parent); + } + + function resetLog() { + error_log('reseting log'); + $new_file = fopen($this->log, "w"); + if (!$new_file) { + throw new Exception("Could not create ". $this->log); + } + fclose($new_file); + if (!chmod($this->log, 0666)) { + throw new Exception("Could not change ownership on file ". $this->log); + } + $handler = new CoverageDataHandler($this->log); + $handler->createSchema(); + } + + function startCoverage() { + $this->root = getcwd(); + if(!extension_loaded("xdebug")) { + throw new Exception("Could not load xdebug extension"); + }; + xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); + } + + function stopCoverage() { + $cov = xdebug_get_code_coverage(); + $this->filter($cov); + $data = new CoverageDataHandler($this->log); + chdir($this->root); + $data->write($cov); + unset($data); // release sqlite connection + xdebug_stop_code_coverage(); + // make sure we wind up on same current working directory, otherwise + // coverage handler writer doesn't know what directory to chop off + chdir($this->root); + } + + function readSettings() { + if (file_exists($this->settingsFile)) { + $this->setSettings(file_get_contents($this->settingsFile)); + } else { + error_log("could not find file ". $this->settingsFile); + } + } + + function writeSettings() { + file_put_contents($this->settingsFile, $this->getSettings()); + } + + function getSettings() { + $data = array( + 'log' => realpath($this->log), + 'includes' => $this->includes, + 'excludes' => $this->excludes); + return serialize($data); + } + + function setSettings($settings) { + $data = unserialize($settings); + $this->log = $data['log']; + $this->includes = $data['includes']; + $this->excludes = $data['excludes']; + } + + function filter(&$coverage) { + foreach ($coverage as $file => $line) { + if (!$this->isFileIncluded($file)) { + unset($coverage[$file]); + } + } + } + + function isFileIncluded($file) { + if (!empty($this->excludes)) { + foreach ($this->excludes as $path) { + if (preg_match('|' . $path . '|', $file)) { + return False; + } + } + } + + if (!empty($this->includes)) { + foreach ($this->includes as $path) { + if (preg_match('|' . $path . '|', $file)) { + return True; + } + } + return False; + } + + return True; + } + + function isDirectoryIncluded($dir, $directoryDepth) { + if ($directoryDepth >= $this->maxDirectoryDepth) { + return false; + } + if (isset($this->excludes)) { + foreach ($this->excludes as $path) { + if (preg_match('|' . $path . '|', $dir)) { + return False; + } + } + } + + return True; + } + + static function isCoverageOn() { + $coverage = self::getInstance(); + $coverage->readSettings(); + if (empty($coverage->log) || !file_exists($coverage->log)) { + trigger_error('No coverage log'); + return False; + } + return True; + } + + static function getInstance() { + if (self::$instance == NULL) { + self::$instance = new CodeCoverage(); + self::$instance->readSettings(); + } + return self::$instance; + } +} +?> diff --git a/3rdparty/simpletest/extensions/coverage/coverage_calculator.php b/3rdparty/simpletest/extensions/coverage/coverage_calculator.php new file mode 100644 index 0000000000..f1aa57bbab --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/coverage_calculator.php @@ -0,0 +1,98 @@ +lineCoverageCodeToStyleClass($coverage, $i); + $lines[$i] = array('lineCoverage' => $lineCoverage, 'code' => $line); + } + + fclose($hnd); + + $var = compact('file', 'lines', 'coverage'); + return $var; + } + + function lineCoverageCodeToStyleClass($coverage, $line) { + if (!array_key_exists($line, $coverage)) { + return "comment"; + } + $code = $coverage[$line]; + if (empty($code)) { + return "comment"; + } + switch ($code) { + case -1: + return "missed"; + case -2: + return "dead"; + } + + return "covered"; + } + + function totalLoc($total, $coverage) { + return $total + sizeof($coverage); + } + + function lineCoverage($total, $line) { + # NOTE: counting dead code as covered, as it's almost always an executable line + # strange artifact of xdebug or underlying system + return $total + ($line > 0 || $line == -2 ? 1 : 0); + } + + function totalCoverage($total, $coverage) { + return $total + array_reduce($coverage, array(&$this, "lineCoverage")); + } + + static function reportFilename($filename) { + return preg_replace('|[/\\\\]|', '_', $filename) . '.html'; + } + + function percentCoverageByFile($coverage, $file, &$results) { + $byFileReport = self::reportFilename($file); + + $loc = sizeof($coverage); + if ($loc == 0) + return 0; + $lineCoverage = array_reduce($coverage, array(&$this, "lineCoverage")); + $percentage = 100 * ($lineCoverage / $loc); + $results[0][$file] = array('byFileReport' => $byFileReport, 'percentage' => $percentage); + } + + function variables($coverage, $untouched) { + $coverageByFile = array(); + array_walk($coverage, array(&$this, "percentCoverageByFile"), array(&$coverageByFile)); + + $totalLoc = array_reduce($coverage, array(&$this, "totalLoc")); + + if ($totalLoc > 0) { + $totalLinesOfCoverage = array_reduce($coverage, array(&$this, "totalCoverage")); + $totalPercentCoverage = 100 * ($totalLinesOfCoverage / $totalLoc); + } + + $untouchedPercentageDenominator = sizeof($coverage) + sizeof($untouched); + if ($untouchedPercentageDenominator > 0) { + $filesTouchedPercentage = 100 * sizeof($coverage) / $untouchedPercentageDenominator; + } + + $var = compact('coverageByFile', 'totalPercentCoverage', 'totalLoc', 'totalLinesOfCoverage', 'filesTouchedPercentage'); + $var['untouched'] = $untouched; + return $var; + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/coverage_data_handler.php b/3rdparty/simpletest/extensions/coverage/coverage_data_handler.php new file mode 100644 index 0000000000..bbf81106fc --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/coverage_data_handler.php @@ -0,0 +1,125 @@ +filename = $filename; + $this->db = new SQLiteDatabase($filename); + if (empty($this->db)) { + throw new Exception("Could not create sqlite db ". $filename); + } + } + + function createSchema() { + $this->db->queryExec("create table untouched (filename text)"); + $this->db->queryExec("create table coverage (name text, coverage text)"); + } + + function &getFilenames() { + $filenames = array(); + $cursor = $this->db->unbufferedQuery("select distinct name from coverage"); + while ($row = $cursor->fetch()) { + $filenames[] = $row[0]; + } + + return $filenames; + } + + function write($coverage) { + foreach ($coverage as $file => $lines) { + $coverageStr = serialize($lines); + $relativeFilename = self::ltrim(getcwd() . '/', $file); + $sql = "insert into coverage (name, coverage) values ('$relativeFilename', '$coverageStr')"; + # if this fails, check you have write permission + $this->db->queryExec($sql); + } + } + + function read() { + $coverage = array_flip($this->getFilenames()); + foreach($coverage as $file => $garbage) { + $coverage[$file] = $this->readFile($file); + } + return $coverage; + } + + function &readFile($file) { + $sql = "select coverage from coverage where name = '$file'"; + $aggregate = array(); + $result = $this->db->query($sql); + while ($result->valid()) { + $row = $result->current(); + $this->aggregateCoverage($aggregate, unserialize($row[0])); + $result->next(); + } + + return $aggregate; + } + + function aggregateCoverage(&$total, $next) { + foreach ($next as $lineno => $code) { + if (!isset($total[$lineno])) { + $total[$lineno] = $code; + } else { + $total[$lineno] = $this->aggregateCoverageCode($total[$lineno], $code); + } + } + } + + function aggregateCoverageCode($code1, $code2) { + switch($code1) { + case -2: return -2; + case -1: return $code2; + default: + switch ($code2) { + case -2: return -2; + case -1: return $code1; + } + } + return $code1 + $code2; + } + + static function ltrim($cruft, $pristine) { + if(stripos($pristine, $cruft) === 0) { + return substr($pristine, strlen($cruft)); + } + return $pristine; + } + + function writeUntouchedFile($file) { + $relativeFile = CoverageDataHandler::ltrim('./', $file); + $sql = "insert into untouched values ('$relativeFile')"; + $this->db->queryExec($sql); + } + + function &readUntouchedFiles() { + $untouched = array(); + $result = $this->db->query("select filename from untouched order by filename"); + while ($result->valid()) { + $row = $result->current(); + $untouched[] = $row[0]; + $result->next(); + } + + return $untouched; + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/coverage_reporter.php b/3rdparty/simpletest/extensions/coverage/coverage_reporter.php new file mode 100644 index 0000000000..ba4e7161c2 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/coverage_reporter.php @@ -0,0 +1,68 @@ +writer = new SimpleCoverageWriter(); + $this->calculator = new CoverageCalculator(); + } + + function generateSummaryReport($out) { + $variables = $this->calculator->variables($this->coverage, $this->untouched); + $variables['title'] = $this->title; + $report = $this->writer->writeSummary($out, $variables); + fwrite($out, $report); + } + + function generate() { + CoverageUtils::mkdir($this->reportDir); + + $index = $this->reportDir .'/index.html'; + $hnd = fopen($index, 'w'); + $this->generateSummaryReport($hnd); + fclose($hnd); + + foreach ($this->coverage as $file => $cov) { + $byFile = $this->reportDir .'/'. self::reportFilename($file); + $byFileHnd = fopen($byFile, 'w'); + $this->generateCoverageByFile($byFileHnd, $file, $cov); + fclose($byFileHnd); + } + + echo "generated report $index\n"; + } + + function generateCoverageByFile($out, $file, $cov) { + $variables = $this->calculator->coverageByFileVariables($file, $cov); + $variables['title'] = $this->title .' - '. $file; + $this->writer->writeByFile($out, $variables); + } + + static function reportFilename($filename) { + return preg_replace('|[/\\\\]|', '_', $filename) . '.html'; + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/coverage_utils.php b/3rdparty/simpletest/extensions/coverage/coverage_utils.php new file mode 100644 index 0000000000..d2c3a635f4 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/coverage_utils.php @@ -0,0 +1,114 @@ + \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/coverage_writer.php b/3rdparty/simpletest/extensions/coverage/coverage_writer.php new file mode 100644 index 0000000000..0a8519cb50 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/coverage_writer.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/simple_coverage_writer.php b/3rdparty/simpletest/extensions/coverage/simple_coverage_writer.php new file mode 100644 index 0000000000..7eb73fc8ab --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/simple_coverage_writer.php @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/templates/file.php b/3rdparty/simpletest/extensions/coverage/templates/file.php new file mode 100644 index 0000000000..70f6903068 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/templates/file.php @@ -0,0 +1,60 @@ + + +<?php echo $title ?> + + + +

+ + + $line) { ?> + + + + + + +
+

Legend

+
+
Missed
+
lines code that were not excersized during program execution.
+
Covered
+
lines code were excersized during program execution.
+
Comment/non executable
+
Comment or non-executable line of code.
+
Dead
+
lines of code that according to xdebug could not be executed. This is counted as coverage code because + in almost all cases it is code that runnable.
+
+ + diff --git a/3rdparty/simpletest/extensions/coverage/templates/index.php b/3rdparty/simpletest/extensions/coverage/templates/index.php new file mode 100644 index 0000000000..e4374e2380 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/templates/index.php @@ -0,0 +1,106 @@ + + +<?php echo $title ?> + + + +

+ + + + + + + + + + + + + + + + +
Summary
Total Coverage (?) :%
Total Files Covered (?) :%
Report Generation Date :
+ + + + + + + + + + $coverage) { ?> + + + + + + +
Coverage (?)
FileCoverage
%
+ + + + $file) { ?> + + + + + +
Files Not Covered (?)
+ +

Glossary

+
+
Total Coverage
+
Ratio of all the lines of executable code that were executed to the + lines of code that were not executed. This does not include the files + that were not covered at all.
+
Total Files Covered
+
This is the ratio of the number of files tested, to the number of + files not tested at all.
+
Coverage
+
These files were parsed and loaded by the php interpreter while + running the tests. Percentage is determined by the ratio of number of + lines of code executed to the number of possible executable lines of + code. "dead" lines of code, or code that could not be executed + according to xdebug, are counted as covered because in almost all cases + it is the end of a logical loop.
+
Files Not Covered
+
These files were not loaded by the php interpreter at anytime + during a unit test. You could consider these files having 0% coverage, + but because it is difficult to determine the total coverage unless you + could count the lines for executable code, this is not reflected in the + Total Coverage calculation.
+
+ +

Code coverage generated by SimpleTest

+ + + diff --git a/3rdparty/simpletest/extensions/coverage/test/coverage_calculator_test.php b/3rdparty/simpletest/extensions/coverage/test/coverage_calculator_test.php new file mode 100644 index 0000000000..64bd8d463f --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/test/coverage_calculator_test.php @@ -0,0 +1,65 @@ +skipIf( + !file_exists('DB/sqlite.php'), + 'The Coverage extension needs to have PEAR installed'); + } + + function setUp() { + require_once dirname(__FILE__) .'/../coverage_calculator.php'; + $this->calc = new CoverageCalculator(); + } + + function testVariables() { + $coverage = array('file' => array(1,1,1,1)); + $untouched = array('missed-file'); + $variables = $this->calc->variables($coverage, $untouched); + $this->assertEqual(4, $variables['totalLoc']); + $this->assertEqual(100, $variables['totalPercentCoverage']); + $this->assertEqual(4, $variables['totalLinesOfCoverage']); + $expected = array('file' => array('byFileReport' => 'file.html', 'percentage' => 100)); + $this->assertEqual($expected, $variables['coverageByFile']); + $this->assertEqual(50, $variables['filesTouchedPercentage']); + $this->assertEqual($untouched, $variables['untouched']); + } + + function testPercentageCoverageByFile() { + $coverage = array(0,0,0,1,1,1); + $results = array(); + $this->calc->percentCoverageByFile($coverage, 'file', $results); + $pct = $results[0]; + $this->assertEqual(50, $pct['file']['percentage']); + $this->assertEqual('file.html', $pct['file']['byFileReport']); + } + + function testTotalLoc() { + $this->assertEqual(13, $this->calc->totalLoc(10, array(1,2,3))); + } + + function testLineCoverage() { + $this->assertEqual(10, $this->calc->lineCoverage(10, -1)); + $this->assertEqual(10, $this->calc->lineCoverage(10, 0)); + $this->assertEqual(11, $this->calc->lineCoverage(10, 1)); + } + + function testTotalCoverage() { + $this->assertEqual(11, $this->calc->totalCoverage(10, array(-1,1))); + } + + static function getAttribute($element, $attribute) { + $a = $element->attributes(); + return $a[$attribute]; + } + + static function dom($stream) { + rewind($stream); + $actual = stream_get_contents($stream); + $html = DOMDocument::loadHTML($actual); + return simplexml_import_dom($html); + } +} + +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/test/coverage_data_handler_test.php b/3rdparty/simpletest/extensions/coverage/test/coverage_data_handler_test.php new file mode 100644 index 0000000000..54c67a4a7b --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/test/coverage_data_handler_test.php @@ -0,0 +1,83 @@ +skipIf( + !file_exists('DB/sqlite.php'), + 'The Coverage extension needs to have PEAR installed'); + } + + function setUp() { + require_once dirname(__FILE__) .'/../coverage_data_handler.php'; + } + + function testAggregateCoverageCode() { + $handler = new CoverageDataHandler($this->tempdb()); + $this->assertEqual(-2, $handler->aggregateCoverageCode(-2, -2)); + $this->assertEqual(-2, $handler->aggregateCoverageCode(-2, 10)); + $this->assertEqual(-2, $handler->aggregateCoverageCode(10, -2)); + $this->assertEqual(-1, $handler->aggregateCoverageCode(-1, -1)); + $this->assertEqual(10, $handler->aggregateCoverageCode(-1, 10)); + $this->assertEqual(10, $handler->aggregateCoverageCode(10, -1)); + $this->assertEqual(20, $handler->aggregateCoverageCode(10, 10)); + } + + function testSimpleWriteRead() { + $handler = new CoverageDataHandler($this->tempdb()); + $handler->createSchema(); + $coverage = array(10 => -2, 20 => -1, 30 => 0, 40 => 1); + $handler->write(array('file' => $coverage)); + + $actual = $handler->readFile('file'); + $expected = array(10 => -2, 20 => -1, 30 => 0, 40 => 1); + $this->assertEqual($expected, $actual); + } + + function testMultiFileWriteRead() { + $handler = new CoverageDataHandler($this->tempdb()); + $handler->createSchema(); + $handler->write(array( + 'file1' => array(-2, -1, 1), + 'file2' => array(-2, -1, 1) + )); + $handler->write(array( + 'file1' => array(-2, -1, 1) + )); + + $expected = array( + 'file1' => array(-2, -1, 2), + 'file2' => array(-2, -1, 1) + ); + $actual = $handler->read(); + $this->assertEqual($expected, $actual); + } + + function testGetfilenames() { + $handler = new CoverageDataHandler($this->tempdb()); + $handler->createSchema(); + $rawCoverage = array('file0' => array(), 'file1' => array()); + $handler->write($rawCoverage); + $actual = $handler->getFilenames(); + $this->assertEqual(array('file0', 'file1'), $actual); + } + + function testWriteUntouchedFiles() { + $handler = new CoverageDataHandler($this->tempdb()); + $handler->createSchema(); + $handler->writeUntouchedFile('bluejay'); + $handler->writeUntouchedFile('robin'); + $this->assertEqual(array('bluejay', 'robin'), $handler->readUntouchedFiles()); + } + + function testLtrim() { + $this->assertEqual('ber', CoverageDataHandler::ltrim('goo', 'goober')); + $this->assertEqual('some/file', CoverageDataHandler::ltrim('./', './some/file')); + $this->assertEqual('/x/y/z/a/b/c', CoverageDataHandler::ltrim('/a/b/', '/x/y/z/a/b/c')); + } + + function tempdb() { + return tempnam(NULL, 'coverage.test.db'); + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/test/coverage_reporter_test.php b/3rdparty/simpletest/extensions/coverage/test/coverage_reporter_test.php new file mode 100644 index 0000000000..a8b09962a0 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/test/coverage_reporter_test.php @@ -0,0 +1,22 @@ +skipIf( + !file_exists('DB/sqlite.php'), + 'The Coverage extension needs to have PEAR installed'); + } + + function setUp() { + require_once dirname(__FILE__) .'/../coverage_reporter.php'; + new CoverageReporter(); + } + + function testreportFilename() { + $this->assertEqual("parula.php.html", CoverageReporter::reportFilename("parula.php")); + $this->assertEqual("warbler_parula.php.html", CoverageReporter::reportFilename("warbler/parula.php")); + $this->assertEqual("warbler_parula.php.html", CoverageReporter::reportFilename("warbler\\parula.php")); + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/test/coverage_test.php b/3rdparty/simpletest/extensions/coverage/test/coverage_test.php new file mode 100644 index 0000000000..f09d03f78a --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/test/coverage_test.php @@ -0,0 +1,109 @@ +skipIf( + !file_exists('DB/sqlite.php'), + 'The Coverage extension needs to have PEAR installed'); + } + + function setUp() { + require_once dirname(__FILE__) .'/../coverage.php'; + } + + function testIsFileIncluded() { + $coverage = new CodeCoverage(); + $this->assertTrue($coverage->isFileIncluded('aaa')); + $coverage->includes = array('a'); + $this->assertTrue($coverage->isFileIncluded('aaa')); + $coverage->includes = array('x'); + $this->assertFalse($coverage->isFileIncluded('aaa')); + $coverage->excludes = array('aa'); + $this->assertFalse($coverage->isFileIncluded('aaa')); + } + + function testIsFileIncludedRegexp() { + $coverage = new CodeCoverage(); + $coverage->includes = array('modules/.*\.php$'); + $coverage->excludes = array('bad-bunny.php'); + $this->assertFalse($coverage->isFileIncluded('modules/a.test')); + $this->assertFalse($coverage->isFileIncluded('modules/bad-bunny.test')); + $this->assertTrue($coverage->isFileIncluded('modules/test.php')); + $this->assertFalse($coverage->isFileIncluded('module-bad/good-bunny.php')); + $this->assertTrue($coverage->isFileIncluded('modules/good-bunny.php')); + } + + function testIsDirectoryIncludedPastMaxDepth() { + $coverage = new CodeCoverage(); + $coverage->maxDirectoryDepth = 5; + $this->assertTrue($coverage->isDirectoryIncluded('aaa', 1)); + $this->assertFalse($coverage->isDirectoryIncluded('aaa', 5)); + } + + function testIsDirectoryIncluded() { + $coverage = new CodeCoverage(); + $this->assertTrue($coverage->isDirectoryIncluded('aaa', 0)); + $coverage->excludes = array('b$'); + $this->assertTrue($coverage->isDirectoryIncluded('aaa', 0)); + $coverage->includes = array('a$'); // includes are ignore, all dirs are included unless excluded + $this->assertTrue($coverage->isDirectoryIncluded('aaa', 0)); + $coverage->excludes = array('.*a$'); + $this->assertFalse($coverage->isDirectoryIncluded('aaa', 0)); + } + + function testFilter() { + $coverage = new CodeCoverage(); + $data = array('a' => 0, 'b' => 0, 'c' => 0); + $coverage->includes = array('b'); + $coverage->filter($data); + $this->assertEqual(array('b' => 0), $data); + } + + function testUntouchedFiles() { + $coverage = new CodeCoverage(); + $touched = array_flip(array("test/coverage_test.php")); + $actual = array(); + $coverage->includes = array('coverage_test\.php$'); + $parentDir = realpath(dirname(__FILE__)); + $coverage->getUntouchedFiles($actual, $touched, $parentDir, $parentDir); + $this->assertEqual(array("coverage_test.php"), $actual); + } + + function testResetLog() { + $coverage = new CodeCoverage(); + $coverage->log = tempnam(NULL, 'php.xdebug.coverage.test.'); + $coverage->resetLog(); + $this->assertTrue(file_exists($coverage->log)); + } + + function testSettingsSerialization() { + $coverage = new CodeCoverage(); + $coverage->log = '/banana/boat'; + $coverage->includes = array('apple', 'orange'); + $coverage->excludes = array('tomato', 'pea'); + $data = $coverage->getSettings(); + $this->assertNotNull($data); + + $actual = new CodeCoverage(); + $actual->setSettings($data); + $this->assertEqual('/banana/boat', $actual->log); + $this->assertEqual(array('apple', 'orange'), $actual->includes); + $this->assertEqual(array('tomato', 'pea'), $actual->excludes); + } + + function testSettingsCanBeReadWrittenToDisk() { + $settings_file = 'banana-boat-coverage-settings-test.dat'; + $coverage = new CodeCoverage(); + $coverage->log = '/banana/boat'; + $coverage->settingsFile = $settings_file; + $coverage->writeSettings(); + + $actual = new CodeCoverage(); + $actual->settingsFile = $settings_file; + $actual->readSettings(); + $this->assertEqual('/banana/boat', $actual->log); + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/test/coverage_utils_test.php b/3rdparty/simpletest/extensions/coverage/test/coverage_utils_test.php new file mode 100644 index 0000000000..b900c5d2c4 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/test/coverage_utils_test.php @@ -0,0 +1,70 @@ +skipIf( + !file_exists('DB/sqlite.php'), + 'The Coverage extension needs to have PEAR installed'); + } + + function setUp() { + require_once dirname(__FILE__) .'/../coverage_utils.php'; + } + + function testMkdir() { + CoverageUtils::mkdir(dirname(__FILE__)); + try { + CoverageUtils::mkdir(__FILE__); + $this->fail("Should give error about cannot create dir of a file"); + } catch (Exception $expected) { + } + } + + function testIsPackageClassAvailable() { + $coverageSource = dirname(__FILE__) .'/../coverage_calculator.php'; + $this->assertTrue(CoverageUtils::isPackageClassAvailable($coverageSource, 'CoverageCalculator')); + $this->assertFalse(CoverageUtils::isPackageClassAvailable($coverageSource, 'BogusCoverage')); + $this->assertFalse(CoverageUtils::isPackageClassAvailable('bogus-file', 'BogusCoverage')); + $this->assertTrue(CoverageUtils::isPackageClassAvailable('bogus-file', 'CoverageUtils')); + } + + function testParseArgumentsMultiValue() { + $actual = CoverageUtils::parseArguments(array('scriptname', '--a=b', '--a=c'), True); + $expected = array('extraArguments' => array(), 'a' => 'c', 'a[]' => array('b', 'c')); + $this->assertEqual($expected, $actual); + } + + function testParseArguments() { + $actual = CoverageUtils::parseArguments(array('scriptname', '--a=b', '-c', 'xxx')); + $expected = array('a' => 'b', 'c' => '', 'extraArguments' => array('xxx')); + $this->assertEqual($expected, $actual); + } + + function testParseDoubleDashNoArguments() { + $actual = CoverageUtils::parseArguments(array('scriptname', '--aa')); + $this->assertTrue(isset($actual['aa'])); + } + + function testParseHyphenedExtraArguments() { + $actual = CoverageUtils::parseArguments(array('scriptname', '--alpha-beta=b', 'gamma-lambda')); + $expected = array('alpha-beta' => 'b', 'extraArguments' => array('gamma-lambda')); + $this->assertEqual($expected, $actual); + } + + function testAddItemAsArray() { + $actual = array(); + CoverageUtils::addItemAsArray($actual, 'bird', 'duck'); + $this->assertEqual(array('bird[]' => array('duck')), $actual); + + CoverageUtils::addItemAsArray(&$actual, 'bird', 'pigeon'); + $this->assertEqual(array('bird[]' => array('duck', 'pigeon')), $actual); + } + + function testIssetOr() { + $data = array('bird' => 'gull'); + $this->assertEqual('lab', CoverageUtils::issetOr($data['dog'], 'lab')); + $this->assertEqual('gull', CoverageUtils::issetOr($data['bird'], 'sparrow')); + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/test/sample/code.php b/3rdparty/simpletest/extensions/coverage/test/sample/code.php new file mode 100644 index 0000000000..a2438f4bee --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/test/sample/code.php @@ -0,0 +1,4 @@ +skipIf( + !file_exists('DB/sqlite.php'), + 'The Coverage extension needs to have PEAR installed'); + } + + function setUp() { + require_once dirname(__FILE__) .'/../simple_coverage_writer.php'; + require_once dirname(__FILE__) .'/../coverage_calculator.php'; + + } + + function testGenerateSummaryReport() { + $writer = new SimpleCoverageWriter(); + $coverage = array('file' => array(0, 1)); + $untouched = array('missed-file'); + $calc = new CoverageCalculator(); + $variables = $calc->variables($coverage, $untouched); + $variables['title'] = 'coverage'; + $out = fopen("php://memory", 'w'); + $writer->writeSummary($out, $variables); + $dom = self::dom($out); + $totalPercentCoverage = $dom->elements->xpath("//span[@class='totalPercentCoverage']"); + $this->assertEqual('50%', (string)$totalPercentCoverage[0]); + + $fileLinks = $dom->elements->xpath("//a[@class='byFileReportLink']"); + $fileLinkAttr = $fileLinks[0]->attributes(); + $this->assertEqual('file.html', $fileLinkAttr['href']); + $this->assertEqual('file', (string)($fileLinks[0])); + + $untouchedFile = $dom->elements->xpath("//span[@class='untouchedFile']"); + $this->assertEqual('missed-file', (string)$untouchedFile[0]); + } + + function testGenerateCoverageByFile() { + $writer = new SimpleCoverageWriter(); + $cov = array(3 => 1, 4 => -2); // 2 comments, 1 code, 1 dead (1-based indexes) + $out = fopen("php://memory", 'w'); + $file = dirname(__FILE__) .'/sample/code.php'; + $calc = new CoverageCalculator(); + $variables = $calc->coverageByFileVariables($file, $cov); + $variables['title'] = 'coverage'; + $writer->writeByFile($out, $variables); + $dom = self::dom($out); + + $cells = $dom->elements->xpath("//table[@id='code']/tbody/tr/td/span"); + $this->assertEqual("comment code", self::getAttribute($cells[1], 'class')); + $this->assertEqual("comment code", self::getAttribute($cells[3], 'class')); + $this->assertEqual("covered code", self::getAttribute($cells[5], 'class')); + $this->assertEqual("dead code", self::getAttribute($cells[7], 'class')); + } + + static function getAttribute($element, $attribute) { + $a = $element->attributes(); + return $a[$attribute]; + } + + static function dom($stream) { + rewind($stream); + $actual = stream_get_contents($stream); + $html = DOMDocument::loadHTML($actual); + return simplexml_import_dom($html); + } +} +?> \ No newline at end of file diff --git a/3rdparty/simpletest/extensions/coverage/test/test.php b/3rdparty/simpletest/extensions/coverage/test/test.php new file mode 100644 index 0000000000..0af4dbf3e7 --- /dev/null +++ b/3rdparty/simpletest/extensions/coverage/test/test.php @@ -0,0 +1,14 @@ +TestSuite('Coverage Unit tests'); + $path = dirname(__FILE__) . '/*_test.php'; + foreach(glob($path) as $test) { + $this->addFile($test); + } + } +} +?> \ No newline at end of file