Chris@0
|
1 <?php
|
Chris@0
|
2 /*
|
Chris@0
|
3 * This file is part of the PHP_CodeCoverage package.
|
Chris@0
|
4 *
|
Chris@0
|
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
|
Chris@0
|
6 *
|
Chris@0
|
7 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
8 * file that was distributed with this source code.
|
Chris@0
|
9 */
|
Chris@0
|
10
|
Chris@0
|
11 /**
|
Chris@0
|
12 * Driver for PHPDBG's code coverage functionality.
|
Chris@0
|
13 *
|
Chris@0
|
14 * @since Class available since Release 2.2.0
|
Chris@0
|
15 * @codeCoverageIgnore
|
Chris@0
|
16 */
|
Chris@0
|
17 class PHP_CodeCoverage_Driver_PHPDBG implements PHP_CodeCoverage_Driver
|
Chris@0
|
18 {
|
Chris@0
|
19 /**
|
Chris@0
|
20 * Constructor.
|
Chris@0
|
21 */
|
Chris@0
|
22 public function __construct()
|
Chris@0
|
23 {
|
Chris@0
|
24 if (PHP_SAPI !== 'phpdbg') {
|
Chris@0
|
25 throw new PHP_CodeCoverage_Exception(
|
Chris@0
|
26 'This driver requires the PHPDBG SAPI'
|
Chris@0
|
27 );
|
Chris@0
|
28 }
|
Chris@0
|
29
|
Chris@0
|
30 if (!function_exists('phpdbg_start_oplog')) {
|
Chris@0
|
31 throw new PHP_CodeCoverage_Exception(
|
Chris@0
|
32 'This build of PHPDBG does not support code coverage'
|
Chris@0
|
33 );
|
Chris@0
|
34 }
|
Chris@0
|
35 }
|
Chris@0
|
36
|
Chris@0
|
37 /**
|
Chris@0
|
38 * Start collection of code coverage information.
|
Chris@0
|
39 */
|
Chris@0
|
40 public function start()
|
Chris@0
|
41 {
|
Chris@0
|
42 phpdbg_start_oplog();
|
Chris@0
|
43 }
|
Chris@0
|
44
|
Chris@0
|
45 /**
|
Chris@0
|
46 * Stop collection of code coverage information.
|
Chris@0
|
47 *
|
Chris@0
|
48 * @return array
|
Chris@0
|
49 */
|
Chris@0
|
50 public function stop()
|
Chris@0
|
51 {
|
Chris@0
|
52 static $fetchedLines = array();
|
Chris@0
|
53
|
Chris@0
|
54 $dbgData = phpdbg_end_oplog();
|
Chris@0
|
55
|
Chris@0
|
56 if ($fetchedLines == array()) {
|
Chris@0
|
57 $sourceLines = phpdbg_get_executable();
|
Chris@0
|
58 } else {
|
Chris@0
|
59 $newFiles = array_diff(
|
Chris@0
|
60 get_included_files(),
|
Chris@0
|
61 array_keys($fetchedLines)
|
Chris@0
|
62 );
|
Chris@0
|
63
|
Chris@0
|
64 if ($newFiles) {
|
Chris@0
|
65 $sourceLines = phpdbg_get_executable(
|
Chris@0
|
66 array('files' => $newFiles)
|
Chris@0
|
67 );
|
Chris@0
|
68 } else {
|
Chris@0
|
69 $sourceLines = array();
|
Chris@0
|
70 }
|
Chris@0
|
71 }
|
Chris@0
|
72
|
Chris@0
|
73 foreach ($sourceLines as $file => $lines) {
|
Chris@0
|
74 foreach ($lines as $lineNo => $numExecuted) {
|
Chris@0
|
75 $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED;
|
Chris@0
|
76 }
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 $fetchedLines = array_merge($fetchedLines, $sourceLines);
|
Chris@0
|
80
|
Chris@0
|
81 return $this->detectExecutedLines($fetchedLines, $dbgData);
|
Chris@0
|
82 }
|
Chris@0
|
83
|
Chris@0
|
84 /**
|
Chris@0
|
85 * Convert phpdbg based data into the format CodeCoverage expects
|
Chris@0
|
86 *
|
Chris@0
|
87 * @param array $sourceLines
|
Chris@0
|
88 * @param array $dbgData
|
Chris@0
|
89 * @return array
|
Chris@0
|
90 */
|
Chris@0
|
91 private function detectExecutedLines(array $sourceLines, array $dbgData)
|
Chris@0
|
92 {
|
Chris@0
|
93 foreach ($dbgData as $file => $coveredLines) {
|
Chris@0
|
94 foreach ($coveredLines as $lineNo => $numExecuted) {
|
Chris@0
|
95 // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown.
|
Chris@0
|
96 // make sure we only mark lines executed which are actually executable.
|
Chris@0
|
97 if (isset($sourceLines[$file][$lineNo])) {
|
Chris@0
|
98 $sourceLines[$file][$lineNo] = self::LINE_EXECUTED;
|
Chris@0
|
99 }
|
Chris@0
|
100 }
|
Chris@0
|
101 }
|
Chris@0
|
102
|
Chris@0
|
103 return $sourceLines;
|
Chris@0
|
104 }
|
Chris@0
|
105 }
|