2 # Copyright 2014 the V8 project authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 from collections import namedtuple
9 from mock import DEFAULT
10 from mock import MagicMock
12 from os import path, sys
17 # Requires python-coverage and python-mock. Native python coverage
18 # version >= 3.7.1 should be installed to get the best speed.
20 TEST_WORKSPACE = path.join(tempfile.gettempdir(), "test-v8-run-benchmarks")
28 "results_regexp": "^%s: (.+)$",
31 {"name": "DeltaBlue"},
35 V8_NESTED_SUITES_JSON = {
45 "resources": ["file1.js", "file2.js"],
47 "results_regexp": "^Richards: (.+)$"},
56 "results_regexp": "^Simple: (.+) ms.$"},
60 "path": ["delta_blue"],
63 "results_regexp": "^DeltaBlue: (.+)$"},
64 {"name": "ShouldntRun",
71 Output = namedtuple("Output", "stdout, stderr")
73 class BenchmarksTest(unittest.TestCase):
76 cls.base = path.dirname(path.dirname(path.abspath(__file__)))
77 sys.path.append(cls.base)
78 cls._cov = coverage.coverage(
79 include=([os.path.join(cls.base, "run_benchmarks.py")]))
82 from testrunner.local import commands
87 def tearDownClass(cls):
90 print cls._cov.report()
94 if path.exists(TEST_WORKSPACE):
95 shutil.rmtree(TEST_WORKSPACE)
96 os.makedirs(TEST_WORKSPACE)
99 if path.exists(TEST_WORKSPACE):
100 shutil.rmtree(TEST_WORKSPACE)
102 def _WriteTestInput(self, json_content):
103 self._test_input = path.join(TEST_WORKSPACE, "test.json")
104 with open(self._test_input, "w") as f:
105 f.write(json.dumps(json_content))
107 def _MockCommand(self, *args):
108 # Fake output for each benchmark run.
109 benchmark_outputs = [Output(stdout=arg, stderr=None) for arg in args[1]]
110 def execute(*args, **kwargs):
111 return benchmark_outputs.pop()
112 commands.Execute = MagicMock(side_effect=execute)
114 # Check that d8 is called from the correct cwd for each benchmark run.
115 dirs = [path.join(TEST_WORKSPACE, arg) for arg in args[0]]
116 def chdir(*args, **kwargs):
117 self.assertEquals(dirs.pop(), args[0])
118 os.chdir = MagicMock(side_effect=chdir)
120 def _CallMain(self, *args):
121 self._test_output = path.join(TEST_WORKSPACE, "results.json")
123 "--json-test-results",
128 return run_benchmarks.Main(all_args)
130 def _LoadResults(self):
131 with open(self._test_output) as f:
134 def _VerifyResults(self, suite, units, traces):
137 "graphs": [suite, trace["name"]],
138 "results": trace["results"],
139 "stddev": trace["stddev"]} for trace in traces],
140 self._LoadResults()["traces"])
142 def _VerifyErrors(self, errors):
143 self.assertEquals(errors, self._LoadResults()["errors"])
145 def _VerifyMock(self, binary, *args):
146 arg = [path.join(path.dirname(self.base), binary)]
148 commands.Execute.assert_called_with(arg, timeout=60)
150 def _VerifyMockMultiple(self, *args):
153 a = [path.join(path.dirname(self.base), arg[0])]
155 expected.append(((a,), {"timeout": 60}))
156 self.assertEquals(expected, commands.Execute.call_args_list)
158 def testOneRun(self):
159 self._WriteTestInput(V8_JSON)
160 self._MockCommand(["."], ["x\nRichards: 1.234\nDeltaBlue: 10657567\ny\n"])
161 self.assertEquals(0, self._CallMain())
162 self._VerifyResults("test", "score", [
163 {"name": "Richards", "results": ["1.234"], "stddev": ""},
164 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""},
166 self._VerifyErrors([])
167 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js")
169 def testTwoRuns_Units_SuiteName(self):
170 test_input = dict(V8_JSON)
171 test_input["run_count"] = 2
172 test_input["name"] = "v8"
173 test_input["units"] = "ms"
174 self._WriteTestInput(test_input)
175 self._MockCommand([".", "."],
176 ["Richards: 100\nDeltaBlue: 200\n",
177 "Richards: 50\nDeltaBlue: 300\n"])
178 self.assertEquals(0, self._CallMain())
179 self._VerifyResults("v8", "ms", [
180 {"name": "Richards", "results": ["50", "100"], "stddev": ""},
181 {"name": "DeltaBlue", "results": ["300", "200"], "stddev": ""},
183 self._VerifyErrors([])
184 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js")
186 def testTwoRuns_SubRegexp(self):
187 test_input = dict(V8_JSON)
188 test_input["run_count"] = 2
189 del test_input["results_regexp"]
190 test_input["benchmarks"][0]["results_regexp"] = "^Richards: (.+)$"
191 test_input["benchmarks"][1]["results_regexp"] = "^DeltaBlue: (.+)$"
192 self._WriteTestInput(test_input)
193 self._MockCommand([".", "."],
194 ["Richards: 100\nDeltaBlue: 200\n",
195 "Richards: 50\nDeltaBlue: 300\n"])
196 self.assertEquals(0, self._CallMain())
197 self._VerifyResults("test", "score", [
198 {"name": "Richards", "results": ["50", "100"], "stddev": ""},
199 {"name": "DeltaBlue", "results": ["300", "200"], "stddev": ""},
201 self._VerifyErrors([])
202 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js")
204 def testNestedSuite(self):
205 self._WriteTestInput(V8_NESTED_SUITES_JSON)
206 self._MockCommand(["delta_blue", "sub/leaf", "richards"],
213 self.assertEquals(0, self._CallMain())
216 "graphs": ["test", "Richards"],
217 "results": ["50", "100"],
220 "graphs": ["test", "Sub", "Leaf"],
221 "results": ["3", "2", "1"],
224 "graphs": ["test", "DeltaBlue"],
227 ], self._LoadResults()["traces"])
228 self._VerifyErrors([])
229 self._VerifyMockMultiple(
230 (path.join("out", "x64.release", "d7"), "--flag", "file1.js",
231 "file2.js", "run.js"),
232 (path.join("out", "x64.release", "d7"), "--flag", "file1.js",
233 "file2.js", "run.js"),
234 (path.join("out", "x64.release", "d8"), "--flag", "run.js"),
235 (path.join("out", "x64.release", "d8"), "--flag", "run.js"),
236 (path.join("out", "x64.release", "d8"), "--flag", "run.js"),
237 (path.join("out", "x64.release", "d8"), "--flag", "--flag2", "run.js"))
239 def testOneRunStdDevRegExp(self):
240 test_input = dict(V8_JSON)
241 test_input["stddev_regexp"] = "^%s\-stddev: (.+)$"
242 self._WriteTestInput(test_input)
243 self._MockCommand(["."], ["Richards: 1.234\nRichards-stddev: 0.23\n"
244 "DeltaBlue: 10657567\nDeltaBlue-stddev: 106\n"])
245 self.assertEquals(0, self._CallMain())
246 self._VerifyResults("test", "score", [
247 {"name": "Richards", "results": ["1.234"], "stddev": "0.23"},
248 {"name": "DeltaBlue", "results": ["10657567"], "stddev": "106"},
250 self._VerifyErrors([])
251 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js")
253 def testTwoRunsStdDevRegExp(self):
254 test_input = dict(V8_JSON)
255 test_input["stddev_regexp"] = "^%s\-stddev: (.+)$"
256 test_input["run_count"] = 2
257 self._WriteTestInput(test_input)
258 self._MockCommand(["."], ["Richards: 3\nRichards-stddev: 0.7\n"
259 "DeltaBlue: 6\nDeltaBlue-boom: 0.9\n",
260 "Richards: 2\nRichards-stddev: 0.5\n"
261 "DeltaBlue: 5\nDeltaBlue-stddev: 0.8\n"])
262 self.assertEquals(1, self._CallMain())
263 self._VerifyResults("test", "score", [
264 {"name": "Richards", "results": ["2", "3"], "stddev": "0.7"},
265 {"name": "DeltaBlue", "results": ["5", "6"], "stddev": "0.8"},
268 ["Benchmark Richards should only run once since a stddev is provided "
270 "Benchmark DeltaBlue should only run once since a stddev is provided "
272 "Regexp \"^DeltaBlue\-stddev: (.+)$\" didn't match for benchmark "
274 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js")
276 def testBuildbot(self):
277 self._WriteTestInput(V8_JSON)
278 self._MockCommand(["."], ["Richards: 1.234\nDeltaBlue: 10657567\n"])
279 self.assertEquals(0, self._CallMain("--buildbot"))
280 self._VerifyResults("test", "score", [
281 {"name": "Richards", "results": ["1.234"], "stddev": ""},
282 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""},
284 self._VerifyErrors([])
285 self._VerifyMock(path.join("out", "Release", "d7"), "--flag", "run.js")
287 def testRegexpNoMatch(self):
288 self._WriteTestInput(V8_JSON)
289 self._MockCommand(["."], ["x\nRichaards: 1.234\nDeltaBlue: 10657567\ny\n"])
290 self.assertEquals(1, self._CallMain())
291 self._VerifyResults("test", "score", [
292 {"name": "Richards", "results": [], "stddev": ""},
293 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""},
296 ["Regexp \"^Richards: (.+)$\" didn't match for benchmark Richards."])
297 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js")