Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Mueller <thomas.mueller@tmit.eu>2012-08-26 03:35:25 +0400
committerThomas Mueller <thomas.mueller@tmit.eu>2012-08-26 03:36:06 +0400
commit27eb6655162743ada7f64ba4157e425ca86ad312 (patch)
tree3339f1f524411913222b64d3f09b1d0d616042b8 /3rdparty
parentbae07faa3469ff1dcd16c2071946e6a3e7a8b4c2 (diff)
adding coverage extension for simpletest
Diffstat (limited to '3rdparty')
-rw-r--r--3rdparty/simpletest/extensions/coverage/autocoverage.php29
-rwxr-xr-x3rdparty/simpletest/extensions/coverage/bin/php-coverage-close.php14
-rwxr-xr-x3rdparty/simpletest/extensions/coverage/bin/php-coverage-open.php31
-rwxr-xr-x3rdparty/simpletest/extensions/coverage/bin/php-coverage-report.php29
-rw-r--r--3rdparty/simpletest/extensions/coverage/coverage.php196
-rw-r--r--3rdparty/simpletest/extensions/coverage/coverage_calculator.php98
-rw-r--r--3rdparty/simpletest/extensions/coverage/coverage_data_handler.php125
-rw-r--r--3rdparty/simpletest/extensions/coverage/coverage_reporter.php68
-rw-r--r--3rdparty/simpletest/extensions/coverage/coverage_utils.php114
-rw-r--r--3rdparty/simpletest/extensions/coverage/coverage_writer.php16
-rw-r--r--3rdparty/simpletest/extensions/coverage/simple_coverage_writer.php39
-rw-r--r--3rdparty/simpletest/extensions/coverage/templates/file.php60
-rw-r--r--3rdparty/simpletest/extensions/coverage/templates/index.php106
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/coverage_calculator_test.php65
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/coverage_data_handler_test.php83
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/coverage_reporter_test.php22
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/coverage_test.php109
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/coverage_utils_test.php70
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/sample/code.php4
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/simple_coverage_writer_test.php69
-rw-r--r--3rdparty/simpletest/extensions/coverage/test/test.php14
21 files changed, 1361 insertions, 0 deletions
diff --git a/3rdparty/simpletest/extensions/coverage/autocoverage.php b/3rdparty/simpletest/extensions/coverage/autocoverage.php
new file mode 100644
index 00000000000..9fc961bf43a
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/autocoverage.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+/**
+ * Include this in any file to start coverage, coverage will automatically end
+ * when process dies.
+ */
+require_once(dirname(__FILE__) .'/coverage.php');
+
+if (CodeCoverage::isCoverageOn()) {
+ $coverage = CodeCoverage::getInstance();
+ $coverage->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 00000000000..9a5a52ba134
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-close.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Close code coverage data collection, next step is to generate report
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+/**
+ * include coverage files
+ */
+require_once(dirname(__FILE__) . '/../coverage.php');
+$cc = CodeCoverage::getInstance();
+$cc->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 00000000000..c04e1fb512f
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-open.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Initialize code coverage data collection, next step is to run your tests
+ * with ini setting auto_prepend_file=autocoverage.php ...
+ *
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+# optional arguments:
+# --include=<some filepath regexp> these files should be included coverage report
+# --exclude=<come filepath regexp> 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 00000000000..d61c822d997
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/bin/php-coverage-report.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Generate a code coverage report
+ *
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+# optional arguments:
+# --reportDir=some/directory the default is ./coverage-report
+# --title='My Coverage Report' title the main page of your report
+
+/**#@+
+ * include coverage files
+ */
+require_once(dirname(__FILE__) . '/../coverage_utils.php');
+require_once(dirname(__FILE__) . '/../coverage.php');
+require_once(dirname(__FILE__) . '/../coverage_reporter.php');
+/**#@-*/
+$cc = CodeCoverage::getInstance();
+$cc->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 00000000000..44e5b679b82
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/coverage.php
@@ -0,0 +1,196 @@
+<?php
+/**
+* @package SimpleTest
+* @subpackage Extensions
+*/
+/**
+* load coverage data handle
+*/
+require_once dirname(__FILE__) . '/coverage_data_handler.php';
+
+/**
+ * Orchestrates code coverage both in this thread and in subthread under apache
+ * Assumes this is running on same machine as apache.
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+class CodeCoverage {
+ var $log;
+ var $root;
+ var $includes;
+ var $excludes;
+ var $directoryDepth;
+ var $maxDirectoryDepth = 20; // reasonable, otherwise arbitrary
+ var $title = "Code Coverage";
+
+ # NOTE: This assumes all code shares the same current working directory.
+ var $settingsFile = './code-coverage-settings.dat';
+
+ static $instance;
+
+ function writeUntouched() {
+ $touched = array_flip($this->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 00000000000..f1aa57bbab5
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/coverage_calculator.php
@@ -0,0 +1,98 @@
+<?php
+/**
+* @package SimpleTest
+* @subpackage Extensions
+*/
+/**
+* @package SimpleTest
+* @subpackage Extensions
+*/
+class CoverageCalculator {
+
+ function coverageByFileVariables($file, $coverage) {
+ $hnd = fopen($file, 'r');
+ if ($hnd == null) {
+ throw new Exception("File $file is missing");
+ }
+ $lines = array();
+ for ($i = 1; !feof($hnd); $i++) {
+ $line = fgets($hnd);
+ $lineCoverage = $this->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 00000000000..bbf81106fc5
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/coverage_data_handler.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+/**
+ * @todo which db abstraction layer is this?
+ */
+require_once 'DB/sqlite.php';
+
+/**
+ * Persists code coverage data into SQLite database and aggregate data for convienent
+ * interpretation in report generator. Be sure to not to keep an instance longer
+ * than you have, otherwise you risk overwriting database edits from another process
+ * also trying to make updates.
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+class CoverageDataHandler {
+
+ var $db;
+
+ function __construct($filename) {
+ $this->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 00000000000..ba4e7161c2f
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/coverage_reporter.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+/**#@+
+ * include additional coverage files
+ */
+require_once dirname(__FILE__) .'/coverage_calculator.php';
+require_once dirname(__FILE__) .'/coverage_utils.php';
+require_once dirname(__FILE__) .'/simple_coverage_writer.php';
+/**#@-*/
+
+/**
+ * Take aggregated coverage data and generate reports from it using smarty
+ * templates
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+class CoverageReporter {
+ var $coverage;
+ var $untouched;
+ var $reportDir;
+ var $title = 'Coverage';
+ var $writer;
+ var $calculator;
+
+ function __construct() {
+ $this->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 00000000000..d2c3a635f43
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/coverage_utils.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+/**
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+class CoverageUtils {
+
+ static function mkdir($dir) {
+ if (!file_exists($dir)) {
+ mkdir($dir, 0777, True);
+ } else {
+ if (!is_dir($dir)) {
+ throw new Exception($dir .' exists as a file, not a directory');
+ }
+ }
+ }
+
+ static function requireSqlite() {
+ if (!self::isPackageClassAvailable('DB/sqlite.php', 'SQLiteDatabase')) {
+ echo "sqlite library is required to be installed and available in include_path";
+ exit(1);
+ }
+ }
+
+ static function isPackageClassAvailable($includeFile, $class) {
+ @include_once($includeFile);
+ return class_exists($class);
+ }
+
+ /**
+ * Parses simple parameters from CLI.
+ *
+ * Puts trailing parameters into string array in 'extraArguments'
+ *
+ * Example:
+ * $args = CoverageUtil::parseArguments($_SERVER['argv']);
+ * if ($args['verbose']) echo "Verbose Mode On\n";
+ * $files = $args['extraArguments'];
+ *
+ * Example CLI:
+ * --foo=blah -x -h some trailing arguments
+ *
+ * if multiValueMode is true
+ * Example CLI:
+ * --include=a --include=b --exclude=c
+ * Then
+ * $args = CoverageUtil::parseArguments($_SERVER['argv']);
+ * $args['include[]'] will equal array('a', 'b')
+ * $args['exclude[]'] will equal array('c')
+ * $args['exclude'] will equal c
+ * $args['include'] will equal b NOTE: only keeps last value
+ *
+ * @param unknown_type $argv
+ * @param supportMutliValue - will store 2nd copy of value in an array with key "foo[]"
+ * @return unknown
+ */
+ static public function parseArguments($argv, $mutliValueMode = False) {
+ $args = array();
+ $args['extraArguments'] = array();
+ array_shift($argv); // scriptname
+ foreach ($argv as $arg) {
+ if (ereg('^--([^=]+)=(.*)', $arg, $reg)) {
+ $args[$reg[1]] = $reg[2];
+ if ($mutliValueMode) {
+ self::addItemAsArray($args, $reg[1], $reg[2]);
+ }
+ } elseif (ereg('^[-]{1,2}([^[:blank:]]+)', $arg, $reg)) {
+ $nonnull = '';
+ $args[$reg[1]] = $nonnull;
+ if ($mutliValueMode) {
+ self::addItemAsArray($args, $reg[1], $nonnull);
+ }
+ } else {
+ $args['extraArguments'][] = $arg;
+ }
+ }
+
+ return $args;
+ }
+
+ /**
+ * Adds a value as an array of one, or appends to an existing array elements
+ *
+ * @param unknown_type $array
+ * @param unknown_type $item
+ */
+ static function addItemAsArray(&$array, $key, $item) {
+ $array_key = $key .'[]';
+ if (array_key_exists($array_key, $array)) {
+ $array[$array_key][] = $item;
+ } else {
+ $array[$array_key] = array($item);
+ }
+ }
+
+ /**
+ * isset function with default value
+ *
+ * Example: $z = CoverageUtils::issetOr($array[$key], 'no value given')
+ *
+ * @param unknown_type $val
+ * @param unknown_type $default
+ * @return first value unless value is not set then returns 2nd arg or null if no 2nd arg
+ */
+ static public function issetOr(&$val, $default = null)
+ {
+ return isset($val) ? $val : $default;
+ }
+}
+?> \ 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 00000000000..0a8519cb509
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/coverage_writer.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+/**
+ * @package SimpleTest
+ * @subpackage Extensions
+ */
+interface CoverageWriter {
+
+ function writeSummary($out, $variables);
+
+ function writeByFile($out, $variables);
+}
+?> \ 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 00000000000..7eb73fc8ab9
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/simple_coverage_writer.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * SimpleCoverageWriter class file
+ * @package SimpleTest
+ * @subpackage UnitTester
+ * @version $Id: unit_tester.php 1882 2009-07-01 14:30:05Z lastcraft $
+ */
+/**
+ * base coverage writer class
+ */
+require_once dirname(__FILE__) .'/coverage_writer.php';
+
+/**
+ * SimpleCoverageWriter class
+ * @package SimpleTest
+ * @subpackage UnitTester
+ */
+class SimpleCoverageWriter implements CoverageWriter {
+
+ function writeSummary($out, $variables) {
+ extract($variables);
+ $now = date("F j, Y, g:i a");
+ ob_start();
+ include dirname(__FILE__) . '/templates/index.php';
+ $contents = ob_get_contents();
+ fwrite ($out, $contents);
+ ob_end_clean();
+ }
+
+ function writeByFile($out, $variables) {
+ extract($variables);
+ ob_start();
+ include dirname(__FILE__) . '/templates/file.php';
+ $contents = ob_get_contents();
+ fwrite ($out, $contents);
+ ob_end_clean();
+ }
+}
+?> \ 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 00000000000..70f6903068c
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/templates/file.php
@@ -0,0 +1,60 @@
+<html>
+<head>
+<title><?php echo $title ?></title>
+</head>
+<style type="text/css">
+body {
+ font-family: "Gill Sans MT", "Gill Sans", GillSans, Arial, Helvetica, sans-serif;
+}
+h1 {
+ font-size: medium;
+}
+#code {
+ border-spacing: 0;
+}
+.lineNo {
+ color: #ccc;
+}
+.code, .lineNo {
+ white-space: pre;
+ font-family: monospace;
+}
+.covered {
+ color: #090;
+}
+.missed {
+ color: #f00;
+}
+.dead {
+ color: #00f;
+}
+.comment {
+ color: #333;
+}
+</style>
+<body>
+<h1 id="title"><?php echo $title ?></h1>
+<table id="code">
+ <tbody>
+<?php foreach ($lines as $lineNo => $line) { ?>
+ <tr>
+ <td><span class="lineNo"><?php echo $lineNo ?></span></td>
+ <td><span class="<?php echo $line['lineCoverage'] ?> code"><?php echo htmlentities($line['code']) ?></span></td>
+ </tr>
+<?php } ?>
+ </tbody>
+</table>
+<h2>Legend</h2>
+<dl>
+ <dt><span class="missed">Missed</span></dt>
+ <dd>lines code that <strong>were not</strong> excersized during program execution.</dd>
+ <dt><span class="covered">Covered</span></dt>
+ <dd>lines code <strong>were</strong> excersized during program execution.</dd>
+ <dt><span class="comment">Comment/non executable</span></dt>
+ <dd>Comment or non-executable line of code.</dd>
+ <dt><span class="dead">Dead</span></dt>
+ <dd>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.</dd>
+</dl>
+</body>
+</html>
diff --git a/3rdparty/simpletest/extensions/coverage/templates/index.php b/3rdparty/simpletest/extensions/coverage/templates/index.php
new file mode 100644
index 00000000000..e4374e23809
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/templates/index.php
@@ -0,0 +1,106 @@
+<html>
+<head>
+<title><?php echo $title ?></title>
+</head>
+<style type="text/css">
+h1 {
+ font-size: medium;
+}
+
+body {
+ font-family: "Gill Sans MT", "Gill Sans", GillSans, Arial, Helvetica,
+ sans-serif;
+}
+
+td.percentage {
+ text-align: right;
+}
+
+caption {
+ border-bottom: thin solid;
+ font-weight: bolder;
+}
+
+dt {
+ font-weight: bolder;
+}
+
+table {
+ margin: 1em;
+}
+</style>
+<body>
+<h1 id="title"><?php echo $title ?></h1>
+<table>
+ <caption>Summary</caption>
+ <tbody>
+ <tr>
+ <td>Total Coverage (<a href="#total-coverage">?</a>) :</td>
+ <td class="percentage"><span class="totalPercentCoverage"><?php echo number_format($totalPercentCoverage, 0) ?>%</span></td>
+ </tr>
+ <tr>
+ <td>Total Files Covered (<a href="#total-files-covered">?</a>) :</td>
+ <td class="percentage"><span class="filesTouchedPercentage"><?php echo number_format($filesTouchedPercentage, 0) ?>%</span></td>
+ </tr>
+ <tr>
+ <td>Report Generation Date :</td>
+ <td><?php echo $now ?></td>
+ </tr>
+ </tbody>
+</table>
+<table id="covered-files">
+ <caption>Coverage (<a href="#coverage">?</a>)</caption>
+ <thead>
+ <tr>
+ <th>File</th>
+ <th>Coverage</th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($coverageByFile as $file => $coverage) { ?>
+ <tr>
+ <td><a class="byFileReportLink" href="<?php echo $coverage['byFileReport'] ?>"><?php echo $file ?></a></td>
+ <td class="percentage"><span class="percentCoverage"><?php echo number_format($coverage['percentage'], 0) ?>%</span></td>
+ </tr>
+ <?php } ?>
+ </tbody>
+</table>
+<table>
+ <caption>Files Not Covered (<a href="#untouched">?</a>)</caption>
+ <tbody>
+ <?php foreach ($untouched as $key => $file) { ?>
+ <tr>
+ <td><span class="untouchedFile"><?php echo $file ?></span></td>
+ </tr>
+ <?php } ?>
+ </tbody>
+</table>
+
+<h2>Glossary</h2>
+<dl>
+ <dt><a name="total-coverage">Total Coverage</a></dt>
+ <dd>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.</dd>
+ <dt><a name="total-files-covered">Total Files Covered</a></dt>
+ <dd>This is the ratio of the number of files tested, to the number of
+ files not tested at all.</dd>
+ <dt><a name="coverage">Coverage</a></dt>
+ <dd>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.</dd>
+ <dt><a name="untouched">Files Not Covered</a></dt>
+ <dd>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.</dd>
+</dl>
+
+<p>Code coverage generated by <a href="http://www.simpletest.org">SimpleTest</a></p>
+
+</body>
+</html>
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 00000000000..64bd8d463fb
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/coverage_calculator_test.php
@@ -0,0 +1,65 @@
+<?php
+require_once(dirname(__FILE__) . '/../../../autorun.php');
+
+class CoverageCalculatorTest extends UnitTestCase {
+ function skip() {
+ $this->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 00000000000..54c67a4a7b0
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/coverage_data_handler_test.php
@@ -0,0 +1,83 @@
+<?php
+require_once(dirname(__FILE__) . '/../../../autorun.php');
+
+class CoverageDataHandlerTest extends UnitTestCase {
+ function skip() {
+ $this->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 00000000000..a8b09962a04
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/coverage_reporter_test.php
@@ -0,0 +1,22 @@
+<?php
+require_once(dirname(__FILE__) . '/../../../autorun.php');
+
+class CoverageReporterTest extends UnitTestCase {
+ function skip() {
+ $this->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 00000000000..f09d03f78a1
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/coverage_test.php
@@ -0,0 +1,109 @@
+<?php
+require_once(dirname(__FILE__) . '/../../../autorun.php');
+require_once(dirname(__FILE__) . '/../../../mock_objects.php');
+
+class CodeCoverageTest extends UnitTestCase {
+ function skip() {
+ $this->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 00000000000..b900c5d2c43
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/coverage_utils_test.php
@@ -0,0 +1,70 @@
+<?php
+require_once dirname(__FILE__) . '/../../../autorun.php';
+
+class CoverageUtilsTest extends UnitTestCase {
+ function skip() {
+ $this->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 00000000000..a2438f4bee0
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/sample/code.php
@@ -0,0 +1,4 @@
+<?php
+// sample code
+$x = 1 + 2;
+if (false) echo "dead"; \ No newline at end of file
diff --git a/3rdparty/simpletest/extensions/coverage/test/simple_coverage_writer_test.php b/3rdparty/simpletest/extensions/coverage/test/simple_coverage_writer_test.php
new file mode 100644
index 00000000000..2c9f9abc18b
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/simple_coverage_writer_test.php
@@ -0,0 +1,69 @@
+<?php
+require_once(dirname(__FILE__) . '/../../../autorun.php');
+
+class SimpleCoverageWriterTest extends UnitTestCase {
+ function skip() {
+ $this->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 00000000000..0af4dbf3e74
--- /dev/null
+++ b/3rdparty/simpletest/extensions/coverage/test/test.php
@@ -0,0 +1,14 @@
+<?php
+// $Id: $
+require_once(dirname(__FILE__) . '/../../../autorun.php');
+
+class CoverageUnitTests extends TestSuite {
+ function CoverageUnitTests() {
+ $this->TestSuite('Coverage Unit tests');
+ $path = dirname(__FILE__) . '/*_test.php';
+ foreach(glob($path) as $test) {
+ $this->addFile($test);
+ }
+ }
+}
+?> \ No newline at end of file