Index: tools/testrunner/local/old_statusfile.py |
diff --git a/tools/testrunner/local/old_statusfile.py b/tools/testrunner/local/old_statusfile.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a16941b83b9bcbfec90817d40e91d1979b6c9aa7 |
--- /dev/null |
+++ b/tools/testrunner/local/old_statusfile.py |
@@ -0,0 +1,460 @@ |
+# Copyright 2012 the V8 project authors. All rights reserved. |
+# Redistribution and use in source and binary forms, with or without |
+# modification, are permitted provided that the following conditions are |
+# met: |
+# |
+# * Redistributions of source code must retain the above copyright |
+# notice, this list of conditions and the following disclaimer. |
+# * Redistributions in binary form must reproduce the above |
+# copyright notice, this list of conditions and the following |
+# disclaimer in the documentation and/or other materials provided |
+# with the distribution. |
+# * Neither the name of Google Inc. nor the names of its |
+# contributors may be used to endorse or promote products derived |
+# from this software without specific prior written permission. |
+# |
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+ |
+import cStringIO |
+import re |
+ |
+# These outcomes can occur in a TestCase's outcomes list: |
+SKIP = 'SKIP' |
+FAIL = 'FAIL' |
+PASS = 'PASS' |
+OKAY = 'OKAY' |
+TIMEOUT = 'TIMEOUT' |
+CRASH = 'CRASH' |
+SLOW = 'SLOW' |
+# These are just for the status files and are mapped below in DEFS: |
+FAIL_OK = 'FAIL_OK' |
+PASS_OR_FAIL = 'PASS_OR_FAIL' |
+ |
+KEYWORDS = {SKIP: SKIP, |
+ FAIL: FAIL, |
+ PASS: PASS, |
+ OKAY: OKAY, |
+ TIMEOUT: TIMEOUT, |
+ CRASH: CRASH, |
+ SLOW: SLOW, |
+ FAIL_OK: FAIL_OK, |
+ PASS_OR_FAIL: PASS_OR_FAIL} |
+ |
+class Expression(object): |
+ pass |
+ |
+ |
+class Constant(Expression): |
+ |
+ def __init__(self, value): |
+ self.value = value |
+ |
+ def Evaluate(self, env, defs): |
+ return self.value |
+ |
+ |
+class Variable(Expression): |
+ |
+ def __init__(self, name): |
+ self.name = name |
+ |
+ def GetOutcomes(self, env, defs): |
+ if self.name in env: return set([env[self.name]]) |
+ else: return set([]) |
+ |
+ def Evaluate(self, env, defs): |
+ return env[self.name] |
+ |
+ def __str__(self): |
+ return self.name |
+ |
+ def string(self, logical): |
+ return self.__str__() |
+ |
+ |
+class Outcome(Expression): |
+ |
+ def __init__(self, name): |
+ self.name = name |
+ |
+ def GetOutcomes(self, env, defs): |
+ if self.name in defs: |
+ return defs[self.name].GetOutcomes(env, defs) |
+ else: |
+ return set([self.name]) |
+ |
+ def __str__(self): |
+ if self.name in KEYWORDS: |
+ return "%s" % KEYWORDS[self.name] |
+ return "'%s'" % self.name |
+ |
+ def string(self, logical): |
+ if logical: |
+ return "%s" % self.name |
+ return self.__str__() |
+ |
+ |
+class Operation(Expression): |
+ |
+ def __init__(self, left, op, right): |
+ self.left = left |
+ self.op = op |
+ self.right = right |
+ |
+ def Evaluate(self, env, defs): |
+ if self.op == '||' or self.op == ',': |
+ return self.left.Evaluate(env, defs) or self.right.Evaluate(env, defs) |
+ elif self.op == 'if': |
+ return False |
+ elif self.op == '==': |
+ return not self.left.GetOutcomes(env, defs).isdisjoint(self.right.GetOutcomes(env, defs)) |
+ elif self.op == '!=': |
+ return self.left.GetOutcomes(env, defs).isdisjoint(self.right.GetOutcomes(env, defs)) |
+ else: |
+ assert self.op == '&&' |
+ return self.left.Evaluate(env, defs) and self.right.Evaluate(env, defs) |
+ |
+ def GetOutcomes(self, env, defs): |
+ if self.op == '||' or self.op == ',': |
+ return self.left.GetOutcomes(env, defs) | self.right.GetOutcomes(env, defs) |
+ elif self.op == 'if': |
+ if self.right.Evaluate(env, defs): return self.left.GetOutcomes(env, defs) |
+ else: return set([]) |
+ else: |
+ assert self.op == '&&' |
+ return self.left.GetOutcomes(env, defs) & self.right.GetOutcomes(env, defs) |
+ |
+ def __str__(self): |
+ return self.string(False) |
+ |
+ def string(self, logical=False): |
+ if self.op == 'if': |
+ return "['%s', %s]" % (self.right.string(True), self.left.string(logical)) |
+ elif self.op == "||" or self.op == ",": |
+ if logical: |
+ return "%s or %s" % (self.left.string(True), self.right.string(True)) |
+ else: |
+ return "%s, %s" % (self.left, self.right) |
+ elif self.op == "&&": |
+ return "%s and %s" % (self.left.string(True), self.right.string(True)) |
+ return "%s %s %s" % (self.left.string(logical), self.op, |
+ self.right.string(logical)) |
+ |
+ |
+def IsAlpha(string): |
+ for char in string: |
+ if not (char.isalpha() or char.isdigit() or char == '_'): |
+ return False |
+ return True |
+ |
+ |
+class Tokenizer(object): |
+ """A simple string tokenizer that chops expressions into variables, |
+ parens and operators""" |
+ |
+ def __init__(self, expr): |
+ self.index = 0 |
+ self.expr = expr |
+ self.length = len(expr) |
+ self.tokens = None |
+ |
+ def Current(self, length=1): |
+ if not self.HasMore(length): return "" |
+ return self.expr[self.index:self.index + length] |
+ |
+ def HasMore(self, length=1): |
+ return self.index < self.length + (length - 1) |
+ |
+ def Advance(self, count=1): |
+ self.index = self.index + count |
+ |
+ def AddToken(self, token): |
+ self.tokens.append(token) |
+ |
+ def SkipSpaces(self): |
+ while self.HasMore() and self.Current().isspace(): |
+ self.Advance() |
+ |
+ def Tokenize(self): |
+ self.tokens = [ ] |
+ while self.HasMore(): |
+ self.SkipSpaces() |
+ if not self.HasMore(): |
+ return None |
+ if self.Current() == '(': |
+ self.AddToken('(') |
+ self.Advance() |
+ elif self.Current() == ')': |
+ self.AddToken(')') |
+ self.Advance() |
+ elif self.Current() == '$': |
+ self.AddToken('$') |
+ self.Advance() |
+ elif self.Current() == ',': |
+ self.AddToken(',') |
+ self.Advance() |
+ elif IsAlpha(self.Current()): |
+ buf = "" |
+ while self.HasMore() and IsAlpha(self.Current()): |
+ buf += self.Current() |
+ self.Advance() |
+ self.AddToken(buf) |
+ elif self.Current(2) == '&&': |
+ self.AddToken('&&') |
+ self.Advance(2) |
+ elif self.Current(2) == '||': |
+ self.AddToken('||') |
+ self.Advance(2) |
+ elif self.Current(2) == '==': |
+ self.AddToken('==') |
+ self.Advance(2) |
+ elif self.Current(2) == '!=': |
+ self.AddToken('!=') |
+ self.Advance(2) |
+ else: |
+ return None |
+ return self.tokens |
+ |
+ |
+class Scanner(object): |
+ """A simple scanner that can serve out tokens from a given list""" |
+ |
+ def __init__(self, tokens): |
+ self.tokens = tokens |
+ self.length = len(tokens) |
+ self.index = 0 |
+ |
+ def HasMore(self): |
+ return self.index < self.length |
+ |
+ def Current(self): |
+ return self.tokens[self.index] |
+ |
+ def Advance(self): |
+ self.index = self.index + 1 |
+ |
+ |
+def ParseAtomicExpression(scan): |
+ if scan.Current() == "true": |
+ scan.Advance() |
+ return Constant(True) |
+ elif scan.Current() == "false": |
+ scan.Advance() |
+ return Constant(False) |
+ elif IsAlpha(scan.Current()): |
+ name = scan.Current() |
+ scan.Advance() |
+ return Outcome(name) |
+ elif scan.Current() == '$': |
+ scan.Advance() |
+ if not IsAlpha(scan.Current()): |
+ return None |
+ name = scan.Current() |
+ scan.Advance() |
+ return Variable(name.lower()) |
+ elif scan.Current() == '(': |
+ scan.Advance() |
+ result = ParseLogicalExpression(scan) |
+ if (not result) or (scan.Current() != ')'): |
+ return None |
+ scan.Advance() |
+ return result |
+ else: |
+ return None |
+ |
+ |
+BINARIES = ['==', '!='] |
+def ParseOperatorExpression(scan): |
+ left = ParseAtomicExpression(scan) |
+ if not left: return None |
+ while scan.HasMore() and (scan.Current() in BINARIES): |
+ op = scan.Current() |
+ scan.Advance() |
+ right = ParseOperatorExpression(scan) |
+ if not right: |
+ return None |
+ left = Operation(left, op, right) |
+ return left |
+ |
+ |
+def ParseConditionalExpression(scan): |
+ left = ParseOperatorExpression(scan) |
+ if not left: return None |
+ while scan.HasMore() and (scan.Current() == 'if'): |
+ scan.Advance() |
+ right = ParseOperatorExpression(scan) |
+ if not right: |
+ return None |
+ left = Operation(left, 'if', right) |
+ return left |
+ |
+ |
+LOGICALS = ["&&", "||", ","] |
+def ParseLogicalExpression(scan): |
+ left = ParseConditionalExpression(scan) |
+ if not left: return None |
+ while scan.HasMore() and (scan.Current() in LOGICALS): |
+ op = scan.Current() |
+ scan.Advance() |
+ right = ParseConditionalExpression(scan) |
+ if not right: |
+ return None |
+ left = Operation(left, op, right) |
+ return left |
+ |
+ |
+def ParseCondition(expr): |
+ """Parses a logical expression into an Expression object""" |
+ tokens = Tokenizer(expr).Tokenize() |
+ if not tokens: |
+ print "Malformed expression: '%s'" % expr |
+ return None |
+ scan = Scanner(tokens) |
+ ast = ParseLogicalExpression(scan) |
+ if not ast: |
+ print "Malformed expression: '%s'" % expr |
+ return None |
+ if scan.HasMore(): |
+ print "Malformed expression: '%s'" % expr |
+ return None |
+ return ast |
+ |
+ |
+class Section(object): |
+ """A section of the configuration file. Sections are enabled or |
+ disabled prior to running the tests, based on their conditions""" |
+ |
+ def __init__(self, condition): |
+ self.condition = condition |
+ self.rules = [ ] |
+ |
+ def AddRule(self, rule): |
+ self.rules.append(rule) |
+ |
+ |
+class Rule(object): |
+ """A single rule that specifies the expected outcome for a single |
+ test.""" |
+ |
+ def __init__(self, raw_path, path, value): |
+ self.raw_path = raw_path |
+ self.path = path |
+ self.value = value |
+ |
+ def GetOutcomes(self, env, defs): |
+ return self.value.GetOutcomes(env, defs) |
+ |
+ def Contains(self, path): |
+ if len(self.path) > len(path): |
+ return False |
+ for i in xrange(len(self.path)): |
+ if not self.path[i].match(path[i]): |
+ return False |
+ return True |
+ |
+ |
+HEADER_PATTERN = re.compile(r'\[([^]]+)\]') |
+RULE_PATTERN = re.compile(r'\s*([^: ]*)\s*:(.*)') |
+DEF_PATTERN = re.compile(r'^def\s*(\w+)\s*=(.*)$') |
+PREFIX_PATTERN = re.compile(r'^\s*prefix\s+([\w\_\.\-\/]+)$') |
+ |
+ |
+class ConvertNotation(object): |
+ def __init__(self, path): |
+ self.path = path |
+ self.indent = "" |
+ self.comment = [] |
+ self.init = False |
+ self.section = False |
+ self.out = cStringIO.StringIO() |
+ |
+ def OpenGlobal(self): |
+ if self.init: return |
+ self.WriteComment() |
+ print >> self.out, "[" |
+ self.init = True |
+ |
+ def CloseGlobal(self): |
+ if not self.init: return |
+ print >> self.out, "]" |
+ self.init = False |
+ |
+ def OpenSection(self, condition="ALWAYS"): |
+ if self.section: return |
+ self.OpenGlobal() |
+ if type(condition) != str: |
+ condition = "'%s'" % condition.string(True) |
+ print >> self.out, "%s[%s, {" % (self.indent, condition) |
+ self.indent += " " * 2 |
+ self.section = condition |
+ |
+ def CloseSection(self): |
+ if not self.section: return |
+ self.indent = self.indent[:-2] |
+ print >> self.out, "%s}], # %s" % (self.indent, self.section) |
+ self.section = False |
+ |
+ def WriteComment(self): |
+ if not self.comment: return |
+ for c in self.comment: |
+ if len(c.strip()) == 0: |
+ print >> self.out, "" |
+ else: |
+ print >> self.out, "%s%s" % (self.indent, c), |
+ self.comment = [] |
+ |
+ def GetOutput(self): |
+ with open(self.path) as f: |
+ for line in f: |
+ if line[0] == '#': |
+ self.comment += [line] |
+ continue |
+ if len(line.strip()) == 0: |
+ self.comment += [line] |
+ continue |
+ header_match = HEADER_PATTERN.match(line) |
+ if header_match: |
+ condition = ParseCondition(header_match.group(1).strip()) |
+ self.CloseSection() |
+ self.WriteComment() |
+ self.OpenSection(condition) |
+ continue |
+ rule_match = RULE_PATTERN.match(line) |
+ if rule_match: |
+ self.OpenSection() |
+ self.WriteComment() |
+ path = rule_match.group(1).strip() |
+ value_str = rule_match.group(2).strip() |
+ comment = "" |
+ if '#' in value_str: |
+ pos = value_str.find('#') |
+ comment = " %s" % value_str[pos:].strip() |
+ value_str = value_str[:pos].strip() |
+ value = ParseCondition(value_str) |
+ print >> self.out, ("%s'%s': [%s],%s" % |
+ (self.indent, path, value, comment)) |
+ continue |
+ def_match = DEF_PATTERN.match(line) |
+ if def_match: |
+ # Custom definitions are deprecated. |
+ continue |
+ prefix_match = PREFIX_PATTERN.match(line) |
+ if prefix_match: |
+ continue |
+ print "Malformed line: '%s'." % line |
+ self.CloseSection() |
+ self.CloseGlobal() |
+ result = self.out.getvalue() |
+ self.out.close() |
+ return result |