]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/PHP/CodeCoverage/Report/Node/File.php
Merge branch 'master' of github.com:sugarcrm/sugarcrm_dev
[Github/sugarcrm.git] / tests / PHPUnit / PHP / CodeCoverage / Report / Node / File.php
1 <?php
2 /**
3  * PHP_CodeCoverage
4  *
5  * Copyright (c) 2009-2011, 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   PHP
38  * @package    CodeCoverage
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2009-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42  * @link       http://github.com/sebastianbergmann/php-code-coverage
43  * @since      File available since Release 1.1.0
44  */
45
46 /**
47  * Represents a file in the code coverage information tree.
48  *
49  * @category   PHP
50  * @package    CodeCoverage
51  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
52  * @copyright  2009-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
53  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
54  * @version    Release: 1.1.1
55  * @link       http://github.com/sebastianbergmann/php-code-coverage
56  * @since      Class available since Release 1.1.0
57  */
58 class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
59 {
60     /**
61      * @var array
62      */
63     protected $coverageData;
64
65     /**
66      * @var array
67      */
68     protected $testData;
69
70     /**
71      * @var array
72      */
73     protected $ignoredLines;
74
75     /**
76      * @var integer
77      */
78     protected $numExecutableLines = 0;
79
80     /**
81      * @var integer
82      */
83     protected $numExecutedLines = 0;
84
85     /**
86      * @var array
87      */
88     protected $classes = array();
89
90     /**
91      * @var array
92      */
93     protected $traits = array();
94
95     /**
96      * @var array
97      */
98     protected $functions = array();
99
100     /**
101      * @var array
102      */
103     protected $linesOfCode = array();
104
105     /**
106      * @var integer
107      */
108     protected $numTestedTraits = 0;
109
110     /**
111      * @var integer
112      */
113     protected $numTestedClasses = 0;
114
115     /**
116      * @var integer
117      */
118     protected $numMethods = NULL;
119
120     /**
121      * @var integer
122      */
123     protected $numTestedMethods = NULL;
124
125     /**
126      * @var integer
127      */
128     protected $numTestedFunctions = NULL;
129
130     /**
131      * @var array
132      */
133     protected $startLines = array();
134
135     /**
136      * @var array
137      */
138     protected $endLines = array();
139
140     /**
141      * @var boolean
142      */
143     protected $cacheTokens;
144
145     /**
146      * Constructor.
147      *
148      * @param  string                       $name
149      * @param  PHP_CodeCoverage_Report_Node $parent
150      * @param  array                        $coverageData
151      * @param  array                        $testData
152      * @param  boolean                      $cacheTokens
153      */
154     public function __construct($name, PHP_CodeCoverage_Report_Node $parent, array $coverageData, array $testData, $cacheTokens)
155     {
156         if (!is_bool($cacheTokens)) {
157             throw new InvalidArgumentException;
158         }
159
160         parent::__construct($name, $parent);
161
162         $this->coverageData = $coverageData;
163         $this->testData     = $testData;
164         $this->ignoredLines = PHP_CodeCoverage_Util::getLinesToBeIgnored(
165                                 $this->getPath(), $cacheTokens
166                               );
167         $this->cacheTokens  = $cacheTokens;
168
169         $this->calculateStatistics();
170     }
171
172     /**
173      * Returns the number of files in/under this node.
174      *
175      * @return integer
176      */
177     public function count()
178     {
179         return 1;
180     }
181
182     /**
183      * Returns the code coverage data of this node.
184      *
185      * @return array
186      */
187     public function getCoverageData()
188     {
189         return $this->coverageData;
190     }
191
192     /**
193      * Returns the test data of this node.
194      *
195      * @return array
196      */
197     public function getTestData()
198     {
199         return $this->testData;
200     }
201
202     /**
203      * @return array
204      */
205     public function getIgnoredLines()
206     {
207         return $this->ignoredLines;
208     }
209
210     /**
211      * Returns the classes of this node.
212      *
213      * @return array
214      */
215     public function getClasses()
216     {
217         return $this->classes;
218     }
219
220     /**
221      * Returns the traits of this node.
222      *
223      * @return array
224      */
225     public function getTraits()
226     {
227         return $this->traits;
228     }
229
230     /**
231      * Returns the functions of this node.
232      *
233      * @return array
234      */
235     public function getFunctions()
236     {
237         return $this->functions;
238     }
239
240     /**
241      * Returns the LOC/CLOC/NCLOC of this node.
242      *
243      * @return array
244      */
245     public function getLinesOfCode()
246     {
247         return $this->linesOfCode;
248     }
249
250     /**
251      * Returns the number of executable lines.
252      *
253      * @return integer
254      */
255     public function getNumExecutableLines()
256     {
257         return $this->numExecutableLines;
258     }
259
260     /**
261      * Returns the number of executed lines.
262      *
263      * @return integer
264      */
265     public function getNumExecutedLines()
266     {
267         return $this->numExecutedLines;
268     }
269
270     /**
271      * Returns the number of classes.
272      *
273      * @return integer
274      */
275     public function getNumClasses()
276     {
277         return count($this->classes);
278     }
279
280     /**
281      * Returns the number of tested classes.
282      *
283      * @return integer
284      */
285     public function getNumTestedClasses()
286     {
287         return $this->numTestedClasses;
288     }
289
290     /**
291      * Returns the number of traits.
292      *
293      * @return integer
294      */
295     public function getNumTraits()
296     {
297         return count($this->traits);
298     }
299
300     /**
301      * Returns the number of tested traits.
302      *
303      * @return integer
304      */
305     public function getNumTestedTraits()
306     {
307         return $this->numTestedTraits;
308     }
309
310     /**
311      * Returns the number of methods.
312      *
313      * @return integer
314      */
315     public function getNumMethods()
316     {
317         if ($this->numMethods === NULL) {
318             $this->numMethods = 0;
319
320             foreach ($this->classes as $class) {
321                 foreach ($class['methods'] as $method) {
322                     if ($method['executableLines'] > 0) {
323                         $this->numMethods++;
324                     }
325                 }
326             }
327
328             foreach ($this->traits as $trait) {
329                 foreach ($trait['methods'] as $method) {
330                     if ($method['executableLines'] > 0) {
331                         $this->numMethods++;
332                     }
333                 }
334             }
335         }
336
337         return $this->numMethods;
338     }
339
340     /**
341      * Returns the number of tested methods.
342      *
343      * @return integer
344      */
345     public function getNumTestedMethods()
346     {
347         if ($this->numTestedMethods === NULL) {
348             $this->numTestedMethods = 0;
349
350             foreach ($this->classes as $class) {
351                 foreach ($class['methods'] as $method) {
352                     if ($method['executableLines'] > 0 &&
353                         $method['coverage'] == 100) {
354                         $this->numTestedMethods++;
355                     }
356                 }
357             }
358
359             foreach ($this->traits as $trait) {
360                 foreach ($trait['methods'] as $method) {
361                     if ($method['executableLines'] > 0 &&
362                         $method['coverage'] == 100) {
363                         $this->numTestedMethods++;
364                     }
365                 }
366             }
367         }
368
369         return $this->numTestedMethods;
370     }
371
372     /**
373      * Returns the number of functions.
374      *
375      * @return integer
376      */
377     public function getNumFunctions()
378     {
379         return count($this->functions);
380     }
381
382     /**
383      * Returns the number of tested functions.
384      *
385      * @return integer
386      */
387     public function getNumTestedFunctions()
388     {
389         if ($this->numTestedFunctions === NULL) {
390             $this->numTestedFunctions = 0;
391
392             foreach ($this->functions as $function) {
393                 if ($function['executableLines'] > 0 &&
394                     $function['coverage'] == 100) {
395                     $this->numTestedFunctions++;
396                 }
397             }
398         }
399
400         return $this->numTestedFunctions;
401     }
402
403     /**
404      * Calculates coverage statistics for the file.
405      */
406     protected function calculateStatistics()
407     {
408         if ($this->cacheTokens) {
409             $tokens = PHP_Token_Stream_CachingFactory::get($this->getPath());
410         } else {
411             $tokens = new PHP_Token_Stream($this->getPath());
412         }
413
414         $this->processClasses($tokens);
415         $this->processTraits($tokens);
416         $this->processFunctions($tokens);
417         $this->linesOfCode = $tokens->getLinesOfCode();
418         unset($tokens);
419
420         for ($lineNumber = 1; $lineNumber <= $this->linesOfCode['loc']; $lineNumber++) {
421             if (isset($this->startLines[$lineNumber])) {
422                 // Start line of a class.
423                 if (isset($this->startLines[$lineNumber]['className'])) {
424                     $currentClass = &$this->startLines[$lineNumber];
425                 }
426
427                 // Start line of a trait.
428                 else if (isset($this->startLines[$lineNumber]['traitName'])) {
429                     $currentTrait = &$this->startLines[$lineNumber];
430                 }
431
432                 // Start line of a method.
433                 else if (isset($this->startLines[$lineNumber]['methodName'])) {
434                     $currentMethod = &$this->startLines[$lineNumber];
435                 }
436
437                 // Start line of a function.
438                 else if (isset($this->startLines[$lineNumber]['functionName'])) {
439                     $currentFunction = &$this->startLines[$lineNumber];
440                 }
441             }
442
443             if (!isset($this->ignoredLines[$lineNumber]) &&
444                 isset($this->coverageData[$lineNumber]) &&
445                 $this->coverageData[$lineNumber] !== NULL) {
446                 if (isset($currentClass)) {
447                     $currentClass['executableLines']++;
448                 }
449
450                 if (isset($currentTrait)) {
451                     $currentTrait['executableLines']++;
452                 }
453
454                 if (isset($currentMethod)) {
455                     $currentMethod['executableLines']++;
456                 }
457
458                 if (isset($currentFunction)) {
459                     $currentFunction['executableLines']++;
460                 }
461
462                 $this->numExecutableLines++;
463
464                 if (count($this->coverageData[$lineNumber]) > 0 ||
465                     isset($this->ignoredLines[$lineNumber])) {
466                     if (isset($currentClass)) {
467                         $currentClass['executedLines']++;
468                     }
469
470                     if (isset($currentTrait)) {
471                         $currentTrait['executedLines']++;
472                     }
473
474                     if (isset($currentMethod)) {
475                         $currentMethod['executedLines']++;
476                     }
477
478                     if (isset($currentFunction)) {
479                         $currentFunction['executedLines']++;
480                     }
481
482                     $this->numExecutedLines++;
483                 }
484             }
485
486             if (isset($this->endLines[$lineNumber])) {
487                 // End line of a class.
488                 if (isset($this->endLines[$lineNumber]['className'])) {
489                     unset($currentClass);
490                 }
491
492                 // End line of a trait.
493                 else if (isset($this->endLines[$lineNumber]['traitName'])) {
494                     unset($currentTrait);
495                 }
496
497                 // End line of a method.
498                 else if (isset($this->endLines[$lineNumber]['methodName'])) {
499                     unset($currentMethod);
500                 }
501
502                 // End line of a function.
503                 else if (isset($this->endLines[$lineNumber]['functionName'])) {
504                     unset($currentFunction);
505                 }
506             }
507         }
508
509         foreach ($this->traits as $traitName => &$trait) {
510             foreach ($trait['methods'] as &$method) {
511                 if ($method['executableLines'] > 0) {
512                     $method['coverage'] = ($method['executedLines'] /
513                                            $method['executableLines']) * 100;
514                 } else {
515                     $method['coverage'] = 100;
516                 }
517
518                 $method['crap'] = PHP_CodeCoverage_Util::crap(
519                   $method['ccn'], $method['coverage']
520                 );
521
522                 $trait['ccn'] += $method['ccn'];
523             }
524
525             if ($trait['executableLines'] > 0) {
526                 $trait['coverage'] = ($trait['executedLines'] /
527                                       $trait['executableLines']) * 100;
528             } else {
529                 $trait['coverage'] = 100;
530             }
531
532             if ($trait['coverage'] == 100) {
533                 $this->numTestedClasses++;
534             }
535
536             $trait['crap'] = PHP_CodeCoverage_Util::crap(
537               $trait['ccn'], $trait['coverage']
538             );
539         }
540
541         foreach ($this->classes as $className => &$class) {
542             foreach ($class['methods'] as &$method) {
543                 if ($method['executableLines'] > 0) {
544                     $method['coverage'] = ($method['executedLines'] /
545                                            $method['executableLines']) * 100;
546                 } else {
547                     $method['coverage'] = 100;
548                 }
549
550                 $method['crap'] = PHP_CodeCoverage_Util::crap(
551                   $method['ccn'], $method['coverage']
552                 );
553
554                 $class['ccn'] += $method['ccn'];
555             }
556
557             if ($class['executableLines'] > 0) {
558                 $class['coverage'] = ($class['executedLines'] /
559                                       $class['executableLines']) * 100;
560             } else {
561                 $class['coverage'] = 100;
562             }
563
564             if ($class['coverage'] == 100) {
565                 $this->numTestedClasses++;
566             }
567
568             $class['crap'] = PHP_CodeCoverage_Util::crap(
569               $class['ccn'], $class['coverage']
570             );
571         }
572     }
573
574     /**
575      * @param PHP_Token_Stream $tokens
576      */
577     protected function processClasses(PHP_Token_Stream $tokens)
578     {
579         $classes = $tokens->getClasses();
580         unset($tokens);
581
582         $link = $this->getId() . '.html#';
583
584         foreach ($classes as $className => $class) {
585             $this->classes[$className] = array(
586               'className'       => $className,
587               'methods'         => array(),
588               'startLine'       => $class['startLine'],
589               'executableLines' => 0,
590               'executedLines'   => 0,
591               'ccn'             => 0,
592               'coverage'        => 0,
593               'crap'            => 0,
594               'package'         => $class['package'],
595               'link'            => $link . $class['startLine']
596             );
597
598             $this->startLines[$class['startLine']] = &$this->classes[$className];
599             $this->endLines[$class['endLine']]     = &$this->classes[$className];
600
601             foreach ($class['methods'] as $methodName => $method) {
602                 $this->classes[$className]['methods'][$methodName] = array(
603                   'methodName'      => $methodName,
604                   'signature'       => $method['signature'],
605                   'startLine'       => $method['startLine'],
606                   'endLine'         => $method['endLine'],
607                   'executableLines' => 0,
608                   'executedLines'   => 0,
609                   'ccn'             => $method['ccn'],
610                   'coverage'        => 0,
611                   'crap'            => 0,
612                   'link'            => $link . $method['startLine']
613                 );
614
615                 $this->startLines[$method['startLine']] = &$this->classes[$className]['methods'][$methodName];
616                 $this->endLines[$method['endLine']]     = &$this->classes[$className]['methods'][$methodName];
617             }
618         }
619     }
620
621     /**
622      * @param PHP_Token_Stream $tokens
623      */
624     protected function processTraits(PHP_Token_Stream $tokens)
625     {
626         $traits = $tokens->getTraits();
627         unset($tokens);
628
629         $link = $this->getId() . '.html#';
630
631         foreach ($traits as $traitName => $trait) {
632             $this->traits[$traitName] = array(
633               'traitName'       => $traitName,
634               'methods'         => array(),
635               'startLine'       => $trait['startLine'],
636               'executableLines' => 0,
637               'executedLines'   => 0,
638               'ccn'             => 0,
639               'coverage'        => 0,
640               'crap'            => 0,
641               'package'         => $trait['package'],
642               'link'            => $link . $trait['startLine']
643             );
644
645             $this->startLines[$trait['startLine']] = &$this->traits[$traitName];
646             $this->endLines[$trait['endLine']]     = &$this->traits[$traitName];
647
648             foreach ($trait['methods'] as $methodName => $method) {
649                 $this->traits[$traitName]['methods'][$methodName] = array(
650                   'methodName'      => $methodName,
651                   'signature'       => $method['signature'],
652                   'startLine'       => $method['startLine'],
653                   'executableLines' => 0,
654                   'executedLines'   => 0,
655                   'ccn'             => $method['ccn'],
656                   'coverage'        => 0,
657                   'crap'            => 0,
658                   'link'            => $link . $method['startLine']
659                 );
660
661                 $this->startLines[$method['startLine']] = &$this->traits[$traitName]['methods'][$methodName];
662                 $this->endLines[$method['endLine']]     = &$this->traits[$traitName]['methods'][$methodName];
663             }
664         }
665     }
666
667     /**
668      * @param PHP_Token_Stream $tokens
669      */
670     protected function processFunctions(PHP_Token_Stream $tokens)
671     {
672         $functions = $tokens->getFunctions();
673         unset($tokens);
674
675         $link = $this->getId() . '.html#';
676
677         foreach ($functions as $functionName => $function) {
678             $this->functions[$functionName] = array(
679               'functionName'    => $functionName,
680               'signature'       => $function['signature'],
681               'startLine'       => $function['startLine'],
682               'executableLines' => 0,
683               'executedLines'   => 0,
684               'ccn'             => $function['ccn'],
685               'coverage'        => 0,
686               'crap'            => 0,
687               'link'            => $link . $function['startLine']
688             );
689
690             $this->startLines[$function['startLine']] = &$this->functions[$functionName];
691             $this->endLines[$function['endLine']]     = &$this->functions[$functionName];
692         }
693     }
694 }