summaryrefslogtreecommitdiffstats
path: root/3rdparty/simpletest/extensions/coverage/coverage.php
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/simpletest/extensions/coverage/coverage.php')
-rw-r--r--3rdparty/simpletest/extensions/coverage/coverage.php196
1 files changed, 196 insertions, 0 deletions
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;
+ }
+}
+?>