]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Util/Report/Node.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / Util / Report / Node.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.2.0
45  */
46
47 require_once 'PHPUnit/Framework.php';
48 require_once 'PHPUnit/Util/Filter.php';
49 require_once 'PHPUnit/Util/Filesystem.php';
50 require_once 'PHPUnit/Util/Test.php';
51
52 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
53
54 /**
55  * Base class for nodes in the code coverage information tree.
56  *
57  * @category   Testing
58  * @package    PHPUnit
59  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
60  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
61  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
62  * @version    Release: 3.3.17
63  * @link       http://www.phpunit.de/
64  * @since      Class available since Release 3.2.0
65  */
66 abstract class PHPUnit_Util_Report_Node
67 {
68     /**
69      * @var    array
70      */
71     protected $cache = array();
72
73     /**
74      * @var    string
75      */
76     protected $name;
77
78     /**
79      * @var    PHPUnit_Util_Report_Node
80      */
81     protected $parent;
82
83     /**
84      * Constructor.
85      *
86      * @param  string                   $name
87      * @param  PHPUnit_Util_Report_Node $parent
88      */
89     public function __construct($name, PHPUnit_Util_Report_Node $parent = NULL)
90     {
91         $this->name   = $name;
92         $this->parent = $parent;
93     }
94
95     /**
96      * Returns the percentage of classes of which at least one method
97      * has been called at least once..
98      *
99      * @return integer
100      */
101     public function getCalledClassesPercent()
102     {
103         return $this->calculatePercent(
104           $this->getNumCalledClasses(),
105           $this->getNumClasses()
106         );
107     }
108
109     /**
110      * Returns the percentage of methods that has been called at least once.
111      *
112      * @return integer
113      */
114     public function getCalledMethodsPercent()
115     {
116         return $this->calculatePercent(
117           $this->getNumCalledMethods(),
118           $this->getNumMethods()
119         );
120     }
121
122     /**
123      * Returns the percentage of executed lines.
124      *
125      * @return integer
126      */
127     public function getLineExecutedPercent()
128     {
129         return $this->calculatePercent(
130           $this->getNumExecutedLines(),
131           $this->getNumExecutableLines()
132         );
133     }
134
135     /**
136      * Returns this node's ID.
137      *
138      * @return string
139      */
140     public function getId()
141     {
142         if (!isset($this->cache['id'])) {
143             if ($this->parent === NULL) {
144                 $this->cache['id'] = 'index';
145             } else {
146                 $parentId = $this->parent->getId();
147
148                 if ($parentId == 'index') {
149                     $this->cache['id'] = $this->getName();
150                 } else {
151                     $this->cache['id'] = $parentId . '_' . $this->getName();
152                 }
153             }
154         }
155
156         return $this->cache['id'];
157     }
158
159     /**
160      * Returns this node's name.
161      *
162      * @param  boolean $includeParent
163      * @return string
164      */
165     public function getName($includeParent = FALSE, $includeCommonPath = FALSE)
166     {
167         if ($includeParent && $this->parent !== NULL) {
168             if (!isset($this->cache['nameIncludingParent'])) {
169                 $parent = $this->parent->getName(TRUE);
170                 $this->cache['nameIncludingParent'] = !empty($parent) ? $parent . '/' . $this->name : $this->name;
171             }
172
173             return $this->cache['nameIncludingParent'];
174         } else {
175             if ($this->parent !== NULL) {
176                 return $this->name;
177             } else {
178                 return $includeCommonPath ? $this->name : '';
179             }
180         }
181     }
182
183     /**
184      * Returns the link to this node.
185      *
186      * @param  boolean $full
187      * @return string
188      */
189     public function getLink($full)
190     {
191         if (substr($this->name, -1) == DIRECTORY_SEPARATOR) {
192             $name = substr($this->name, 0, -1);
193         } else {
194             $name = $this->name;
195         }
196
197         $cleanId = PHPUnit_Util_Filesystem::getSafeFilename($this->getId());
198
199         if ($full) {
200             if ($this->parent !== NULL) {
201                 $parent = $this->parent->getLink(TRUE) . DIRECTORY_SEPARATOR;
202             } else {
203                 $parent = '';
204             }
205
206             return sprintf(
207               '%s<a href="%s.html">%s</a>',
208               $parent,
209               $cleanId,
210               $name
211             );
212         } else {
213             return sprintf(
214               '<a href="%s.html">%s</a>',
215               $cleanId,
216               $name
217             );
218         }
219     }
220
221     /**
222      * Returns this node's path.
223      *
224      * @return string
225      */
226     public function getPath()
227     {
228         if (!isset($this->cache['path'])) {
229             if ($this->parent === NULL) {
230                 $this->cache['path'] = $this->getName(FALSE, TRUE);
231             } else {
232                 if (substr($this->parent->getPath(), -1) == DIRECTORY_SEPARATOR) {
233                     $this->cache['path'] = $this->parent->getPath() .
234                                            $this->getName(FALSE, TRUE);
235                 } else {
236                     $this->cache['path'] = $this->parent->getPath() .
237                                            DIRECTORY_SEPARATOR .
238                                            $this->getName(FALSE, TRUE);
239
240                     if ($this->parent->getPath() === '' &&
241                         realpath($this->cache['path']) === FALSE &&
242                         realpath($this->getName(FALSE, TRUE)) !== FALSE) {
243                         $this->cache['path'] = $this->getName(FALSE, TRUE);
244                     }
245                 }
246             }
247         }
248
249         return $this->cache['path'];
250     }
251
252     /**
253      * Calculates a percentage value.
254      *
255      * @param  integer $a
256      * @param  integer $b
257      * @return float   ($a / $b) * 100
258      */
259     protected function calculatePercent($a, $b)
260     {
261         if ($b > 0) {
262             $percent = ($a / $b) * 100;
263         } else {
264             $percent = 100;
265         }
266
267         return sprintf(
268           '%01.2F',
269           $percent
270         );
271     }
272
273     protected function doRenderItemObject(PHPUnit_Util_Report_Node $item, $lowUpperBound, $highLowerBound, $link = NULL, $itemClass = 'coverItem')
274     {
275         return $this->doRenderItem(
276           array(
277             'name'                 => $link != NULL ? $link : $item->getLink(FALSE),
278             'itemClass'            => $itemClass,
279             'numClasses'           => $item->getNumClasses(),
280             'numCalledClasses'     => $item->getNumCalledClasses(),
281             'calledClassesPercent' => $item->getCalledClassesPercent(),
282             'numMethods'           => $item->getNumMethods(),
283             'numCalledMethods'     => $item->getNumCalledMethods(),
284             'calledMethodsPercent' => $item->getCalledMethodsPercent(),
285             'numExecutableLines'   => $item->getNumExecutableLines(),
286             'numExecutedLines'     => $item->getNumExecutedLines(),
287             'executedLinesPercent' => $item->getLineExecutedPercent()
288           ),
289           $lowUpperBound,
290           $highLowerBound
291         );
292     }
293
294     protected function doRenderItem(array $data, $lowUpperBound, $highLowerBound, $template = NULL)
295     {
296         if ($template === NULL) {
297             if ($this instanceof PHPUnit_Util_Report_Node_Directory) {
298                 $template = 'directory_item.html';
299             } else {
300                 $template = 'file_item.html';
301             }
302         }
303
304         $itemTemplate = new PHPUnit_Util_Template(
305           PHPUnit_Util_Report::$templatePath . $template
306         );
307
308         if ($data['numClasses'] > 0) {
309             list($classesColor, $classesLevel) = $this->getColorLevel(
310               $data['calledClassesPercent'], $lowUpperBound, $highLowerBound
311             );
312
313             $classesNumber = $data['numCalledClasses'] . ' / ' . $data['numClasses'];
314         } else {
315             $classesColor  = 'snow';
316             $classesLevel  = 'None';
317             $classesNumber = '&nbsp;';
318         }
319
320         if ($data['numMethods'] > 0) {
321             list($methodsColor, $methodsLevel) = $this->getColorLevel(
322               $data['calledMethodsPercent'], $lowUpperBound, $highLowerBound
323             );
324
325             $methodsNumber = $data['numCalledMethods'] . ' / ' . $data['numMethods'];
326         } else {
327             $methodsColor  = 'snow';
328             $methodsLevel  = 'None';
329             $methodsNumber = '&nbsp;';
330         }
331
332         list($linesColor, $linesLevel) = $this->getColorLevel(
333           $data['executedLinesPercent'], $lowUpperBound, $highLowerBound
334         );
335
336         if ($data['name'] == '<b><a href="#0">*</a></b>') {
337             $functions = TRUE;
338         } else {
339             $functions = FALSE;
340         }
341
342         $itemTemplate->setVar(
343           array(
344             'name'                     => $functions ? 'Functions' : $data['name'],
345             'itemClass'                => isset($data['itemClass']) ? $data['itemClass'] : 'coverItem',
346             'classes_color'            => $classesColor,
347             'classes_level'            => $functions ? 'None' : $classesLevel,
348             'classes_called_width'     => floor($data['calledClassesPercent']),
349             'classes_called_percent'   => !$functions && $data['numClasses'] > 0 ? $data['calledClassesPercent'] . '%' : '&nbsp;',
350             'classes_not_called_width' => 100 - floor($data['calledClassesPercent']),
351             'classes_number'           => $functions ? '&nbsp;' : $classesNumber,
352             'methods_color'            => $methodsColor,
353             'methods_level'            => $methodsLevel,
354             'methods_called_width'     => floor($data['calledMethodsPercent']),
355             'methods_called_percent'   => $data['numMethods'] > 0 ? $data['calledMethodsPercent'] . '%' : '&nbsp;',
356             'methods_not_called_width' => 100 - floor($data['calledMethodsPercent']),
357             'methods_number'           => $methodsNumber,
358             'lines_color'              => $linesColor,
359             'lines_level'              => $linesLevel,
360             'lines_executed_width'     => floor($data['executedLinesPercent']),
361             'lines_executed_percent'   => $data['executedLinesPercent'] . '%',
362             'lines_not_executed_width' => 100 - floor($data['executedLinesPercent']),
363             'num_executable_lines'     => $data['numExecutableLines'],
364             'num_executed_lines'       => $data['numExecutedLines']
365           )
366         );
367
368         return $itemTemplate->render();
369     }
370
371     protected function getColorLevel($percent, $lowUpperBound, $highLowerBound)
372     {
373         $floorPercent = floor($percent);
374
375         if ($floorPercent < $lowUpperBound) {
376             $color = 'scarlet_red';
377             $level = 'Lo';
378         }
379
380         else if ($floorPercent >= $lowUpperBound &&
381                  $floorPercent <  $highLowerBound) {
382             $color = 'butter';
383             $level = 'Med';
384         }
385
386         else {
387             $color = 'chameleon';
388             $level = 'Hi';
389         }
390
391         return array($color, $level);
392     }
393
394     protected function renderTotalItem($lowUpperBound, $highLowerBound, $directory = TRUE)
395     {
396         if ($directory && empty($this->directories) && count($this->files) == 1) {
397             return '';
398         }
399
400         return $this->doRenderItemObject($this, $lowUpperBound, $highLowerBound, 'Total') .
401                "        <tr>\n" .
402                '          <td class="tableHead" colspan="10">&nbsp;</td>' . "\n" .
403                "        </tr>\n";
404     }
405
406     /**
407      * @param  PHPUnit_Util_Template $template
408      * @param  string                $title
409      * @param  string                $charset
410      */
411     protected function setTemplateVars(PHPUnit_Util_Template $template, $title, $charset)
412     {
413         $template->setVar(
414           array(
415             'title'                  => $title,
416             'charset'                => $charset,
417             'link'                   => $this->getLink(TRUE),
418             'num_executable_lines'   => $this->getNumExecutableLines(),
419             'num_executed_lines'     => $this->getNumExecutedLines(),
420             'lines_executed_percent' => $this->getLineExecutedPercent(),
421             'date'                   => $template->getDate(),
422             'phpunit_version'        => PHPUnit_Runner_Version::id(),
423             'xdebug_version'         => phpversion('xdebug')
424           )
425         );
426     }
427
428     /**
429      * Returns the classes of this node.
430      *
431      * @return array
432      */
433     abstract public function getClasses();
434
435     /**
436      * Returns the number of executable lines.
437      *
438      * @return integer
439      */
440     abstract public function getNumExecutableLines();
441
442     /**
443      * Returns the number of executed lines.
444      *
445      * @return integer
446      */
447     abstract public function getNumExecutedLines();
448
449     /**
450      * Returns the number of classes.
451      *
452      * @return integer
453      */
454     abstract public function getNumClasses();
455
456     /**
457      * Returns the number of classes of which at least one method
458      * has been called at least once.
459      *
460      * @return integer
461      */
462     abstract public function getNumCalledClasses();
463
464     /**
465      * Returns the number of methods.
466      *
467      * @return integer
468      */
469     abstract public function getNumMethods();
470
471     /**
472      * Returns the number of methods that has been called at least once.
473      *
474      * @return integer
475      */
476     abstract public function getNumCalledMethods();
477
478     /**
479      * Renders this node.
480      *
481      * @param string  $target
482      * @param string  $title
483      * @param string  $charset
484      * @param integer $lowUpperBound
485      * @param integer $highLowerBound
486      */
487     abstract public function render($target, $title, $charset = 'ISO-8859-1', $lowUpperBound = 35, $highLowerBound = 70);
488 }
489 ?>