10 from xml.sax.saxutils import escape
13 invokeDir = os.getcwd();
14 testsRoot = os.path.dirname(os.path.abspath(__file__))
15 if not os.path.exists(os.path.join(testsRoot, "tester.py")): raise "Can't find tests root directory!"
16 os.environ['OMK_TESTSROOT'] = testsRoot
18 sys.path.append(os.path.join(testsRoot, ".."))
23 self.time = time.gmtime()
24 self.datetime = time.strftime("%Y-%m-%d %H:%M:%S +0000", self.time)
25 self.filename = "results-"+time.strftime("%Y%m%d-%H%M%S", self.time)+".html"
29 self.stats = Stats(self)
33 <?xml version="1.0" encoding="iso-8859-1" ?>
35 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
36 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
37 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
39 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
40 <title>OMK test report %(datetime)s</title>
45 s+=self.stats.toHtml()
47 <h2>Chart by rules</h2>
49 s+=self.toHtmlByRules();
51 <h2>Chart by testcase</h2>
52 <table cellpadding='2' border='1'>
55 tests = sorted(self.keys())
60 <h2>Outputs of tests</h2>
63 s+=self[t].toHtmlOutputs()
69 def toHtmlByRules(self):
70 rules = sorted(rulesdef.rules.keys())
71 tests = sorted(self.keys())
75 <a name='results-%(rules)s' />
76 <h3>Rules: %(rules)s</h3>
77 <table cellpadding='2' border='1'>
81 if self[t].has_key(r):
82 s+=self[t][r].toHtml("<a href='%s'>/</a><a href='%s'>%s</a>" %
83 (self[t].tc.dirRelative, self[t].tc.scriptNameRelative, self[t].tc.name))
90 f = file(self.filename, "w+")
91 f.write(self.toHtml())
93 os.remove("results.html")
96 os.symlink(self.filename, "results.html")
97 print "Results written to "+self.filename
99 class TestCaseResult(dict):
100 def __init__(self, tc):
104 rules = sorted(self.keys())
106 <tr><td colspan='5'><strong><a href='%s'>%s</a></strong></td></tr>
107 """ % (self.tc.scriptNameRelative, self.tc.name)
112 def toHtmlOutputs(self):
113 rules = sorted(self.keys())
114 s="<h3>Testcase: %s</h3>" % self.tc.name
116 s+=self[r].toHtmlOutputs()
120 def __init__(self, tcname, rules):
125 def toHtml(self, title):
126 if self.exitcode == 0: color=''
127 elif self.canttest: color=' bgcolor="gold"'
128 else: color=' bgcolor="red"'
129 if self.stdout: stdoutlink="<a href='#output-%(tcname)s-%(rules)s'>output</a>" % self.__dict__
134 <td>%(exitcode)d</td>
136 <td>%(time).1f s</td>
137 <td>%(stdoutlink)s</td>
141 'tcname' : self.rules,
143 'exitcode' : self.exitcode,
144 'message' : escape(self.message),
146 'stdoutlink' : stdoutlink,
149 def toHtmlOutputs(self):
151 'tcname':self.tcname,
153 'stdout':escape(self.stdout),
156 if self.stdout: s+="""
157 <a name='output-%(tcname)s-%(rules)s'/>
158 <h5>Output of test: %(tcname)s, rules: %(rules)s</h5>
159 <pre>%(stdout)s</pre>""" % vals
163 def __init__(self, rules):
169 def update(self, testCaseResult):
171 resultEntry = testCaseResult[self.rules]
173 if resultEntry.exitcode == 0: self.success+=1
174 elif resultEntry.canttest: self.canttest+=1
179 if self.errors == 0 and self.canttest == 0: self.color=''
180 elif self.errors != 0: self.color=' bgcolor="red"'
181 else: self.color = ' bgcolor="gold"'
184 <td><a href='#results-%(rules)s'>%(rules)s</a></td>
188 <td>%(canttest)d</td>
194 def __init__(self, results):
195 rules = rulesdef.rules.keys()
197 rulesStat = RulesStat(rule)
199 for resultEntry in results.values():
200 rulesStat.update(resultEntry)
204 <table cellpadding='2' border='1'>
206 <col span='5' align='right' />
216 rules = sorted(self.keys())
224 def __init__(self, directory, executable):
225 self.directory = directory # Absolute directory
226 self.executable = executable
227 self.name = self._getName()
228 self.scriptNameRelative = self._getScriptRelative();
229 self.dirRelative = os.path.dirname(self.scriptNameRelative)
233 name = self.directory
234 if name.startswith(testsRoot+"/"):
235 name = name[len(testsRoot)+1:]
236 testSuffix = re.match("^runtest[-_. :]*(.*)", self.executable).group(1)
241 def _getScriptRelative(self):
242 script = os.path.join(self.directory, self.executable);
243 if script.startswith(invokeDir+"/"):
244 script = script[len(invokeDir)+1:]
247 def _whichRules(self):
248 """Reads the rules file and creates the self.rules list of all
252 f = open(os.path.join(self.directory, self.executable+'.rules'))
254 self.rules = rulesdef.rules.keys()
257 colonMatch = re.search('([^:]*) *: *(.*)', line)
259 if colonMatch.group(1) == "all":
261 self.rules = rulesdef.rules.keys()
262 elif colonMatch.group(1) == "snip":
264 snip = colonMatch.group(2)
265 for r in rulesdef.rules:
266 if snip in rulesdef.rules[r]:
268 elif colonMatch.group(1) == "python":
270 expr = colonMatch.group(2)
271 for r in rulesdef.rules:
272 if eval(expr, {'rules': r, 'snippets': rulesdef.rules[r]}):
277 if line in rulesdef.rules: self.rules = [ line ]
282 self.results = TestCaseResult(self)
283 print "Testing %s:\n" % self.name,
284 os.chdir(os.path.join(testsRoot, self.directory))
285 # if os.path.exists("Makefile.test"):
286 # self._exec = self._execMake
287 if os.path.exists(self.executable):
288 self._exec = self._execRuntest
290 for rules in self.rules:
291 resultEntry = ResultEntry(self.name, rules)
292 self.results[rules] = resultEntry
293 os.environ['OMK_RULES'] = rules
294 filesBefore = self._getFileSet()
295 self._copyRules(rules)
297 self._doRun(resultEntry)
299 filesAfter = self._getFileSet()
300 self._clean(filesBefore, filesAfter)
303 def _getFileSet(self):
305 for f in os.listdir("."):
309 def _clean(self, filesBefore, filesAfter):
310 remove = filesAfter - filesBefore
312 os.system("rm -rf "+f)
314 # def _execMake(self):
315 # return os.system("make -k -f Makefile.test > /dev/null 2>&1")
317 def _execRuntest(self, log):
318 startTime = time.clock()
319 pipe = subprocess.Popen("./"+self.executable, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
320 (output, error) = pipe.communicate()
321 endTime = time.clock()
322 ret = pipe.returncode
323 log.time = endTime - startTime
327 if os.path.exists("_canttest"):
328 log.message = file("_canttest").read()
330 ret = 2 # If Makefile sets canttest, override the exit code which might be zero
333 if os.path.exists("_error"):
334 log.message = file("_error").read()
337 def _copyRules(self, rules):
338 "Copies the rules to the current directory"
339 src = os.path.join(testsRoot, "..", "rules", rules, "Makefile.rules")
340 shutil.copy(src, ".")
342 def _doRun(self, log):
343 "Runs the teset in current directory."
344 print " ",os.environ['OMK_RULES'],
346 ret = self._exec(log)
347 if log.canttest: retstr = "--"
348 elif ret == 0: retstr = "OK"
349 else: retstr = "FAILED"
350 print "%*s%s" % (20-len(os.environ['OMK_RULES']), "", retstr)
355 for dirpath, dirnames, filenames in os.walk(invokeDir):
356 executables = fnmatch.filter(filenames, "runtest*")
357 if not executables: continue
358 for exe in executables:
359 if exe[-1] == "~": continue
360 if re.search(".rules$", exe): continue
361 t = TestCase(dirpath, exe)
363 results[t.name] = t.results
370 # compile-command: "python tester.py"