source: trunk/coverager/coverager.php @ 184

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

fix tplcov

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