source: trunk/coverager/coverager.php @ 33

Last change on this file since 33 was 33, checked in by moo, 8 years ago

coverage dumper web viewer

File size: 6.8 KB
RevLine 
[33]1<?php
2
3error_reporting(E_ALL);
4define('REQUEST_TIME', time());
5
6class Cycle
7{
8    var $values;
9    var $i;
10    var $count;
11
12    function Cycle($v)
13    {
14        $this->values = func_get_args();
15        $this->i = -1;
16        $this->count = count($this->values);
17    }
18
19    function next()
20    {
21        $this->i = ($this->i + 1) % $this->count;
22        return $this->values[$this->i];
23    }
24
25    function cur()
26    {
27        return $this->values[$this->i];
28    }
29
30    function reset()
31    {
32        $this->i = -1;
33    }
34}
35
36class XcacheCoverageViewer
37{
38    var $syntaxhiglight = true;
39    var $usecache = false;
40    var $include_paths = array();
41    var $exclude_paths = array();
42    var $charset = 'UTF-8';
43
44    function XcacheCoverageViewer()
45    {
46        $this->datadir = ini_get('xcache.coveragedump_directory');
47
48        // copy config
49        foreach (array('charset', 'include_paths', 'exclude_paths', 'syntaxhiglight', 'usecache', 'datadir') as $k) {
50            if (isset($GLOBALS['usecache'])) {
51                $this->{$k} = $GLOBALS['usecache'];
52            }
53        }
54
55        $this->datadir = preg_replace('!/$!', '', $this->datadir);
56        $this->datadir_len =  strlen($this->datadir);
57
58        $this->path = isset($_GET['path']) ? $_GET['path'] : '';
59        $this->path = preg_replace('!\.{2,}!', '.', $this->path);
60        $this->path = preg_replace('![\\\\/]{2,}!', '/', $this->path);
61        if ($this->path == '/') {
62            $this->path = '';
63        }
64        $this->outpath = $this->datadir . $this->path;
65    }
66
67    function main()
68    {
69        $path = $this->path;
70
71        if (is_dir($this->outpath)) {
72            $action = 'dir';
73            $prefix_len = strlen($path) + 1;
74            $dirinfo = $this->loadDir($this->outpath);
75            if (!$this->usecache) {
76                ksort($dirinfo['subdirs']);
77                ksort($dirinfo['files']);
78            }
79        }
80        else if (is_file($this->outpath . ".pcov")) {
81            $action = 'file';
82
83            $dir = dirname($path);
84            $filename = basename($path);
85
86            $fileinfo = $this->loadCov($this->outpath . ".pcov");
87
88            $lines = file($path);
89            // fix the tabs not in the middle
90            foreach ($lines as $l => $line) {
91                if (preg_match('!^(\\t*)([^\\t]+\\t.*)$!s', $line, $m)) {
92                    $lines[$l] = $m[1];
93                    $chunks = explode("\t", $m[2]);
94                    for ($i = 0, $c = count($chunks) - 1; $i < $c; $i ++) {
95                        $lines[$l] .= $chunks[$i] . str_repeat(" ", 4 - (strlen($chunks[$i]) % 4));
96                    }
97                    $lines[$l] .= $chunks[$c];
98                }
99            }
100            if ($this->syntaxhiglight) {
101                $source = implode('', $lines);
102                ob_start();
103                highlight_string($source);
104                $lines = explode('<br />', str_replace("\n", "", ob_get_clean()));
105                $last = array_pop($lines);
106                $filecov = sprint_cov($fileinfo['cov'], $lines, false);
107                $filecov .= $last;
108                unset($source);
109            }
110            else {
111                $filecov = sprint_cov($fileinfo['cov'], $lines);
112            }
113
114            list($tplfile, $tpllines, $tplcov) = $this->loadTplCov($fileinfo['cov'], substr($this->outpath, $this->datadir_len));
115            if ($tplfile) {
116                $tplcov = sprint_cov($tplinfo['tplcov'], $tpllines);
117                unset($tpllines);
118            }
119        }
120        else if (!$this->datadir) {
121            $action = 'require xcache.coveragedump_directory';
122        }
123        else {
124            $action = "no data";
125        }
126
127        include("coverager.tpl.php");
128    }
129
130    function loadDir($outdir, $addtodo = null)
131    {
132        if ($this->usecache) {
133            $cachefile = $outdir . "/.pcovcache";
134            if (file_exists($cachefile)) {
135                return unserialize(file_get_contents($cachefile));
136            }
137        }
138        $srcdir = substr($outdir, $this->datadir_len);
139
140        $total = $hits = $todos = 0;
141        $files = array();
142        $subdirs = array();
143        if (!isset($addtodo)) {
144            if ($this->include_paths) {
145                foreach ($this->include_paths as $p) {
146                    if (strncmp($p, $srcdir, strlen($p)) == 0) {
147                        $addtodo = true;
148                        break;
149                    }
150                }
151            }
152        }
153        if ($addtodo) {
154            if ($this->exclude_paths) {
155                foreach ($this->exclude_paths as $p) {
156                    if (strncmp($p, $srcdir, strlen($p)) == 0) {
157                        $addtodo = false;
158                        break;
159                    }
160                }
161            }
162        }
163        foreach (glob($outdir . "/*") as $outfile) {
164            if (is_dir($outfile)) {
165                $info = $this->loadDir($outfile, $addtodo);
166                $srcfile = substr($outfile, $this->datadir_len);
167                $subdirs += $info['subdirs'];
168                $total   += $info['total'];
169                $hits    += $info['hits'];
170                $todos   += $info['todos'];
171                unset($info['subdirs']);
172                $subdirs[$srcfile] = $info;
173            }
174            else if (substr($outfile, -5) == ".pcov") {
175                // pass
176                $info = $this->loadFile($outfile);
177                $total += $info['total'];
178                $hits  += $info['hits'];
179                $srcfile = substr($outfile, $this->datadir_len, -5);
180                $files[$srcfile] = $info;
181            }
182            else {
183                continue;
184            }
185        }
186        if ($addtodo === true) {
187            foreach (glob($srcdir . "/*") as $srcfile) {
188                if (!isset($files[$srcfile]) && is_file($srcfile)) {
189                    $files[$srcfile] = array('total' => 0, 'hits' => 0);
190                    $todos ++;
191                }
192                else if (!isset($subdirs[$srcfile]) && is_dir($srcfile)) {
193                    $subdirs[$srcfile] = array('total' => 0, 'hits' => 0, 'todos' => 1, 'files' => 0, 'subdirs' => array());
194                    $todos ++;
195                }
196            }
197        }
198
199        if ($this->usecache) {
200            ksort($subdirs);
201            ksort($files);
202        }
203
204        $info = array(
205                'total'   => $total,
206                'hits'    => $hits,
207                'todos'   => $todos,
208                'files'   => $files,
209                'subdirs' => $subdirs,
210                );
211
212        if ($this->usecache) {
213            $fp = fopen($cachefile, "wb");
214            fwrite($fp, serialize($info));
215            fclose($fp);
216        }
217        return $info;
218    }
219
220    function loadFile($file)
221    {
222        if ($this->usecache) {
223            $cachefile = $file . "cache";
224            if (file_exists($cachefile)) {
225                return unserialize(file_get_contents($cachefile));
226            }
227        }
228
229        $info = $this->loadCov($file); //, $lines);
230        unset($info['cov']);
231
232        if ($this->usecache) {
233            $fp = fopen($cachefile, "wb");
234            fwrite($fp, serialize($info));
235            fclose($fp);
236        }
237        return $info;
238    }
239
240    function loadCov($file)//, $lines)
241    {
242        $total = $hits = 0;
243
244        $cov = xcache_coverager_decode(file_get_contents($file));
245
246        return array('total' => count($cov) - 1, 'hits' => $cov[0], 'cov' => $cov);
247    }
248
249    function loadTplCov($cov, $ctpl)
250    {
251        $tplinfofile = $ctpl . '.phpinfo';
252
253        if (!file_exists($tplinfofile)) {
254            return;
255        }
256
257        $tplinfo = unserialize(file_get_contents($tplinfofile));
258
259        if (!isset($tplinfo['sourceFile'])) {
260            return;
261        }
262        $tplfile = $tplinfo['sourceFile'];
263        if (!isset($tplinfo['lineMap']) || !count($tplinfo['lineMap'])) {
264            return;
265        }
266
267        $tpllines = file($tplfile);
268
269        $dline = 0;
270        $sline = 0;
271        $tplcov = array();
272        foreach ($cov as $line => $times) {
273            // find nearest line
274            while ($dline < $line) {
275                if ((list($dline, $sline) = each($tplinfo['lineMap'])) === false) {
276                    break 2;
277                }
278            }
279
280            $tplcov[$sline] = $times;
281        }
282        return array($tplfile, $tpllines, $tplcov);
283    }
284}
285
286function sprint_cov($cov, $lines, $encode = true)
287{
288    foreach ($lines as $l => $line) {
289        $offs = $l + 1;
290        if ($encode) {
291            $line = str_replace("\n", "", htmlspecialchars($line));
292        }
293        if (isset($cov[$offs])) {
294            $lines[$l] = sprintf("<li class=\"line%sCov\"> %s\t%s</li>\n"
295                    , $cov[$offs] ? '' : 'No'
296                    , $cov[$offs]
297                    , $line);
298        }
299        else {
300            $lines[$l] = "<li>\t$line</li>\n";
301        }
302    }
303    return implode('', $lines);
304}
305
306if (file_exists("config.php")) {
307    include("config.php");
308}
309
310$app = new XcacheCoverageViewer();
311$app->main();
312
313?>
Note: See TracBrowser for help on using the repository browser.