Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: tools/testrunner/local/old_statusfile.py

Issue 10919265: First commit of new tools/run-tests.py (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: s/server.py/test-server.py/ in README Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/testrunner/local/execution.py ('k') | tools/testrunner/local/progress.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2012 the V8 project authors. All rights reserved.
2 # Redistribution and use in source and binary forms, with or without
3 # modification, are permitted provided that the following conditions are
4 # met:
5 #
6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above
9 # copyright notice, this list of conditions and the following
10 # disclaimer in the documentation and/or other materials provided
11 # with the distribution.
12 # * Neither the name of Google Inc. nor the names of its
13 # contributors may be used to endorse or promote products derived
14 # from this software without specific prior written permission.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
29 import cStringIO
30 import re
31
32 # These outcomes can occur in a TestCase's outcomes list:
33 SKIP = 'SKIP'
34 FAIL = 'FAIL'
35 PASS = 'PASS'
36 OKAY = 'OKAY'
37 TIMEOUT = 'TIMEOUT'
38 CRASH = 'CRASH'
39 SLOW = 'SLOW'
40 # These are just for the status files and are mapped below in DEFS:
41 FAIL_OK = 'FAIL_OK'
42 PASS_OR_FAIL = 'PASS_OR_FAIL'
43
44 KEYWORDS = {SKIP: SKIP,
45 FAIL: FAIL,
46 PASS: PASS,
47 OKAY: OKAY,
48 TIMEOUT: TIMEOUT,
49 CRASH: CRASH,
50 SLOW: SLOW,
51 FAIL_OK: FAIL_OK,
52 PASS_OR_FAIL: PASS_OR_FAIL}
53
54 class Expression(object):
55 pass
56
57
58 class Constant(Expression):
59
60 def __init__(self, value):
61 self.value = value
62
63 def Evaluate(self, env, defs):
64 return self.value
65
66
67 class Variable(Expression):
68
69 def __init__(self, name):
70 self.name = name
71
72 def GetOutcomes(self, env, defs):
73 if self.name in env: return set([env[self.name]])
74 else: return set([])
75
76 def Evaluate(self, env, defs):
77 return env[self.name]
78
79 def __str__(self):
80 return self.name
81
82 def string(self, logical):
83 return self.__str__()
84
85
86 class Outcome(Expression):
87
88 def __init__(self, name):
89 self.name = name
90
91 def GetOutcomes(self, env, defs):
92 if self.name in defs:
93 return defs[self.name].GetOutcomes(env, defs)
94 else:
95 return set([self.name])
96
97 def __str__(self):
98 if self.name in KEYWORDS:
99 return "%s" % KEYWORDS[self.name]
100 return "'%s'" % self.name
101
102 def string(self, logical):
103 if logical:
104 return "%s" % self.name
105 return self.__str__()
106
107
108 class Operation(Expression):
109
110 def __init__(self, left, op, right):
111 self.left = left
112 self.op = op
113 self.right = right
114
115 def Evaluate(self, env, defs):
116 if self.op == '||' or self.op == ',':
117 return self.left.Evaluate(env, defs) or self.right.Evaluate(env, defs)
118 elif self.op == 'if':
119 return False
120 elif self.op == '==':
121 return not self.left.GetOutcomes(env, defs).isdisjoint(self.right.GetOutco mes(env, defs))
122 elif self.op == '!=':
123 return self.left.GetOutcomes(env, defs).isdisjoint(self.right.GetOutcomes( env, defs))
124 else:
125 assert self.op == '&&'
126 return self.left.Evaluate(env, defs) and self.right.Evaluate(env, defs)
127
128 def GetOutcomes(self, env, defs):
129 if self.op == '||' or self.op == ',':
130 return self.left.GetOutcomes(env, defs) | self.right.GetOutcomes(env, defs )
131 elif self.op == 'if':
132 if self.right.Evaluate(env, defs): return self.left.GetOutcomes(env, defs)
133 else: return set([])
134 else:
135 assert self.op == '&&'
136 return self.left.GetOutcomes(env, defs) & self.right.GetOutcomes(env, defs )
137
138 def __str__(self):
139 return self.string(False)
140
141 def string(self, logical=False):
142 if self.op == 'if':
143 return "['%s', %s]" % (self.right.string(True), self.left.string(logical))
144 elif self.op == "||" or self.op == ",":
145 if logical:
146 return "%s or %s" % (self.left.string(True), self.right.string(True))
147 else:
148 return "%s, %s" % (self.left, self.right)
149 elif self.op == "&&":
150 return "%s and %s" % (self.left.string(True), self.right.string(True))
151 return "%s %s %s" % (self.left.string(logical), self.op,
152 self.right.string(logical))
153
154
155 def IsAlpha(string):
156 for char in string:
157 if not (char.isalpha() or char.isdigit() or char == '_'):
158 return False
159 return True
160
161
162 class Tokenizer(object):
163 """A simple string tokenizer that chops expressions into variables,
164 parens and operators"""
165
166 def __init__(self, expr):
167 self.index = 0
168 self.expr = expr
169 self.length = len(expr)
170 self.tokens = None
171
172 def Current(self, length=1):
173 if not self.HasMore(length): return ""
174 return self.expr[self.index:self.index + length]
175
176 def HasMore(self, length=1):
177 return self.index < self.length + (length - 1)
178
179 def Advance(self, count=1):
180 self.index = self.index + count
181
182 def AddToken(self, token):
183 self.tokens.append(token)
184
185 def SkipSpaces(self):
186 while self.HasMore() and self.Current().isspace():
187 self.Advance()
188
189 def Tokenize(self):
190 self.tokens = [ ]
191 while self.HasMore():
192 self.SkipSpaces()
193 if not self.HasMore():
194 return None
195 if self.Current() == '(':
196 self.AddToken('(')
197 self.Advance()
198 elif self.Current() == ')':
199 self.AddToken(')')
200 self.Advance()
201 elif self.Current() == '$':
202 self.AddToken('$')
203 self.Advance()
204 elif self.Current() == ',':
205 self.AddToken(',')
206 self.Advance()
207 elif IsAlpha(self.Current()):
208 buf = ""
209 while self.HasMore() and IsAlpha(self.Current()):
210 buf += self.Current()
211 self.Advance()
212 self.AddToken(buf)
213 elif self.Current(2) == '&&':
214 self.AddToken('&&')
215 self.Advance(2)
216 elif self.Current(2) == '||':
217 self.AddToken('||')
218 self.Advance(2)
219 elif self.Current(2) == '==':
220 self.AddToken('==')
221 self.Advance(2)
222 elif self.Current(2) == '!=':
223 self.AddToken('!=')
224 self.Advance(2)
225 else:
226 return None
227 return self.tokens
228
229
230 class Scanner(object):
231 """A simple scanner that can serve out tokens from a given list"""
232
233 def __init__(self, tokens):
234 self.tokens = tokens
235 self.length = len(tokens)
236 self.index = 0
237
238 def HasMore(self):
239 return self.index < self.length
240
241 def Current(self):
242 return self.tokens[self.index]
243
244 def Advance(self):
245 self.index = self.index + 1
246
247
248 def ParseAtomicExpression(scan):
249 if scan.Current() == "true":
250 scan.Advance()
251 return Constant(True)
252 elif scan.Current() == "false":
253 scan.Advance()
254 return Constant(False)
255 elif IsAlpha(scan.Current()):
256 name = scan.Current()
257 scan.Advance()
258 return Outcome(name)
259 elif scan.Current() == '$':
260 scan.Advance()
261 if not IsAlpha(scan.Current()):
262 return None
263 name = scan.Current()
264 scan.Advance()
265 return Variable(name.lower())
266 elif scan.Current() == '(':
267 scan.Advance()
268 result = ParseLogicalExpression(scan)
269 if (not result) or (scan.Current() != ')'):
270 return None
271 scan.Advance()
272 return result
273 else:
274 return None
275
276
277 BINARIES = ['==', '!=']
278 def ParseOperatorExpression(scan):
279 left = ParseAtomicExpression(scan)
280 if not left: return None
281 while scan.HasMore() and (scan.Current() in BINARIES):
282 op = scan.Current()
283 scan.Advance()
284 right = ParseOperatorExpression(scan)
285 if not right:
286 return None
287 left = Operation(left, op, right)
288 return left
289
290
291 def ParseConditionalExpression(scan):
292 left = ParseOperatorExpression(scan)
293 if not left: return None
294 while scan.HasMore() and (scan.Current() == 'if'):
295 scan.Advance()
296 right = ParseOperatorExpression(scan)
297 if not right:
298 return None
299 left = Operation(left, 'if', right)
300 return left
301
302
303 LOGICALS = ["&&", "||", ","]
304 def ParseLogicalExpression(scan):
305 left = ParseConditionalExpression(scan)
306 if not left: return None
307 while scan.HasMore() and (scan.Current() in LOGICALS):
308 op = scan.Current()
309 scan.Advance()
310 right = ParseConditionalExpression(scan)
311 if not right:
312 return None
313 left = Operation(left, op, right)
314 return left
315
316
317 def ParseCondition(expr):
318 """Parses a logical expression into an Expression object"""
319 tokens = Tokenizer(expr).Tokenize()
320 if not tokens:
321 print "Malformed expression: '%s'" % expr
322 return None
323 scan = Scanner(tokens)
324 ast = ParseLogicalExpression(scan)
325 if not ast:
326 print "Malformed expression: '%s'" % expr
327 return None
328 if scan.HasMore():
329 print "Malformed expression: '%s'" % expr
330 return None
331 return ast
332
333
334 class Section(object):
335 """A section of the configuration file. Sections are enabled or
336 disabled prior to running the tests, based on their conditions"""
337
338 def __init__(self, condition):
339 self.condition = condition
340 self.rules = [ ]
341
342 def AddRule(self, rule):
343 self.rules.append(rule)
344
345
346 class Rule(object):
347 """A single rule that specifies the expected outcome for a single
348 test."""
349
350 def __init__(self, raw_path, path, value):
351 self.raw_path = raw_path
352 self.path = path
353 self.value = value
354
355 def GetOutcomes(self, env, defs):
356 return self.value.GetOutcomes(env, defs)
357
358 def Contains(self, path):
359 if len(self.path) > len(path):
360 return False
361 for i in xrange(len(self.path)):
362 if not self.path[i].match(path[i]):
363 return False
364 return True
365
366
367 HEADER_PATTERN = re.compile(r'\[([^]]+)\]')
368 RULE_PATTERN = re.compile(r'\s*([^: ]*)\s*:(.*)')
369 DEF_PATTERN = re.compile(r'^def\s*(\w+)\s*=(.*)$')
370 PREFIX_PATTERN = re.compile(r'^\s*prefix\s+([\w\_\.\-\/]+)$')
371
372
373 class ConvertNotation(object):
374 def __init__(self, path):
375 self.path = path
376 self.indent = ""
377 self.comment = []
378 self.init = False
379 self.section = False
380 self.out = cStringIO.StringIO()
381
382 def OpenGlobal(self):
383 if self.init: return
384 self.WriteComment()
385 print >> self.out, "["
386 self.init = True
387
388 def CloseGlobal(self):
389 if not self.init: return
390 print >> self.out, "]"
391 self.init = False
392
393 def OpenSection(self, condition="ALWAYS"):
394 if self.section: return
395 self.OpenGlobal()
396 if type(condition) != str:
397 condition = "'%s'" % condition.string(True)
398 print >> self.out, "%s[%s, {" % (self.indent, condition)
399 self.indent += " " * 2
400 self.section = condition
401
402 def CloseSection(self):
403 if not self.section: return
404 self.indent = self.indent[:-2]
405 print >> self.out, "%s}], # %s" % (self.indent, self.section)
406 self.section = False
407
408 def WriteComment(self):
409 if not self.comment: return
410 for c in self.comment:
411 if len(c.strip()) == 0:
412 print >> self.out, ""
413 else:
414 print >> self.out, "%s%s" % (self.indent, c),
415 self.comment = []
416
417 def GetOutput(self):
418 with open(self.path) as f:
419 for line in f:
420 if line[0] == '#':
421 self.comment += [line]
422 continue
423 if len(line.strip()) == 0:
424 self.comment += [line]
425 continue
426 header_match = HEADER_PATTERN.match(line)
427 if header_match:
428 condition = ParseCondition(header_match.group(1).strip())
429 self.CloseSection()
430 self.WriteComment()
431 self.OpenSection(condition)
432 continue
433 rule_match = RULE_PATTERN.match(line)
434 if rule_match:
435 self.OpenSection()
436 self.WriteComment()
437 path = rule_match.group(1).strip()
438 value_str = rule_match.group(2).strip()
439 comment = ""
440 if '#' in value_str:
441 pos = value_str.find('#')
442 comment = " %s" % value_str[pos:].strip()
443 value_str = value_str[:pos].strip()
444 value = ParseCondition(value_str)
445 print >> self.out, ("%s'%s': [%s],%s" %
446 (self.indent, path, value, comment))
447 continue
448 def_match = DEF_PATTERN.match(line)
449 if def_match:
450 # Custom definitions are deprecated.
451 continue
452 prefix_match = PREFIX_PATTERN.match(line)
453 if prefix_match:
454 continue
455 print "Malformed line: '%s'." % line
456 self.CloseSection()
457 self.CloseGlobal()
458 result = self.out.getvalue()
459 self.out.close()
460 return result
OLDNEW
« no previous file with comments | « tools/testrunner/local/execution.py ('k') | tools/testrunner/local/progress.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698