This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/tests/lib/vendor/lime/LimeCoverage.php
2010-01-04 15:26:20 +01:00

250 lines
5.9 KiB
PHP

<?php
/*
* This file is part of the Lime framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* (c) Bernhard Schussek <bernhard.schussek@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
class LimeCoverage extends LimeRegistration
{
const
COVERED = 1,
UNCOVERED = -1;
protected
$options = array(),
$files = array(),
$suite = null,
$coverage = array(),
$coveredLines = 0,
$uncoveredLines = 0,
$coveredCode = array(),
$uncoveredCode = array(),
$actualCode = array();
public function __construct(LimeTestSuite $suite, array $options = array())
{
$this->suite = $suite;
$this->options = array_merge(array(
'base_dir' => null,
'extension' => '.php',
'verbose' => false,
), $options);
// temporary solution, LimeRegistration needs to be modified
$this->setBaseDir($this->options['base_dir']);
$this->setExtension($this->options['extension']);
if (!function_exists('xdebug_start_code_coverage'))
{
throw new Exception('You must install and enable xdebug before using lime coverage.');
}
if (!ini_get('xdebug.extended_info'))
{
throw new Exception('You must set xdebug.extended_info to 1 in your php.ini to use lime coverage.');
}
}
public function setFiles($files)
{
if (!is_array($files))
{
$files = array($files);
}
$this->files = $files;
}
public function run()
{
if (!count($this->suite->files))
{
throw new Exception('You must register some test files before running coverage!');
}
if (!count($this->files))
{
throw new Exception('You must register some files to cover!');
}
$this->coverage = array();
$this->process($this->suite->files);
$this->parseCoverage($this->coverage);
$this->render();
}
protected function process(array $files)
{
$this->output = new LimeOutput();
foreach ($files as $file)
{
$command = new LimeShellCommand($file, array('coverage' => true));
$command->execute();
// script failed
if ($command->getStatus() != LimeShell::SUCCESS)
{
$this->output->echoln(sprintf('Warning: %s returned status %d, results may be inaccurate', $file, $command->getStatus()), LimeOutput::ERROR);
}
// script succeeded, coverage not readable
if (false === $coverage = @unserialize($command->getOutput()))
{
if ($command->getStatus() == LimeShell::SUCCESS)
{
throw new Exception(sprintf('Unable to unserialize coverage for file "%s"', $file));
}
}
else
{
foreach ($coverage as $file => $lines)
{
if (!isset($this->coverage[$file]))
{
$this->coverage[$file] = $lines;
}
else
{
foreach ($lines as $line => $flag)
{
if ($flag == self::COVERED)
{
$this->coverage[$file][$line] = 1;
}
}
}
}
}
}
}
protected function parseCoverage(array $coverage)
{
$this->coveredLines = 0;
$this->uncoveredLines = 0;
ksort($coverage);
foreach ($coverage as $file => $lines)
{
$this->coveredCode[$file] = array();
$this->uncoveredCode[$file] = array();
foreach ($lines as $line => $flag)
{
if ($flag == self::COVERED)
{
$this->coveredCode[$file][] = $line;
$this->coveredLines++;
}
else
{
$this->uncoveredCode[$file][] = $line;
$this->uncoveredLines++;
}
}
}
$lexer = new LimeLexerCodeLines();
foreach ($this->files as $file)
{
if (!array_key_exists($file, $this->coveredCode))
{
$this->coveredCode[$file] = array();
$this->uncoveredCode[$file] = $lexer->parse($file);
$this->uncoveredLines += count($this->uncoveredCode[$file]);
}
}
}
protected function render()
{
$printer = new LimePrinter(new LimeColorizer());
foreach ($this->files as $file)
{
$totalLines = count($this->coveredCode[$file]) + count($this->uncoveredCode[$file]);
$percent = count($this->coveredCode[$file]) * 100 / max($totalLines, 1);
$relativeFile = $this->getRelativeFile($file);
if ($percent == 100)
{
$style = LimePrinter::OK;
}
else if ($percent >= 90)
{
$style = LimePrinter::INFO;
}
else if ($percent <= 20)
{
$style = LimePrinter::NOT_OK;
}
else
{
$style = null;
}
$printer->printLine(sprintf("%-76s%3.0f%%", $relativeFile, $percent), $style);
if ($this->options['verbose'] && $percent > 0 && $percent < 100)
{
$printer->printLine(sprintf("missing: %s", $this->formatRange($this->uncoveredCode[$file])), LimePrinter::COMMENT);
}
}
$totalLines = $this->coveredLines + $this->uncoveredLines;
$percent = $this->coveredLines * 100 / max($totalLines, 1);
if ($percent <= 20)
{
$style = LimePrinter::NOT_OK;
}
else
{
$style = LimePrinter::HAPPY;
}
$printer->printLine(str_pad(sprintf(" Total Coverage: %3.0f%%", $percent), 80), $style);
}
protected function formatRange(array $lines)
{
sort($lines);
$formatted = '';
$first = -1;
$last = -1;
foreach ($lines as $line)
{
if ($last + 1 != $line)
{
if ($first != -1)
{
$formatted .= $first == $last ? "$first " : "[$first - $last] ";
}
$first = $line;
$last = $line;
}
else
{
$last = $line;
}
}
if ($first != -1)
{
$formatted .= $first == $last ? "$first " : "[$first - $last] ";
}
return $formatted;
}
}