]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Util/CodeCoverage.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / Util / CodeCoverage.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @category   Testing
38  * @package    PHPUnit
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
43  * @link       http://www.phpunit.de/
44  * @since      File available since Release 3.1.0
45  */
46
47 require_once 'PHPUnit/Util/Filter.php';
48
49 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
50
51 /**
52  * Code Coverage helpers.
53  *
54  * @category   Testing
55  * @package    PHPUnit
56  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
57  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
58  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
59  * @version    Release: 3.3.17
60  * @link       http://www.phpunit.de/
61  * @since      Class available since Release 3.1.0
62  * @abstract
63  */
64 abstract class PHPUnit_Util_CodeCoverage
65 {
66     protected static $lineToTestMap = array();
67     protected static $summary = array();
68
69     /**
70      * Returns only the executed lines.
71      *
72      * @param  array $data
73      * @return array
74      * @since  Method available since Release 3.3.15
75      */
76     public static function getExecutedLines(array $data)
77     {
78         return self::getLinesByStatus($data, 1);
79     }
80
81     /**
82      * Returns only the executable lines.
83      *
84      * @param  array $data
85      * @return array
86      * @since  Method available since Release 3.3.15
87      */
88     public static function getExecutableLines(array $data)
89     {
90         return self::getLinesByStatus($data, array(-1, 1));
91     }
92
93     /**
94      * Returns only the lines that were not executed.
95      *
96      * @param  array $data
97      * @return array
98      * @since  Method available since Release 3.3.15
99      */
100     public static function getNotExecutedLines(array $data)
101     {
102         return self::getLinesByStatus($data, -1);
103     }
104
105     /**
106      * Returns only the dead code lines.
107      *
108      * @param  array $data
109      * @return array
110      * @since  Method available since Release 3.3.15
111      */
112     public static function getDeadLines(array $data)
113     {
114         return self::getLinesByStatus($data, -2);
115     }
116
117     /**
118      * Filters lines by status.
119      *
120      * @param  array         $data
121      * @param  array|integer $status
122      * @return array
123      * @since  Method available since Release 3.3.15
124      */
125     protected static function getLinesByStatus(array $data, $status)
126     {
127         if (!is_array($status)) {
128             $status = array($status);
129         }
130
131         $isFileCache = array();
132         $result      = array();
133
134         foreach ($data as $file => $coverage) {
135             if (!isset($isFileCache[$file])) {
136                 $isFileCache[$file] = self::isFile($file);
137             }
138
139             if (!$isFileCache[$file]) {
140                 continue;
141             }
142
143             $result[$file] = array();
144
145             foreach ($coverage as $line => $_status) {
146                 if (in_array($_status, $status)) {
147                     $result[$file][$line] = $_status;
148                 }
149             }
150         }
151
152         return $result;
153     }
154
155     /**
156      * Returns the tests that cover a given line.
157      *
158      * @param  array   $data
159      * @param  string  $file
160      * @param  string  $line
161      * @param  boolean $clear
162      * @return array
163      */
164     public static function getCoveringTests(array &$data, $file, $line, $clear = FALSE)
165     {
166         if (empty(self::$lineToTestMap) || $clear) {
167             foreach ($data as $test) {
168                 foreach ($test['files'] as $_file => $lines) {
169                     foreach ($lines as $_line => $flag) {
170                         if ($flag > 0) {
171                             if (!isset(self::$lineToTestMap[$_file][$_line])) {
172                                 self::$lineToTestMap[$_file][$_line] = array($test['test']);
173                             } else {
174                                 self::$lineToTestMap[$_file][$_line][] = $test['test'];
175                             }
176                         }
177                     }
178                 }
179             }
180         }
181
182         if (isset(self::$lineToTestMap[$file][$line])) {
183             return self::$lineToTestMap[$file][$line];
184         } else {
185             return FALSE;
186         }
187     }
188
189     /**
190      * Returns summarized code coverage data.
191      *
192      * Format of the result array:
193      *
194      * <code>
195      * array(
196      *   "/tested/code.php" => array(
197      *     linenumber => number of tests that executed the line
198      *   )
199      * )
200      * </code>
201      *
202      * @param  array $data
203      * @param  boolean $clear
204      * @return array
205      */
206     public static function getSummary(array &$data, $clear = FALSE)
207     {
208         if (empty(self::$summary) || $clear) {
209             foreach ($data as $test) {
210                 foreach ($test['files'] as $file => $lines) {
211                     foreach ($lines as $line => $flag) {
212                         if ($flag == 1) {
213                             if (isset(self::$summary[$file][$line][0])) {
214                                 self::$summary[$file][$line][] = $test['test'];
215                             } else {
216                                 self::$summary[$file][$line] = array($test['test']);
217                             }
218                         }
219
220                         else if (!isset(self::$summary[$file][$line])) {
221                             self::$summary[$file][$line] = $flag;
222                         }
223                     }
224                 }
225
226                 if (isset($test['executable'])) {
227                     foreach ($test['executable'] as $file => $lines) {
228                         foreach ($lines as $line => $flag) {
229                             if ($flag == 1 && !isset(self::$summary[$file][$line][0])) {
230                                 self::$summary[$file][$line] = -1;
231                             }
232
233                             else if (!isset(self::$summary[$file][$line])) {
234                                 self::$summary[$file][$line] = $flag;
235                             }
236                         }
237                     }
238                 }
239
240                 if (isset($test['dead'])) {
241                     foreach ($test['dead'] as $file => $lines) {
242                         foreach ($lines as $line => $flag) {
243                             if ($flag == -2 && !isset(self::$summary[$file][$line][0])) {
244                                 self::$summary[$file][$line] = -2;
245                             }
246                         }
247                     }
248                 }
249             }
250         }
251
252         return self::$summary;
253     }
254
255     /**
256      * Returns the coverage statistics for a section of a file.
257      *
258      * @param  array   $data
259      * @param  string  $filename
260      * @param  integer $startLine
261      * @param  integer $endLine
262      * @return array
263      * @since  Method available since Release 3.2.0
264      */
265     public static function getStatistics(array &$data, $filename, $startLine = 1, $endLine = FALSE)
266     {
267         $coverage      = 0;
268         $locExecutable = 0;
269         $locExecuted   = 0;
270
271         if (isset($data[$filename])) {
272             if ($endLine == FALSE) {
273                 $endLine = count(file($filename));
274             }
275
276             foreach ($data[$filename] as $line => $_data) {
277                 if ($line >= $startLine && $line < $endLine) {
278                     if (is_array($_data)) {
279                         $locExecutable++;
280                         $locExecuted++;
281                     }
282
283                     else if ($_data == -1) {
284                         $locExecutable++;
285                     }
286                 }
287             }
288
289             if ($locExecutable > 0) {
290                 $coverage = ($locExecuted / $locExecutable) * 100;
291             } else {
292                 $coverage = 100;
293             }
294         }
295
296         return array(
297           'coverage'      => $coverage,
298           'loc'           => $endLine - $startLine + 1,
299           'locExecutable' => $locExecutable,
300           'locExecuted'   => $locExecuted
301         );
302     }
303
304     /**
305      * Checks whether a file (as seen by Xdebug) is actually a file.
306      *
307      * @param  string $file
308      * @return boolean
309      */
310     public static function isFile($file)
311     {
312         if (strpos($file, 'eval()\'d code') ||
313             strpos($file, 'runtime-created function') ||
314             strpos($file, 'assert code') ||
315             strpos($file, 'regexp code')) {
316             return FALSE;
317         }
318
319         return TRUE;
320     }
321
322     /**
323      * Clears the cached summary information.
324      *
325      * @since  Method available since Release 3.3.0
326      */
327     public static function clearSummary()
328     {
329         self::$summary = array();
330     }
331 }
332 ?>