| 1 |
lars |
1 |
<?php
|
|
|
2 |
/**
|
|
|
3 |
* PHPUnit
|
|
|
4 |
*
|
|
|
5 |
* Copyright (c) 2002-2010, 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-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
|
|
|
41 |
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
|
|
42 |
* @link http://www.phpunit.de/
|
|
|
43 |
* @since File available since Release 3.3.0
|
|
|
44 |
*/
|
|
|
45 |
|
|
|
46 |
require_once 'PHPUnit/Runner/Version.php';
|
|
|
47 |
require_once 'PHPUnit/Util/Class.php';
|
|
|
48 |
require_once 'PHPUnit/Util/CodeCoverage.php';
|
|
|
49 |
require_once 'PHPUnit/Util/Filter.php';
|
|
|
50 |
require_once 'PHPUnit/Util/XML.php';
|
|
|
51 |
|
|
|
52 |
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
|
|
|
53 |
|
|
|
54 |
/**
|
|
|
55 |
* Writes one XML file per covered PHP source file to a given directory.
|
|
|
56 |
* Each <line> element holds a line of PHP sourcecode that is annotated with
|
|
|
57 |
* code coverage information.
|
|
|
58 |
*
|
|
|
59 |
* @category Testing
|
|
|
60 |
* @package PHPUnit
|
|
|
61 |
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
|
|
|
62 |
* @copyright 2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
|
|
|
63 |
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
|
|
64 |
* @version Release: 3.4.15
|
|
|
65 |
* @link http://www.phpunit.de/
|
|
|
66 |
* @since Class available since Release 3.3.0
|
|
|
67 |
*/
|
|
|
68 |
class PHPUnit_Util_Log_CodeCoverage_XML_Source
|
|
|
69 |
{
|
|
|
70 |
protected $directory;
|
|
|
71 |
|
|
|
72 |
/**
|
|
|
73 |
* @param string $directory
|
|
|
74 |
*/
|
|
|
75 |
public function __construct($directory)
|
|
|
76 |
{
|
|
|
77 |
$this->directory = PHPUnit_Util_Filesystem::getDirectory($directory);
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
/**
|
|
|
81 |
* @param PHPUnit_Framework_TestResult $result
|
|
|
82 |
*/
|
|
|
83 |
public function process(PHPUnit_Framework_TestResult $result)
|
|
|
84 |
{
|
|
|
85 |
$sutData = $result->getCodeCoverageInformation();
|
|
|
86 |
$sutFiles = PHPUnit_Util_CodeCoverage::getSummary($sutData, TRUE);
|
|
|
87 |
$allData = $result->getCodeCoverageInformation(FALSE);
|
|
|
88 |
$allFiles = PHPUnit_Util_CodeCoverage::getSummary($allData, TRUE);
|
|
|
89 |
$testFiles = array_diff(array_keys($allFiles), array_keys($sutFiles));
|
|
|
90 |
|
|
|
91 |
foreach (array_keys($allFiles) as $key) {
|
|
|
92 |
if (!in_array($key, $testFiles)) {
|
|
|
93 |
unset($allFiles[$key]);
|
|
|
94 |
}
|
|
|
95 |
}
|
|
|
96 |
|
|
|
97 |
$allCommonPath = PHPUnit_Util_Filesystem::reducePaths($allFiles);
|
|
|
98 |
$sutCommonPath = PHPUnit_Util_Filesystem::reducePaths($sutFiles);
|
|
|
99 |
$testFiles = $allFiles;
|
|
|
100 |
|
|
|
101 |
unset($allData);
|
|
|
102 |
unset($allFiles);
|
|
|
103 |
unset($sutData);
|
|
|
104 |
|
|
|
105 |
$testToCoveredLinesMap = array();
|
|
|
106 |
$time = time();
|
|
|
107 |
|
|
|
108 |
foreach ($sutFiles as $filename => $data) {
|
|
|
109 |
$fullPath = $sutCommonPath . DIRECTORY_SEPARATOR . $filename;
|
|
|
110 |
|
|
|
111 |
if (file_exists($fullPath)) {
|
|
|
112 |
$fullPath = realpath($fullPath);
|
|
|
113 |
|
|
|
114 |
$document = new DOMDocument('1.0', 'UTF-8');
|
|
|
115 |
$document->formatOutput = TRUE;
|
|
|
116 |
|
|
|
117 |
$coveredFile = $document->createElement('coveredFile');
|
|
|
118 |
$coveredFile->setAttribute('fullPath', $fullPath);
|
|
|
119 |
$coveredFile->setAttribute('shortenedPath', $filename);
|
|
|
120 |
$coveredFile->setAttribute('generated', $time);
|
|
|
121 |
$coveredFile->setAttribute('phpunit', PHPUnit_Runner_Version::id());
|
|
|
122 |
$document->appendChild($coveredFile);
|
|
|
123 |
|
|
|
124 |
$lines = file($fullPath, FILE_IGNORE_NEW_LINES);
|
|
|
125 |
$lineNum = 1;
|
|
|
126 |
|
|
|
127 |
foreach ($lines as $line) {
|
|
|
128 |
if (isset($data[$lineNum])) {
|
|
|
129 |
if (is_array($data[$lineNum])) {
|
|
|
130 |
$count = count($data[$lineNum]);
|
|
|
131 |
} else {
|
|
|
132 |
$count = $data[$lineNum];
|
|
|
133 |
}
|
|
|
134 |
} else {
|
|
|
135 |
$count = -3;
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
$xmlLine = $coveredFile->appendChild(
|
|
|
139 |
$document->createElement('line')
|
|
|
140 |
);
|
|
|
141 |
|
|
|
142 |
$xmlLine->setAttribute('lineNumber', $lineNum);
|
|
|
143 |
$xmlLine->setAttribute('executed', $count);
|
|
|
144 |
|
|
|
145 |
$xmlLine->appendChild(
|
|
|
146 |
$document->createElement(
|
|
|
147 |
'body', PHPUnit_Util_XML::prepareString($line)
|
|
|
148 |
)
|
|
|
149 |
);
|
|
|
150 |
|
|
|
151 |
if (isset($data[$lineNum]) && is_array($data[$lineNum])) {
|
|
|
152 |
$xmlTests = $document->createElement('tests');
|
|
|
153 |
$xmlLine->appendChild($xmlTests);
|
|
|
154 |
|
|
|
155 |
foreach ($data[$lineNum] as $test) {
|
|
|
156 |
$xmlTest = $xmlTests->appendChild(
|
|
|
157 |
$document->createElement('test')
|
|
|
158 |
);
|
|
|
159 |
|
|
|
160 |
if ($test instanceof PHPUnit_Framework_TestCase) {
|
|
|
161 |
$xmlTest->setAttribute('name', $test->getName());
|
|
|
162 |
$xmlTest->setAttribute('status', $test->getStatus());
|
|
|
163 |
|
|
|
164 |
if ($test->hasFailed()) {
|
|
|
165 |
$xmlTest->appendChild(
|
|
|
166 |
$document->createElement(
|
|
|
167 |
'message',
|
|
|
168 |
PHPUnit_Util_XML::prepareString(
|
|
|
169 |
$test->getStatusMessage()
|
|
|
170 |
)
|
|
|
171 |
)
|
|
|
172 |
);
|
|
|
173 |
}
|
|
|
174 |
|
|
|
175 |
$class = new ReflectionClass($test);
|
|
|
176 |
$testFullPath = $class->getFileName();
|
|
|
177 |
$testShortenedPath = str_replace($allCommonPath, '', $testFullPath);
|
|
|
178 |
$methodName = $test->getName(FALSE);
|
|
|
179 |
|
|
|
180 |
if ($class->hasMethod($methodName)) {
|
|
|
181 |
$method = $class->getMethod($methodName);
|
|
|
182 |
$startLine = $method->getStartLine();
|
|
|
183 |
|
|
|
184 |
$xmlTest->setAttribute('class', $class->getName());
|
|
|
185 |
$xmlTest->setAttribute('fullPath', $testFullPath);
|
|
|
186 |
$xmlTest->setAttribute('shortenedPath', $testShortenedPath);
|
|
|
187 |
$xmlTest->setAttribute('line', $startLine);
|
|
|
188 |
|
|
|
189 |
if (!isset($testToCoveredLinesMap[$testFullPath][$startLine])) {
|
|
|
190 |
$testToCoveredLinesMap[$testFullPath][$startLine] = array();
|
|
|
191 |
}
|
|
|
192 |
|
|
|
193 |
if (!isset($testToCoveredLinesMap[$testFullPath][$startLine][$fullPath])) {
|
|
|
194 |
$testToCoveredLinesMap[$testFullPath][$startLine][$fullPath] = array(
|
|
|
195 |
'coveredLines' => array($lineNum),
|
|
|
196 |
'shortenedPath' => $filename
|
|
|
197 |
);
|
|
|
198 |
} else {
|
|
|
199 |
$testToCoveredLinesMap[$testFullPath][$startLine][$fullPath]['coveredLines'][] = $lineNum;
|
|
|
200 |
}
|
|
|
201 |
}
|
|
|
202 |
}
|
|
|
203 |
}
|
|
|
204 |
}
|
|
|
205 |
|
|
|
206 |
$lineNum++;
|
|
|
207 |
}
|
|
|
208 |
|
|
|
209 |
$document->save(
|
|
|
210 |
sprintf(
|
|
|
211 |
'%s%s.xml',
|
|
|
212 |
|
|
|
213 |
$this->directory,
|
|
|
214 |
PHPUnit_Util_Filesystem::getSafeFilename(
|
|
|
215 |
basename($filename)
|
|
|
216 |
)
|
|
|
217 |
)
|
|
|
218 |
);
|
|
|
219 |
}
|
|
|
220 |
}
|
|
|
221 |
|
|
|
222 |
foreach ($testFiles as $filename => $data) {
|
|
|
223 |
$fullPath = $allCommonPath . DIRECTORY_SEPARATOR . $filename;
|
|
|
224 |
|
|
|
225 |
if (file_exists($fullPath)) {
|
|
|
226 |
$document = new DOMDocument('1.0', 'UTF-8');
|
|
|
227 |
$document->formatOutput = TRUE;
|
|
|
228 |
|
|
|
229 |
$testFile = $document->createElement('testFile');
|
|
|
230 |
$testFile->setAttribute('fullPath', $fullPath);
|
|
|
231 |
$testFile->setAttribute('shortenedPath', $filename);
|
|
|
232 |
$testFile->setAttribute('generated', $time);
|
|
|
233 |
$testFile->setAttribute('phpunit', PHPUnit_Runner_Version::id());
|
|
|
234 |
$document->appendChild($testFile);
|
|
|
235 |
|
|
|
236 |
$lines = file($fullPath, FILE_IGNORE_NEW_LINES);
|
|
|
237 |
$lineNum = 1;
|
|
|
238 |
|
|
|
239 |
foreach ($lines as $line) {
|
|
|
240 |
$xmlLine = $testFile->appendChild(
|
|
|
241 |
$document->createElement('line')
|
|
|
242 |
);
|
|
|
243 |
|
|
|
244 |
$xmlLine->setAttribute('lineNumber', $lineNum);
|
|
|
245 |
|
|
|
246 |
$xmlLine->appendChild(
|
|
|
247 |
$document->createElement(
|
|
|
248 |
'body', PHPUnit_Util_XML::prepareString($line)
|
|
|
249 |
)
|
|
|
250 |
);
|
|
|
251 |
|
|
|
252 |
if (isset($testToCoveredLinesMap[$fullPath][$lineNum])) {
|
|
|
253 |
$xmlCoveredFiles = $xmlLine->appendChild(
|
|
|
254 |
$document->createElement('coveredFiles')
|
|
|
255 |
);
|
|
|
256 |
|
|
|
257 |
foreach ($testToCoveredLinesMap[$fullPath][$lineNum] as $coveredFileFullPath => $coveredFileData) {
|
|
|
258 |
$xmlCoveredFile = $xmlCoveredFiles->appendChild(
|
|
|
259 |
$document->createElement('coveredFile')
|
|
|
260 |
);
|
|
|
261 |
|
|
|
262 |
$xmlCoveredFile->setAttribute('fullPath', $fullPath);
|
|
|
263 |
$xmlCoveredFile->setAttribute('shortenedPath', $coveredFileData['shortenedPath']);
|
|
|
264 |
|
|
|
265 |
foreach ($coveredFileData['coveredLines'] as $coveredLineNum) {
|
|
|
266 |
$xmlCoveredLine = $xmlCoveredFile->appendChild(
|
|
|
267 |
$document->createElement('coveredLine', $coveredLineNum)
|
|
|
268 |
);
|
|
|
269 |
}
|
|
|
270 |
}
|
|
|
271 |
}
|
|
|
272 |
|
|
|
273 |
$lineNum++;
|
|
|
274 |
}
|
|
|
275 |
|
|
|
276 |
$document->save(
|
|
|
277 |
sprintf(
|
|
|
278 |
'%s%s.xml',
|
|
|
279 |
|
|
|
280 |
$this->directory,
|
|
|
281 |
PHPUnit_Util_Filesystem::getSafeFilename(
|
|
|
282 |
basename($filename)
|
|
|
283 |
)
|
|
|
284 |
)
|
|
|
285 |
);
|
|
|
286 |
}
|
|
|
287 |
}
|
|
|
288 |
}
|
|
|
289 |
}
|
|
|
290 |
?>
|