Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
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.1.0
44
 */
45
 
46
require_once 'PHPUnit/Util/Filter.php';
47
 
48
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
49
 
50
/**
51
 * Code Coverage helpers.
52
 *
53
 * @category   Testing
54
 * @package    PHPUnit
55
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
56
 * @copyright  2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
57
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
58
 * @version    Release: 3.4.15
59
 * @link       http://www.phpunit.de/
60
 * @since      Class available since Release 3.1.0
61
 */
62
abstract class PHPUnit_Util_CodeCoverage
63
{
64
    /**
65
     * @var array
66
     */
67
    protected static $lineToTestMap = array();
68
 
69
    /**
70
     * @var array
71
     */
72
    protected static $summary = array();
73
 
74
    /**
75
     * Returns only the executed lines.
76
     *
77
     * @param  array $data
78
     * @return array
79
     * @since  Method available since Release 3.3.15
80
     */
81
    public static function getExecutedLines(array $data)
82
    {
83
        return self::getLinesByStatus($data, 1);
84
    }
85
 
86
    /**
87
     * Returns only the executable lines.
88
     *
89
     * @param  array $data
90
     * @return array
91
     * @since  Method available since Release 3.3.15
92
     */
93
    public static function getExecutableLines(array $data)
94
    {
95
        return self::getLinesByStatus($data, array(-1, 1));
96
    }
97
 
98
    /**
99
     * Returns only the lines that were not executed.
100
     *
101
     * @param  array $data
102
     * @return array
103
     * @since  Method available since Release 3.3.15
104
     */
105
    public static function getNotExecutedLines(array $data)
106
    {
107
        return self::getLinesByStatus($data, -1);
108
    }
109
 
110
    /**
111
     * Returns only the dead code lines.
112
     *
113
     * @param  array $data
114
     * @return array
115
     * @since  Method available since Release 3.3.15
116
     */
117
    public static function getDeadLines(array $data)
118
    {
119
        return self::getLinesByStatus($data, -2);
120
    }
121
 
122
    /**
123
     * Filters lines by status.
124
     *
125
     * @param  array         $data
126
     * @param  array|integer $status
127
     * @return array
128
     * @since  Method available since Release 3.3.15
129
     */
130
    protected static function getLinesByStatus(array $data, $status)
131
    {
132
        if (!is_array($status)) {
133
            $status = array($status);
134
        }
135
 
136
        $isFileCache = array();
137
        $result      = array();
138
 
139
        foreach ($data as $file => $coverage) {
140
            if (!isset($isFileCache[$file])) {
141
                $isFileCache[$file] = self::isFile($file);
142
            }
143
 
144
            if (!$isFileCache[$file]) {
145
                continue;
146
            }
147
 
148
            $result[$file] = array();
149
 
150
            foreach ($coverage as $line => $_status) {
151
                if (in_array($_status, $status)) {
152
                    $result[$file][$line] = $_status;
153
                }
154
            }
155
        }
156
 
157
        return $result;
158
    }
159
 
160
    /**
161
     * Returns the tests that cover a given line.
162
     *
163
     * @param  array   $data
164
     * @param  string  $file
165
     * @param  string  $line
166
     * @param  boolean $clear
167
     * @return array
168
     */
169
    public static function getCoveringTests(array &$data, $file, $line, $clear = FALSE)
170
    {
171
        if (empty(self::$lineToTestMap) || $clear) {
172
            foreach ($data as $test) {
173
                foreach ($test['files'] as $_file => $lines) {
174
                    foreach ($lines as $_line => $flag) {
175
                        if ($flag > 0) {
176
                            if (!isset(self::$lineToTestMap[$_file][$_line])) {
177
                                self::$lineToTestMap[$_file][$_line] = array(
178
                                  $test['test']
179
                                );
180
                            } else {
181
                                self::$lineToTestMap[$_file][$_line][] = $test['test'];
182
                            }
183
                        }
184
                    }
185
                }
186
            }
187
        }
188
 
189
        if (isset(self::$lineToTestMap[$file][$line])) {
190
            return self::$lineToTestMap[$file][$line];
191
        } else {
192
            return FALSE;
193
        }
194
    }
195
 
196
    /**
197
     * Returns summarized code coverage data.
198
     *
199
     * Format of the result array:
200
     *
201
     * <code>
202
     * array(
203
     *   "/tested/code.php" => array(
204
     *     linenumber => array(tests that executed the line)
205
     *   )
206
     * )
207
     * </code>
208
     *
209
     * @param  array $data
210
     * @param  boolean $clear
211
     * @return array
212
     */
213
    public static function getSummary(array &$data, $clear = FALSE)
214
    {
215
        if (empty(self::$summary) || $clear) {
216
            foreach ($data as $test) {
217
                foreach ($test['files'] as $file => $lines) {
218
                    foreach ($lines as $line => $flag) {
219
                        if ($flag == 1) {
220
                            if (isset(self::$summary[$file][$line][0])) {
221
                                self::$summary[$file][$line][] = $test['test'];
222
                            } else {
223
                                self::$summary[$file][$line] = array(
224
                                  $test['test']
225
                                );
226
                            }
227
                        }
228
 
229
                        else if (!isset(self::$summary[$file][$line])) {
230
                            self::$summary[$file][$line] = $flag;
231
                        }
232
                    }
233
                }
234
 
235
                if (isset($test['executable'])) {
236
                    foreach ($test['executable'] as $file => $lines) {
237
                        foreach ($lines as $line => $flag) {
238
                            if ($flag == 1 &&
239
                                !isset(self::$summary[$file][$line][0])) {
240
                                self::$summary[$file][$line] = -1;
241
                            }
242
 
243
                            else if (!isset(self::$summary[$file][$line])) {
244
                                self::$summary[$file][$line] = $flag;
245
                            }
246
                        }
247
                    }
248
                }
249
 
250
                if (isset($test['dead'])) {
251
                    foreach ($test['dead'] as $file => $lines) {
252
                        foreach ($lines as $line => $flag) {
253
                            if ($flag == -2 &&
254
                                !isset(self::$summary[$file][$line][0])) {
255
                                self::$summary[$file][$line] = -2;
256
                            }
257
                        }
258
                    }
259
                }
260
            }
261
        }
262
 
263
        return self::$summary;
264
    }
265
 
266
    /**
267
     * Returns the coverage statistics for a section of a file.
268
     *
269
     * @param  array   $data
270
     * @param  string  $filename
271
     * @param  integer $startLine
272
     * @param  integer $endLine
273
     * @return array
274
     * @since  Method available since Release 3.2.0
275
     */
276
    public static function getStatistics(array &$data, $filename, $startLine = 1, $endLine = FALSE)
277
    {
278
        $coverage      = 0;
279
        $locExecutable = 0;
280
        $locExecuted   = 0;
281
 
282
        if (isset($data[$filename])) {
283
            if ($endLine == FALSE) {
284
                $endLine = count(file($filename));
285
            }
286
 
287
            foreach ($data[$filename] as $line => $_data) {
288
                if ($line >= $startLine && $line < $endLine) {
289
                    if (is_array($_data)) {
290
                        $locExecutable++;
291
                        $locExecuted++;
292
                    }
293
 
294
                    else if ($_data == -1) {
295
                        $locExecutable++;
296
                    }
297
                }
298
            }
299
 
300
            if ($locExecutable > 0) {
301
                $coverage = ($locExecuted / $locExecutable) * 100;
302
            } else {
303
                $coverage = 100;
304
            }
305
        }
306
 
307
        return array(
308
          'coverage'      => $coverage,
309
          'loc'           => $endLine - $startLine + 1,
310
          'locExecutable' => $locExecutable,
311
          'locExecuted'   => $locExecuted
312
        );
313
    }
314
 
315
    /**
316
     * Checks whether a file (as seen by Xdebug) is actually a file.
317
     *
318
     * @param  string $file
319
     * @return boolean
320
     */
321
    public static function isFile($file)
322
    {
323
        if (strpos($file, 'eval()\'d code') ||
324
            strpos($file, 'runtime-created function') ||
325
            strpos($file, 'assert code') ||
326
            strpos($file, 'regexp code')) {
327
            return FALSE;
328
        }
329
 
330
        return TRUE;
331
    }
332
 
333
    /**
334
     * Clears the cached summary information.
335
     *
336
     * @since  Method available since Release 3.3.0
337
     */
338
    public static function clearSummary()
339
    {
340
        self::$summary = array();
341
    }
342
}
343
?>