1# Copyright 2008 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 28import test 29import os 30from os.path import join, dirname, exists, basename, isdir 31import re 32 33FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") 34 35class MessageTestCase(test.TestCase): 36 37 def __init__(self, path, file, expected, mode, context, config): 38 super(MessageTestCase, self).__init__(context, path, mode) 39 self.file = file 40 self.expected = expected 41 self.config = config 42 43 def IgnoreLine(self, str): 44 """Ignore empty lines and valgrind output.""" 45 if not str: return True 46 else: return str.startswith('==') or str.startswith('**') 47 48 def IsFailureOutput(self, output): 49 f = file(self.expected) 50 # Skip initial '#' comment and spaces 51 for line in f: 52 if (not line.startswith('#')) and (not line.strip()): 53 break 54 # Convert output lines to regexps that we can match 55 env = { 'basename': basename(self.file) } 56 patterns = [ ] 57 for line in f: 58 if not line.strip(): 59 continue 60 pattern = re.escape(line.rstrip() % env) 61 pattern = pattern.replace('\\*', '.*') 62 pattern = '^%s$' % pattern 63 patterns.append(pattern) 64 # Compare actual output with the expected 65 raw_lines = output.stdout.split('\n') 66 outlines = [ s for s in raw_lines if not self.IgnoreLine(s) ] 67 if len(outlines) != len(patterns): 68 return True 69 for i in xrange(len(patterns)): 70 if not re.match(patterns[i], outlines[i]): 71 return True 72 return False 73 74 def GetLabel(self): 75 return "%s %s" % (self.mode, self.GetName()) 76 77 def GetName(self): 78 return self.path[-1] 79 80 def GetCommand(self): 81 result = self.config.context.GetVmCommand(self, self.mode) 82 source = open(self.file).read() 83 flags_match = FLAGS_PATTERN.search(source) 84 if flags_match: 85 result += flags_match.group(1).strip().split() 86 result.append(self.file) 87 return result 88 89 def GetSource(self): 90 return (open(self.file).read() 91 + "\n--- expected output ---\n" 92 + open(self.expected).read()) 93 94 95class MessageTestConfiguration(test.TestConfiguration): 96 97 def __init__(self, context, root): 98 super(MessageTestConfiguration, self).__init__(context, root) 99 100 def Ls(self, path): 101 if isdir(path): 102 return [f[:-3] for f in os.listdir(path) if f.endswith('.js')] 103 else: 104 return [] 105 106 def ListTests(self, current_path, path, mode, variant_flags): 107 mjsunit = [current_path + [t] for t in self.Ls(self.root)] 108 regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))] 109 bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))] 110 mjsunit.sort() 111 regress.sort() 112 bugs.sort() 113 all_tests = mjsunit + regress + bugs 114 result = [] 115 for test in all_tests: 116 if self.Contains(path, test): 117 file_prefix = join(self.root, reduce(join, test[1:], "")) 118 file_path = file_prefix + ".js" 119 output_path = file_prefix + ".out" 120 if not exists(output_path): 121 print "Could not find %s" % output_path 122 continue 123 result.append(MessageTestCase(test, file_path, output_path, mode, 124 self.context, self)) 125 return result 126 127 def GetBuildRequirements(self): 128 return ['d8'] 129 130 def GetTestStatus(self, sections, defs): 131 status_file = join(self.root, 'message.status') 132 if exists(status_file): 133 test.ReadConfigurationInto(status_file, sections, defs) 134 135 136def GetConfiguration(context, root): 137 return MessageTestConfiguration(context, root) 138