nextcloud/3rdparty/simpletest/extensions/coverage/coverage.php

197 lines
5.8 KiB
PHP

<?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;
}
}
?>