Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
if (!defined('T_ML_COMMENT'))
4
	define('T_ML_COMMENT', T_COMMENT);
5
else
6
	define('T_DOC_COMMENT', T_ML_COMMENT);
7
 
8
class HtmlReporterWithCoverage extends HtmlReporter
9
{
10
	protected $coverage = array();
11
 
12
	protected $painter;
13
 
14
	protected $base_dir;
15
 
16
	function __construct($painter = 'index.php', $base_dir)
17
	{
18
		$this->painter = $painter;
19
		$this->base_dir = $base_dir;
20
	}
21
 
22
	function paintHeader($test_name, $charset="UTF-8")
23
	{
24
		$this->sendNoCacheHeaders();
25
		header('Content-Type: text/html; Charset='.$charset);
26
		print "<html>\n<head>\n<title>$test_name</title>\n";
27
		print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset={$charset}\"/>";
28
		print "<style type=\"text/css\">\n";
29
		print $this->_getCss() . "\n";
30
		print "</style>\n";
31
		print "</head>\n<body>\n";
32
		print "<h1>$test_name</h1>\n";
33
		flush();
34
 
35
		if (extension_loaded('xdebug'))
36
			xdebug_start_code_coverage(XDEBUG_CC_UNUSED);
37
 
38
	}
39
 
40
	/**
41
	 *
42
	 */
43
	function _getCss()
44
	{
45
		$contents = parent::_getCss()."\n ";
46
		$contents .= '
47
	 .bar { float: left; display: inline;  border: 1px solid #eee; width: 300px; white-space: nowrap;}
48
	.percentage { float: left; background-color: #eef;  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;  font-size: 0.65em;  padding: 5px;  margin-right: }
49
	.coverage {margin: 0.4em; }
50
	.coverage a {
51
		padding-left: 0.5em;
52
	}
53
	.coverage:after {
54
	content: ".";
55
	display: block;
56
	height: 0;
57
	clear: both;
58
	visibility: hidden;
59
	}
60
	.coverage {display: inline-block;}
61
	/* Hides from IE-mac \*/
62
	* html .coverage {height: 1%;}
63
	.coverage {display: block;}
64
	/* End hide from IE-mac */
65
	';
66
		Return $contents;
67
	}
68
 
69
	function paintFooter($test_name)
70
	{
71
		if (extension_loaded('xdebug'))
72
		{
73
			$this->coverage = xdebug_get_code_coverage();
74
			xdebug_stop_code_coverage();
75
		}
76
 
77
		$colour = ($this->getFailCount() + $this->getExceptionCount() > 0 ? "red" : "green");
78
		print "<div style=\"";
79
		print "padding: 8px; margin-top: 1em; background-color: $colour; color: white;";
80
		print "\">";
81
		print $this->getTestCaseProgress() . "/" . $this->getTestCaseCount();
82
		print " test cases complete:\n";
83
		print "<strong>" . $this->getPassCount() . "</strong> passes, ";
84
		print "<strong>" . $this->getFailCount() . "</strong> fails and ";
85
		print "<strong>" . $this->getExceptionCount() . "</strong> exceptions.";
86
		print "</div>\n";
87
		$this->paintCoverage();
88
		print "</body>\n</html>\n";
89
	}
90
 
91
	function paintCoverage()
92
	{
93
		$dir = dirname(__FILE__);
94
		if(count($this->coverage) > 0)
95
			print '<h2>Code Coverage</h2>';
96
 
97
 
98
		ksort($this->coverage);
99
 
100
		$details = array();
101
		foreach($this->coverage as $file => $coverage)
102
		{
103
			if(is_int(strpos($file, $dir)) == false
104
			&& is_int(strpos($file, 'simpletest')) == false
105
			&& is_int(strpos($file, $this->base_dir)))
106
			{
107
				$total = HTMLCoverageReport::codelines($file);
108
				$executed = count($coverage);
109
				$percentage = sprintf('%01d',$executed/$total*100);
110
				$width = $percentage * 3;
111
				$filename = str_replace($this->base_dir, '',$file);
112
				$link = $this->constructURL($filename, $coverage);
113
 
114
				$detail['total'] = $total;
115
				$detail['executed'] = $executed;
116
				$detail['width'] = $width;
117
				$detail['filename'] = $filename;
118
				$detail['link'] = $link;
119
				$details[$percentage][] = $detail;
120
			}
121
		}
122
		krsort($details);
123
		foreach($details as $percentage => $files)
124
		{
125
			foreach($files as $detail)
126
			{
127
				$total = $detail['total'];
128
				$executed = $detail['executed'];
129
				$width = $detail['width'];
130
				$filename = $detail['filename'];
131
				$link = $detail['link'];
132
 
133
				print "<div class=\"coverage\">";
134
				print "<span class=\"bar\">";
135
				print "<span class=\"percentage\" style=\"width:{$width}px\">";
136
				print "$executed/$total\n";
137
				print "$percentage%</span></span>\n";
138
				print "<a href=\"{$link}\">{$filename}</a>\n";
139
				print "</div>\n";
140
			}
141
		}
142
	}
143
 
144
	function constructURL($file, $coverage)
145
	{
146
		$file = rawurlencode($file);
147
		$lines = implode(',', array_keys($coverage));
148
		return $this->painter.'?file='.$file.'&amp;lines='.$lines;
149
	}
150
}
151
 
152
 
153
class HTMLCoverageReport extends HtmlReporter
154
{
155
	protected $file;
156
	protected $lines;
157
	protected $name;
158
 
159
	function __construct($file, $name, $lines)
160
	{
161
		$this->file = $file;
162
		$this->lines = $lines;
163
		$this->name = $name;
164
	}
165
 
166
	function show()
167
	{
168
		$this->paintHeader($this->name);
169
 
170
		$contents = file($this->file);
171
		foreach($contents as $count => $line)
172
		{
173
			$num = ($count+1);
174
			$line = preg_replace("/\\n|\\r/",'',$line);
175
			$line = htmlspecialchars($line);
176
			$line = str_replace(' ','&nbsp;',$line);
177
			$line = str_replace("\t",'&nbsp;&nbsp;&nbsp;&nbsp;',$line);
178
			if(in_array($count+1, $this->lines))
179
			echo "<div class=\"highlight\"><tt>$num $line</tt></div>\n";
180
			else
181
			echo "<tt>$num $line</tt><br />\n";
182
		}
183
 
184
		$this->paintFooter();
185
	}
186
 
187
	function paintHeader($file, $charset="UTF-8")
188
	{
189
		$total = $this->codelines($this->file);
190
		$executed = count($this->lines);
191
		$percentage = sprintf('%01.2f',$executed/$total*100);
192
 
193
		$this->sendNoCacheHeaders();
194
		header('Content-Type: text/html Charset='.$charset);
195
		print "<html>\n<head>\n<title>Code Coverage: $file</title>\n";
196
		print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset={$charset}\"/>";
197
		print "<style type=\"text/css\">\n";
198
		print $this->_getCss() . "\n";
199
		print ".highlight { background-color: #eef; } \n";
200
		print ".filename { margin-bottom: 2em; } \n";
201
		print "</style>\n";
202
		print "</head>\n<body>\n";
203
		print "<h1>Code Coverage</h1>\n";
204
		print "<div class=\"filename\"><strong>$file</strong></div>";
205
		print "<div class=\"filename\"><tt>&nbsp;&nbsp;&nbsp;&nbsp;Total code lines: {$total} <br /> Total lines executed: {$executed} ({$percentage}%)</tt></div>";
206
		flush();
207
	}
208
 
209
	function paintFooter($test_name)
210
	{
211
		print "</body>\n</html>\n";
212
	}
213
 
214
	static function codelines($file)
215
	{
216
		$source = file_get_contents($file);
217
		$tokens = @token_get_all($source);
218
 
219
		$lines = '';
220
 
221
		foreach ($tokens as $token)
222
		{
223
			if (is_string($token))
224
			{
225
				// simple 1-character token
226
				$lines .= $token;
227
			}
228
			else
229
			{
230
					// token array
231
				list($id, $text) = $token;
232
 
233
				switch ($id)
234
				{
235
					case T_COMMENT:
236
					case T_ML_COMMENT: // we've defined this
237
					case T_DOC_COMMENT: // and this
238
					// no action on comments
239
					break;
240
 
241
					default:
242
					// anything else -> output "as is"
243
					//echo $text;
244
					$lines .= $text;
245
					break;
246
				}
247
			}
248
		}
249
 
250
		$lines =  preg_replace('/\\n\s*$/m',"",$lines);
251
		$codelines = explode("\n",$lines);
252
		$count = 0;
253
		$patterns[] = '^\s*{\s*$';
254
		$patterns[] = '<\?';
255
		$patterns[] = '^\s*(private|protected|public)\s+\$';
256
		$pattern = '/'.implode('|', $patterns).'/';
257
		foreach($codelines as $line)
258
		{
259
			if(!preg_match($pattern, $line))
260
				$count++;
261
		}
262
		return $count;
263
		//var_dump($codelines);
264
		//return count($codelines);
265
	}
266
}
267
 
268
?>