source: branches/1.0/coverager/coverager.php @ 240

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

trunk->1.0: merged coverager

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