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
31import re
32import tempfile
33
34FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
35FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
36SELF_SCRIPT_PATTERN = re.compile(r"//\s+Env: TEST_FILE_NAME")
37
38
39class MjsunitTestCase(test.TestCase):
40
41  def __init__(self, path, file, mode, context, config, isolates):
42    super(MjsunitTestCase, self).__init__(context, path, mode)
43    self.file = file
44    self.config = config
45    self.self_script = False
46    self.isolates = isolates
47
48  def GetLabel(self):
49    return "%s %s" % (self.mode, self.GetName())
50
51  def GetName(self):
52    return self.path[-1] + ["", "-isolates"][self.isolates]
53
54  def TestsIsolates(self):
55    return self.isolates
56
57  def GetVmCommand(self, source):
58    result = self.config.context.GetVmCommand(self, self.mode)
59    flags_match = FLAGS_PATTERN.search(source)
60    if flags_match:
61      result += flags_match.group(1).strip().split()
62    return result
63
64  def GetVmArguments(self, source):
65    result = []
66    additional_files = []
67    files_match = FILES_PATTERN.search(source);
68    # Accept several lines of 'Files:'
69    while True:
70      if files_match:
71        additional_files += files_match.group(1).strip().split()
72        files_match = FILES_PATTERN.search(source, files_match.end())
73      else:
74        break
75    for a_file in additional_files:
76      result.append(join(dirname(self.config.root), '..', a_file))
77    framework = join(dirname(self.config.root), 'mjsunit', 'mjsunit.js')
78    if SELF_SCRIPT_PATTERN.search(source):
79      result.append(self.CreateSelfScript())
80    result += [framework, self.file]
81    return result
82
83  def GetCommand(self):
84    source = open(self.file).read()
85    result = self.GetVmCommand(source)
86    result += self.GetVmArguments(source)
87    if self.isolates:
88      result.append("--isolate")
89      result += self.GetVmArguments(source)
90    return result
91
92  def GetSource(self):
93    return open(self.file).read()
94
95  def CreateSelfScript(self):
96    (fd_self_script, self_script) = tempfile.mkstemp(suffix=".js")
97    def MakeJsConst(name, value):
98      return "var %(name)s=\'%(value)s\';\n" % \
99             {'name': name, \
100              'value': value.replace('\\', '\\\\').replace('\'', '\\\'') }
101    try:
102      os.write(fd_self_script, MakeJsConst('TEST_FILE_NAME', self.file))
103    except IOError, e:
104      test.PrintError("write() " + str(e))
105    os.close(fd_self_script)
106    self.self_script = self_script
107    return self_script
108
109  def AfterRun(self, result):
110    if self.self_script and (not result or (not result.HasPreciousOutput())):
111      test.CheckedUnlink(self.self_script)
112
113class MjsunitTestConfiguration(test.TestConfiguration):
114
115  def __init__(self, context, root):
116    super(MjsunitTestConfiguration, self).__init__(context, root)
117
118  def Ls(self, path):
119    def SelectTest(name):
120      return name.endswith('.js') and name != 'mjsunit.js'
121    return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
122
123  def ListTests(self, current_path, path, mode, variant_flags):
124    mjsunit = [current_path + [t] for t in self.Ls(self.root)]
125    regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
126    bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
127    third_party = [current_path + ['third_party', t] for t in self.Ls(join(self.root, 'third_party'))]
128    tools = [current_path + ['tools', t] for t in self.Ls(join(self.root, 'tools'))]
129    compiler = [current_path + ['compiler', t] for t in self.Ls(join(self.root, 'compiler'))]
130    harmony = [current_path + ['harmony', t] for t in self.Ls(join(self.root, 'harmony'))]
131    mjsunit.sort()
132    regress.sort()
133    bugs.sort()
134    third_party.sort()
135    tools.sort()
136    compiler.sort()
137    harmony.sort()
138    all_tests = mjsunit + regress + bugs + third_party + tools + compiler + harmony
139    result = []
140    for test in all_tests:
141      if self.Contains(path, test):
142        file_path = join(self.root, reduce(join, test[1:], "") + ".js")
143        result.append(MjsunitTestCase(test, file_path, mode, self.context, self, False))
144        result.append(MjsunitTestCase(test, file_path, mode, self.context, self, True))
145    return result
146
147  def GetBuildRequirements(self):
148    return ['d8']
149
150  def GetTestStatus(self, sections, defs):
151    status_file = join(self.root, 'mjsunit.status')
152    if exists(status_file):
153      test.ReadConfigurationInto(status_file, sections, defs)
154
155
156
157def GetConfiguration(context, root):
158  return MjsunitTestConfiguration(context, root)
159