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
19 "List of all rules and their snippets"
21 for r in os.listdir("../rules"):
23 fn = os.path.join("..", "rules", r, "Makefile.rules")
26 m = re.search("#OMK:(.*)\.omk", line);
28 snippets[m.group(1)] = 1;
29 self[r] = snippets.keys()
36 self.time = time.gmtime()
37 self.datetime = time.strftime("%Y-%m-%d %H:%M:%S +0000", self.time)
38 self.filename = "results-"+time.strftime("%Y%m%d-%H%M%S", self.time)+".html"
42 self.stats = Stats(self)
46 <?xml version="1.0" encoding="iso-8859-1" ?>
48 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
49 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
50 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
52 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
53 <title>OMK test report %(datetime)s</title>
58 s+=self.stats.toHtml()
60 <h2>Chart by rules</h2>
62 s+=self.toHtmlByRules();
64 <h2>Chart by testcase</h2>
65 <table cellpadding='2' border='1'>
68 tests = sorted(self.keys())
73 <h2>Outputs of tests</h2>
76 s+=self[t].toHtmlOutputs()
82 def toHtmlByRules(self):
83 rk = sorted(rules.keys())
84 tests = sorted(self.keys())
88 <a name='results-%(rules)s' />
89 <h3>Rules: %(rules)s</h3>
90 <table cellpadding='2' border='1'>
94 if self[t].has_key(r):
95 s+=self[t][r].toHtml("<a href='%s'>/</a><a href='%s'>%s</a>" %
96 (self[t].tc.dirRelative, self[t].tc.scriptNameRelative, self[t].tc.name))
103 f = file(self.filename, "w+")
104 f.write(self.toHtml())
106 os.remove("results.html")
109 os.symlink(self.filename, "results.html")
110 print "Results written to "+self.filename
112 class TestCaseResult(dict):
113 def __init__(self, tc):
117 rules = sorted(self.keys())
119 <tr><td colspan='5'><strong><a href='%s'>%s</a></strong></td></tr>
120 """ % (self.tc.scriptNameRelative, self.tc.name)
125 def toHtmlOutputs(self):
126 rules = sorted(self.keys())
127 s="<h3>Testcase: %s</h3>" % self.tc.name
129 s+=self[r].toHtmlOutputs()
133 def __init__(self, tcname, rules):
138 def toHtml(self, title):
139 if self.exitcode == 0: color=''
140 elif self.canttest: color=' bgcolor="gold"'
141 else: color=' bgcolor="red"'
142 if self.stdout: stdoutlink="<a href='#output-%(tcname)s-%(rules)s'>output</a>" % self.__dict__
147 <td>%(exitcode)d</td>
149 <td>%(time).1f s</td>
150 <td>%(stdoutlink)s</td>
154 'tcname' : self.rules,
156 'exitcode' : self.exitcode,
157 'message' : escape(self.message),
159 'stdoutlink' : stdoutlink,
162 def toHtmlOutputs(self):
164 'tcname':self.tcname,
166 'stdout':escape(self.stdout),
169 if self.stdout: s+="""
170 <a name='output-%(tcname)s-%(rules)s'/>
171 <h5>Output of test: %(tcname)s, rules: %(rules)s</h5>
172 <pre>%(stdout)s</pre>""" % vals
176 def __init__(self, rules):
182 def update(self, testCaseResult):
184 resultEntry = testCaseResult[self.rules]
186 if resultEntry.exitcode == 0: self.success+=1
187 elif resultEntry.canttest: self.canttest+=1
192 if self.errors == 0 and self.canttest == 0: self.color=''
193 elif self.errors != 0: self.color=' bgcolor="red"'
194 else: self.color = ' bgcolor="gold"'
197 <td><a href='#results-%(rules)s'>%(rules)s</a></td>
201 <td>%(canttest)d</td>
207 def __init__(self, results):
210 rulesStat = RulesStat(rule)
212 for resultEntry in results.values():
213 rulesStat.update(resultEntry)
217 <table cellpadding='2' border='1'>
219 <col span='5' align='right' />
229 rules = sorted(self.keys())
237 def __init__(self, directory, executable):
238 self.directory = directory # Absolute directory
239 self.executable = executable
240 self.name = self._getName()
241 self.scriptNameRelative = self._getScriptRelative();
242 self.dirRelative = os.path.dirname(self.scriptNameRelative)
246 name = self.directory
247 if name.startswith(testsRoot+"/"):
248 name = name[len(testsRoot)+1:]
249 testSuffix = re.match("^runtest[-_. :]*(.*)", self.executable).group(1)
254 def _getScriptRelative(self):
255 script = os.path.join(self.directory, self.executable);
256 if script.startswith(invokeDir+"/"):
257 script = script[len(invokeDir)+1:]
260 def _whichRules(self):
261 """Reads the rules file and creates the self.rules list of all
265 f = open(os.path.join(self.directory, self.executable+'.rules'))
267 self.rules = rules.keys()
270 colonMatch = re.search('([^:]*) *: *(.*)', line)
272 if colonMatch.group(1) == "all":
274 self.rules = rules.keys()
275 elif colonMatch.group(1) == "snip":
277 snip = colonMatch.group(2)
281 elif colonMatch.group(1) == "python":
283 expr = colonMatch.group(2)
285 if eval(expr, {'rules': r, 'snippets': rules[r]}):
290 if line in rules: self.rules = [ line ]
295 self.results = TestCaseResult(self)
296 print "Testing \"%s\" in %s:\n" % (self.name, self.executable),
297 os.chdir(os.path.join(testsRoot, self.directory))
298 # Chose how to run the test - currently there is only one option
299 # if os.path.exists("Makefile.test"):
300 # self._exec = self._execMake
301 if os.path.exists(self.executable):
302 self._exec = self._execRuntest
305 for rules in self.rules:
306 resultEntry = ResultEntry(self.name, rules)
307 self.results[rules] = resultEntry
308 os.environ['OMK_RULES'] = rules
309 filesBefore = self._getFileSet()
310 self._copyRules(rules)
312 self._doRun(resultEntry)
314 filesAfter = self._getFileSet()
315 self._clean(filesBefore, filesAfter)
318 def _getFileSet(self):
320 for f in os.listdir("."):
324 def _clean(self, filesBefore, filesAfter):
325 remove = filesAfter - filesBefore
327 os.system("rm -rf "+f)
329 # def _execMake(self):
330 # return os.system("make -k -f Makefile.test > /dev/null 2>&1")
332 def _execRuntest(self, log):
333 startTime = time.clock()
334 pipe = subprocess.Popen("./"+self.executable, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
335 (output, error) = pipe.communicate()
336 endTime = time.clock()
337 ret = pipe.returncode
338 log.time = endTime - startTime
342 if os.path.exists("_canttest"):
343 log.message = file("_canttest").read()
345 ret = 2 # If Makefile sets canttest, override the exit code which might be zero
348 if os.path.exists("_error"):
349 log.message = file("_error").read()
352 def _copyRules(self, rules):
353 "Copies the rules to the current directory"
354 src = os.path.join(testsRoot, "..", "rules", rules, "Makefile.rules")
355 shutil.copy(src, ".")
357 def _doRun(self, log):
358 "Runs the teset in current directory."
359 # print " ",os.environ['OMK_RULES'],
361 ret = self._exec(log)
362 # if log.canttest: retstr = "--"
363 # elif ret == 0: retstr = "ok"
367 # print "%*s%s" % (20-len(os.environ['OMK_RULES']), "", retstr)
368 if log.canttest: retstr = "[not tested] ok"
369 elif ret == 0: retstr = "ok"
373 print "! %s (%s) %s" % (self.name, os.environ['OMK_RULES'], retstr)
380 for dirpath, dirnames, filenames in os.walk(invokeDir):
381 executables = fnmatch.filter(filenames, "runtest*")
382 if not executables: continue
383 for exe in executables:
384 if exe[-1] == "~": continue
385 if re.search(".rules$", exe): continue
386 t = TestCase(dirpath, exe)
388 if t.failed: failed = True
389 results[t.name] = t.results
398 # compile-command: "python tester.py"