adding zend project folders into old campcaster.
This commit is contained in:
parent
56abfaf28e
commit
7ef0c18b26
4045 changed files with 1054952 additions and 0 deletions
414
library/phing/tasks/ext/coverage/CoverageThresholdTask.php
Normal file
414
library/phing/tasks/ext/coverage/CoverageThresholdTask.php
Normal file
|
@ -0,0 +1,414 @@
|
|||
<?php
|
||||
/**
|
||||
* $Id: CoverageThresholdTask.php 905 2010-10-05 16:28:03Z mrook $
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information please see
|
||||
* <http://phing.info>.
|
||||
*/
|
||||
|
||||
require_once 'phing/Task.php';
|
||||
require_once 'phing/system/io/PhingFile.php';
|
||||
require_once 'phing/system/util/Properties.php';
|
||||
|
||||
/**
|
||||
* Stops the build if any of the specified coverage threshold was not reached
|
||||
*
|
||||
* @author Benjamin Schultz <bschultz@proqrent.de>
|
||||
* @version $Id: CoverageThresholdTask.php 905 2010-10-05 16:28:03Z mrook $
|
||||
* @package phing.tasks.ext.coverage
|
||||
* @since 2.4.1
|
||||
*/
|
||||
class CoverageThresholdTask extends Task
|
||||
{
|
||||
/**
|
||||
* Holds an optional classpath
|
||||
*
|
||||
* @var Path
|
||||
*/
|
||||
private $_classpath = null;
|
||||
|
||||
/**
|
||||
* Holds an optional database file
|
||||
*
|
||||
* @var PhingFile
|
||||
*/
|
||||
private $_database = null;
|
||||
|
||||
/**
|
||||
* Holds the coverage threshold for the entire project
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_perProject = 25;
|
||||
|
||||
/**
|
||||
* Holds the coverage threshold for any class
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_perClass = 25;
|
||||
|
||||
/**
|
||||
* Holds the coverage threshold for any method
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_perMethod = 25;
|
||||
|
||||
/**
|
||||
* Holds the minimum found coverage value for a class
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_minClassCoverageFound = null;
|
||||
|
||||
/**
|
||||
* Holds the minimum found coverage value for a method
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_minMethodCoverageFound = null;
|
||||
|
||||
/**
|
||||
* Number of statements in the entire project
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_projectStatementCount = 0;
|
||||
|
||||
/**
|
||||
* Number of covered statements in the entire project
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_projectStatementsCovered = 0;
|
||||
|
||||
/**
|
||||
* Whether to enable detailed logging
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $_verbose = false;
|
||||
|
||||
/**
|
||||
* Sets an optional classpath
|
||||
*
|
||||
* @param Path $classpath The classpath
|
||||
*/
|
||||
public function setClasspath(Path $classpath)
|
||||
{
|
||||
if ($this->_classpath === null) {
|
||||
$this->_classpath = $classpath;
|
||||
} else {
|
||||
$this->_classpath->append($classpath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional coverage database to use
|
||||
*
|
||||
* @param PhingFile The database file
|
||||
*/
|
||||
public function setDatabase(PhingFile $database)
|
||||
{
|
||||
$this->_database = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create classpath object
|
||||
*
|
||||
* @return Path
|
||||
*/
|
||||
public function createClasspath()
|
||||
{
|
||||
$this->classpath = new Path();
|
||||
return $this->classpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the coverage threshold for entire project
|
||||
*
|
||||
* @param integer $threshold Coverage threshold for entire project
|
||||
*/
|
||||
public function setPerProject($threshold)
|
||||
{
|
||||
$this->_perProject = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the coverage threshold for any class
|
||||
*
|
||||
* @param integer $threshold Coverage threshold for any class
|
||||
*/
|
||||
public function setPerClass($threshold)
|
||||
{
|
||||
$this->_perClass = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the coverage threshold for any method
|
||||
*
|
||||
* @param integer $threshold Coverage threshold for any method
|
||||
*/
|
||||
public function setPerMethod($threshold)
|
||||
{
|
||||
$this->_perMethod = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable detailed logging or not
|
||||
*
|
||||
* @param boolean $verbose
|
||||
*/
|
||||
public function setVerbose($verbose)
|
||||
{
|
||||
$this->_verbose = StringHelper::booleanValue($verbose);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter covered statements
|
||||
*
|
||||
* @param integer $var Coverage CODE/count
|
||||
* @return boolean
|
||||
*/
|
||||
protected function filterCovered($var)
|
||||
{
|
||||
return ($var >= 0 || $var === -2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the coverage threshold
|
||||
*
|
||||
* @param string $filename The filename to analyse
|
||||
* @param array $coverageInformation Array with coverage information
|
||||
*/
|
||||
protected function calculateCoverageThreshold($filename, $coverageInformation)
|
||||
{
|
||||
$classes = PHPUnitUtil::getDefinedClasses($filename, $this->_classpath);
|
||||
|
||||
if (is_array($classes)) {
|
||||
foreach ($classes as $className) {
|
||||
$reflection = new ReflectionClass($className);
|
||||
$classStartLine = $reflection->getStartLine();
|
||||
|
||||
// Strange PHP5 reflection bug, classes without parent class
|
||||
// or implemented interfaces seem to start one line off
|
||||
if ($reflection->getParentClass() === null
|
||||
&& count($reflection->getInterfaces()) === 0
|
||||
) {
|
||||
unset($coverageInformation[$classStartLine + 1]);
|
||||
} else {
|
||||
unset($coverageInformation[$classStartLine]);
|
||||
}
|
||||
|
||||
reset($coverageInformation);
|
||||
|
||||
$methods = $reflection->getMethods();
|
||||
|
||||
foreach ($methods as $method) {
|
||||
// PHP5 reflection considers methods of a parent class
|
||||
// to be part of a subclass, we don't
|
||||
if ($method->getDeclaringClass()->getName() != $reflection->getName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$methodStartLine = $method->getStartLine();
|
||||
$methodEndLine = $method->getEndLine();
|
||||
|
||||
// small fix for XDEBUG_CC_UNUSED
|
||||
if (isset($coverageInformation[$methodStartLine])) {
|
||||
unset($coverageInformation[$methodStartLine]);
|
||||
}
|
||||
|
||||
if (isset($coverageInformation[$methodEndLine])) {
|
||||
unset($coverageInformation[$methodEndLine]);
|
||||
}
|
||||
|
||||
if ($method->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lineNr = key($coverageInformation);
|
||||
|
||||
while ($lineNr !== null && $lineNr < $methodStartLine) {
|
||||
next($coverageInformation);
|
||||
$lineNr = key($coverageInformation);
|
||||
}
|
||||
|
||||
$methodStatementsCovered = 0;
|
||||
$methodStatementCount = 0;
|
||||
|
||||
while ($lineNr !== null && $lineNr <= $methodEndLine) {
|
||||
$methodStatementCount++;
|
||||
|
||||
$lineCoverageInfo = $coverageInformation[$lineNr];
|
||||
// set covered when CODE is other than -1 (not executed)
|
||||
if ($lineCoverageInfo > 0 || $lineCoverageInfo === -2) {
|
||||
$methodStatementsCovered++;
|
||||
}
|
||||
|
||||
next($coverageInformation);
|
||||
$lineNr = key($coverageInformation);
|
||||
}
|
||||
|
||||
if ($methodStatementCount > 0) {
|
||||
$methodCoverage = ( $methodStatementsCovered
|
||||
/ $methodStatementCount) * 100;
|
||||
} else {
|
||||
$methodCoverage = 0;
|
||||
}
|
||||
|
||||
if ($methodCoverage < $this->_perMethod
|
||||
&& !$method->isAbstract()
|
||||
) {
|
||||
throw new BuildException(
|
||||
'The coverage (' . $methodCoverage . '%) '
|
||||
. 'for method "' . $method->getName() . '" is lower'
|
||||
. ' than the specified threshold ('
|
||||
. $this->_perMethod . '%), see file: "'
|
||||
. $filename . '"'
|
||||
);
|
||||
} elseif ($methodCoverage < $this->_perMethod
|
||||
&& $method->isAbstract()
|
||||
) {
|
||||
if ($this->_verbose === true) {
|
||||
$this->log(
|
||||
'Skipped coverage threshold for abstract method "'
|
||||
. $method->getName() . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// store the minimum coverage value for logging (see #466)
|
||||
if ($this->_minMethodCoverageFound !== null) {
|
||||
if ($this->_minMethodCoverageFound > $methodCoverage) {
|
||||
$this->_minMethodCoverageFound = $methodCoverage;
|
||||
}
|
||||
} else {
|
||||
$this->_minMethodCoverageFound = $methodCoverage;
|
||||
}
|
||||
}
|
||||
|
||||
$classStatementCount = count($coverageInformation);
|
||||
$classStatementsCovered = count(
|
||||
array_filter(
|
||||
$coverageInformation,
|
||||
array($this, 'filterCovered')
|
||||
)
|
||||
);
|
||||
|
||||
if ($classStatementCount > 0) {
|
||||
$classCoverage = ( $classStatementsCovered
|
||||
/ $classStatementCount) * 100;
|
||||
} else {
|
||||
$classCoverage = 0;
|
||||
}
|
||||
|
||||
if ($classCoverage < $this->_perClass
|
||||
&& !$reflection->isAbstract()
|
||||
) {
|
||||
throw new BuildException(
|
||||
'The coverage (' . $classCoverage . '%) for class "'
|
||||
. $reflection->getName() . '" is lower than the '
|
||||
. 'specified threshold (' . $this->_perClass . '%), '
|
||||
. 'see file: "' . $filename . '"'
|
||||
);
|
||||
} elseif ($classCoverage < $this->_perClass
|
||||
&& $reflection->isAbstract()
|
||||
) {
|
||||
if ($this->_verbose === true) {
|
||||
$this->log(
|
||||
'Skipped coverage threshold for abstract class "'
|
||||
. $reflection->getName() . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// store the minimum coverage value for logging (see #466)
|
||||
if ($this->_minClassCoverageFound !== null) {
|
||||
if ($this->_minClassCoverageFound > $classCoverage) {
|
||||
$this->_minClassCoverageFound = $classCoverage;
|
||||
}
|
||||
} else {
|
||||
$this->_minClassCoverageFound = $classCoverage;
|
||||
}
|
||||
|
||||
$this->_projectStatementCount += $classStatementCount;
|
||||
$this->_projectStatementsCovered += $classStatementsCovered;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function main()
|
||||
{
|
||||
if ($this->_database === null) {
|
||||
$coverageDatabase = $this->project
|
||||
->getProperty('coverage.database');
|
||||
|
||||
if (! $coverageDatabase) {
|
||||
throw new BuildException(
|
||||
'Either include coverage-setup in your build file or set '
|
||||
. 'the "database" attribute'
|
||||
);
|
||||
}
|
||||
|
||||
$database = new PhingFile($coverageDatabase);
|
||||
} else {
|
||||
$database = $this->_database;
|
||||
}
|
||||
|
||||
$this->log(
|
||||
'Calculating coverage threshold: min. '
|
||||
. $this->_perProject . '% per project, '
|
||||
. $this->_perClass . '% per class and '
|
||||
. $this->_perMethod . '% per method is required'
|
||||
);
|
||||
|
||||
$props = new Properties();
|
||||
$props->load($database);
|
||||
|
||||
foreach ($props->keys() as $filename) {
|
||||
$file = unserialize($props->getProperty($filename));
|
||||
|
||||
$this->calculateCoverageThreshold(
|
||||
$file['fullname'],
|
||||
$file['coverage']
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->_projectStatementCount > 0) {
|
||||
$coverage = ( $this->_projectStatementsCovered
|
||||
/ $this->_projectStatementCount) * 100;
|
||||
} else {
|
||||
$coverage = 0;
|
||||
}
|
||||
|
||||
if ($coverage < $this->_perProject) {
|
||||
throw new BuildException(
|
||||
'The coverage (' . $coverage . '%) for the entire project '
|
||||
. 'is lower than the specified threshold ('
|
||||
. $this->_perProject . '%)'
|
||||
);
|
||||
}
|
||||
|
||||
$this->log(
|
||||
'Passed coverage threshold. Minimum found coverage values are: '
|
||||
. round($coverage, 2) . '% per project, '
|
||||
. round($this->_minClassCoverageFound, 2) . '% per class and '
|
||||
. round($this->_minMethodCoverageFound, 2) . '% per method'
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue