cc.php 10.2 KB
Newer Older
meus's avatar
meus committed
1
<?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 *  $Id: Doctrine.php 1976 2007-07-11 22:03:47Z zYne $
 *
 * 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, see
 * <http://www.phpdoctrine.com>.
 */

meus's avatar
meus committed
22 23 24
require_once dirname(__FILE__) . '/../lib/Doctrine.php';
spl_autoload_register(array('Doctrine', 'autoload'));

25 26 27 28 29 30 31 32 33
$reporter = new Doctrine_Coverage_Report("coverage.txt");
?>
<html>
<head>
<style type="text/css">
    .covered{ background: green;}
    .normal{ background: white;}
    .red{ background: red;}
    .orange{ background: #f90;}
meus's avatar
meus committed
34

35 36 37 38 39
 dl.table-display
{
margin: 2em 0;
padding: 0;
font-family: georgia, times, serif;
meus's avatar
meus committed
40 41
}

42 43 44 45 46 47
.table-display dt
{
float: left;
margin: 0 0 0 0;
padding: 0 .5em 0 .5em;
}
meus's avatar
meus committed
48

49 50 51
/* commented backslash hack for mac-ie5 \*/
dt { clear: both; }
/* end hack */
meus's avatar
meus committed
52

53 54 55 56 57 58 59 60
.table-display dd{
    float: left;
    margin: 0 0 0 0;
    }
</style>
</head>
<body>
<?php
meus's avatar
meus committed
61

62
if (isset($_GET["file"])){
63 64 65
    echo '<h1>Coverage for ' . $_GET["file"] . '</h1>';
    echo '<a href="cc.php">Back to coverage report</a>';
    $reporter->showFile($_GET["file"]);
66
} else {
meus's avatar
meus committed
67
?>
68
    <h1>Coverage report for Doctrine</h1>
meus's avatar
meus committed
69
    <p>Default mode shows results sorted by percentage. This can be changed with GET variables:<br /> <ul><li>order = covered|total|maybe|notcovered|percentage</li><li>desc=true</li></ul></p>
70 71
    <table>
     <tr><th></th><th>Percentage</th><th>Total</th><th>Covered</th><th>Maybe</th><th>Not Covered</th><th></th></tr>
meus's avatar
meus committed
72
<?php
73 74
    $reporter->showSummary();
    echo "</table>";
meus's avatar
meus committed
75
}
76 77 78 79 80
?>
</body>
</html>

<?php
81 82 83
/**
 * Doctrine
 * the base class of Doctrine framework
84
 *
85 86 87 88 89 90 91
 * @package     Doctrine
 * @author      Bjarte S. Karlsen <bjartka@pvv.ntnu.no>
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @category    Object Relational Mapping
 * @link        www.phpdoctrine.com
 * @since       1.0
 * @version     $Revision: 1976 $
92 93 94 95
 */
class Doctrine_Coverage_Report
{

96 97 98 99
    const COVERED = 1;
    const MAYBE = -2;
    const NOTCOVERED = -1;

100 101 102 103
    private $path;
    private $coverage;
    private $key;
    private $covered;
104 105 106 107
    private $totallines = 0;
    private $totalcovered = 0;
    private $totalmaybe = 0;
    private $totalnotcovered = 0;
108

109 110 111 112 113 114
    /*
     * Create a new coverage report
     *
     * @param string $file The name of the file where coverage data is stored
     *
     */
115 116 117 118 119 120 121
    public function __construct($file)
    {
        $result = unserialize(file_get_contents("coverage.txt"));
        $this->path = $result["path"];
        $this->coverage = $result["coverage"];

        $this->sortBy ="percentage"; // default sort
meus's avatar
meus committed
122 123
    }

124 125 126 127 128
    /*
     * Show graphical coverage report for a file
     *
     * @param string $fileName The name of the file to show
     */
129 130 131 132
    public function showFile($fileName)
    {
        $key = $this->path . $fileName;
        $html = '<div id="coverage">';
133
        if (!isset( $this->coverage[$key]))
134
        {
135
            echo '<h2>This file has not been tested!</h2>';
136 137 138 139
        }
        $coveredLines = $this->coverage[$key];
        $fileArray = file(Doctrine::getPath() . "/".$fileName);
        $html .= '<dl class="table-display">' . "\n";
140
        foreach ($fileArray as $num => $line){
141 142 143
            $linenum = $num+1;
            $html .= '<dt>' . $linenum . '</dt>' . "\n";
            $class ="normal";
144
            if (isset($coveredLines[$linenum]) && $coveredLines[$linenum] == 1){
145
                $class = "covered";
146
            } else if (isset($coveredLines[$linenum]) && $coveredLines[$linenum] == -1) {
147
                $class ="red";
148
            } else if (isset($coveredLines[$linenum]) && $coveredLines[$linenum] == -2) {
149 150 151 152 153 154 155 156
                $class ="orange";
            }
            $html .= '<dd class="' . $class . '">' . htmlspecialchars($line) . '</dd>' . "\n";
        }
        $html .='</dl></div>';
        echo $html;
    }

157 158 159 160 161 162 163 164
    /*
     * Generate coverage data for non tested files
     *
     * Scans all files and records data for those that are not in the coverage 
     * record.
     *
     * @return array An array with coverage data
     */
165 166 167 168 169
    public function generateNotCoveredFiles()
    {
        $it = new RecursiveDirectoryIterator(Doctrine::getPath());

        $notCoveredArray = array();
170 171
        foreach (new RecursiveIteratorIterator($it) as $file){
            if (strpos($file->getPathname(), ".svn")){
172 173
                continue;
            }
meus's avatar
meus committed
174
            $path = Doctrine::getPath() . DIRECTORY_SEPARATOR;
175
            $coveredPath = str_replace($path, $this->path, $file->getPathname());
176
            if (isset($this->coverage[$coveredPath])){
177
                continue;
178
            }
179

180 181 182
            $class = str_replace($path, "", $file->getPathname());
            $class = str_replace(DIRECTORY_SEPARATOR, "_", $class);
            $class = substr($class, 0,-4);
183 184 185 186
            if (strpos($class, '_Interface')) {
                continue;
            }

187
            if ( ! class_exists($class)){
188 189 190 191 192
                continue;
            }

            try{
                $refClass = new ReflectionClass($class);
193
            } catch (Exception $e){
194 195 196 197 198
                echo $e->getMessage();
                continue;
            }
            $lines = 0;
            $methodLines = 0;
199
            foreach ($refClass->getMethods() as $refMethod){
200

201
                if ($refMethod->getDeclaringClass() != $refClass){
202 203 204 205 206
                    continue;
                }
                $methodLines = $refMethod->getEndLine() - $refMethod->getStartLine();
                $lines += $methodLines;
            }
207
            if ($methodLines == 0){
208
                $notCoveredArray[$class] = array("covered" => 0, "maybe" => 0, "notcovered"=>$lines, "total" => $lines, "percentage" => 100);
209
            } else {
210
                $notCoveredArray[$class] = array("covered" => 0, "maybe" => 0, "notcovered"=>$lines, "total" => $lines, "percentage" => 0);
211
            }
212 213 214 215 216 217
            $this->totallines += $lines;
            $this->totalnotcovered += $lines;
        }
        return $notCoveredArray;
    }

218 219 220 221 222 223
    /*
     * Show a summary of all files in Doctrine and their coverage data
     *
     * @uses generateNonCoveredFiles
     * @uses generateCoverage
     */
224 225
    public function showSummary()
    {
226
        if (isset($_GET["order"])){
227 228
            $this->sortBy = $_GET["order"];
        }
229 230 231 232 233 234 235 236
        $coveredArray = $this->generateCoverage();
        $notcoveredArray = $this->generateNotCoveredFiles();
        $coveredArray = array_merge($coveredArray, $notcoveredArray);

        //lets sort it.
        uasort($coveredArray, array($this,"sortArray"));

        //and flip if it perhaps?
237
        if (isset($_GET["desc"]) && $_GET["desc"] == "true"){
238 239 240 241 242 243 244 245 246 247
            $coveredArray = array_reverse($coveredArray, true);
        }

        //ugly code to print out the result:
        echo "<tr><td>" . TOTAL . "</td><td>" . round((($this->totalcovered + $this->totalmaybe) / $this->totallines) * 100, 2) . " % </td><td>$this->totallines</td><td>$this->totalcovered</td><td>$this->totalmaybe</td><td>$this->totalnotcovered</td><td></td></tr>";
        foreach($coveredArray as $class => $info){
            $fileName = str_replace("_", "/", $class) . ".php";
            echo "<tr><td>" . $class . "</td><td>" . $info["percentage"] . " % </td><td>" . $info["total"] . "</td><td>" . $info["covered"] . "</td><td>" . $info["maybe"] . "</td><td>" . $info["notcovered"]. "</td><td><a href=\"cc.php?file=" . $fileName . "\">coverage</a></td></tr>";
        }
    }
248

249 250 251 252 253
    /*
     * Generate coverage data for tested files
     *
     *@return array An array of coverage data
     */
254 255
    public function generateCoverage()
    {
256 257 258
        $coveredArray = array();
        foreach ($this->coverage as $file => $lines) {
            $pos = strpos($file, $this->path);
259
            if ($pos === false && $pos !== 0){
260 261 262 263 264 265 266 267 268
                continue;
            }

            $class = str_replace(DIRECTORY_SEPARATOR, '_', substr($file, strlen($this->path), -4));
            $class = str_replace($this->path, Doctrine::getPath(), $class); 
            if (strpos($class, '_Interface')) {
                continue;
            }

269
            if ( ! class_exists($class)){
270 271 272 273 274 275 276
                continue;
            }

            $total = count($lines) -1; //we have to remove one since it always reports the last line as a hit
            $covered = 0;
            $maybe = 0;
            $notcovered = 0;
277
            foreach ($lines as $result){
278
                switch($result){
279
                case self::COVERED:
280 281
                    $covered++;
                    break;
282
                case self::NOTCOVERED:
283 284
                    $notcovered++;
                    break;
285
                case self::MAYBE:
286 287 288 289 290
                    $maybe++;
                    break;
                }
            }
            $covered--; //again we have to remove that last line.
291 292 293 294
            $this->totallines += $total;
            $this->totalcovered += $covered;
            $this->totalnotcovered += $notcovered;
            $this->totalmaybe += $maybe;
meus's avatar
meus committed
295

296 297 298 299 300 301
            if ($total === 0) {
                $total = 1;
            }
            $percentage = round((($covered + $maybe) / $total) * 100, 2);
            $coveredArray[$class] = array("covered" => $covered, "maybe" => $maybe, "notcovered"=>$notcovered, "total" => $total, "percentage" => $percentage);
        }
302
        return $coveredArray;
303 304
    }

305 306 307 308
   /*
    * Uasort function to sort the array by key
    *
    */
309 310 311 312 313
    public function sortArray($a, $b)
    {
        if ($a[$this->sortBy] == $b[$this->sortBy]) {
            return 0;
        }
314
        return ( $a[$this->sortBy] < $b[$this->sortBy]) ? -1 : 1;
meus's avatar
meus committed
315 316
    }
}
317