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

Side by Side Diff: tools/run_perf.py

Issue 1215273003: [test] Let perf runner interleave try executions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Review Created 5 years, 5 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
« no previous file with comments | « no previous file | tools/unittests/run_perf_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2014 the V8 project authors. All rights reserved. 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 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """ 6 """
7 Performance runner for d8. 7 Performance runner for d8.
8 8
9 Call e.g. with tools/run-perf.py --arch ia32 some_suite.json 9 Call e.g. with tools/run-perf.py --arch ia32 some_suite.json
10 10
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 208
209 def GetResults(self): 209 def GetResults(self):
210 return Results([{ 210 return Results([{
211 "graphs": self.graphs, 211 "graphs": self.graphs,
212 "units": self.units, 212 "units": self.units,
213 "results": self.results, 213 "results": self.results,
214 "stddev": self.stddev, 214 "stddev": self.stddev,
215 }], self.errors) 215 }], self.errors)
216 216
217 217
218 def AccumulateResults(graph_names, trace_configs, iter_output, calc_total): 218 class NullMeasurement(object):
219 """Null object to avoid having extra logic for configurations that didn't
220 run like running without patch on trybots.
221 """
222 def ConsumeOutput(self, stdout):
223 pass
224
225 def GetResults(self):
226 return Results()
227
228
229 def Unzip(iterable):
230 left = []
231 right = []
232 for l, r in iterable:
233 left.append(l)
234 right.append(r)
235 return lambda: iter(left), lambda: iter(right)
236
237
238 def AccumulateResults(
239 graph_names, trace_configs, iter_output, trybot, no_patch, calc_total):
219 """Iterates over the output of multiple benchmark reruns and accumulates 240 """Iterates over the output of multiple benchmark reruns and accumulates
220 results for a configured list of traces. 241 results for a configured list of traces.
221 242
222 Args: 243 Args:
223 graph_names: List of names that configure the base path of the traces. E.g. 244 graph_names: List of names that configure the base path of the traces. E.g.
224 ['v8', 'Octane']. 245 ['v8', 'Octane'].
225 trace_configs: List of "TraceConfig" instances. Each trace config defines 246 trace_configs: List of "TraceConfig" instances. Each trace config defines
226 how to perform a measurement. 247 how to perform a measurement.
227 iter_output: Iterator over the standard output of each test run. 248 iter_output: Iterator over the standard output of each test run.
249 trybot: Indicates that this is run in trybot mode, i.e. run twice, once
250 with once without patch.
251 no_patch: Indicates weather this is a trybot run without patch.
228 calc_total: Boolean flag to speficy the calculation of a summary trace. 252 calc_total: Boolean flag to speficy the calculation of a summary trace.
229 Returns: A "Results" object. 253 Returns: A "Results" object.
230 """ 254 """
231 measurements = [trace.CreateMeasurement() for trace in trace_configs] 255 measurements = [
256 trace.CreateMeasurement(trybot, no_patch) for trace in trace_configs]
232 for stdout in iter_output(): 257 for stdout in iter_output():
233 for measurement in measurements: 258 for measurement in measurements:
234 measurement.ConsumeOutput(stdout) 259 measurement.ConsumeOutput(stdout)
235 260
236 res = reduce(lambda r, m: r + m.GetResults(), measurements, Results()) 261 res = reduce(lambda r, m: r + m.GetResults(), measurements, Results())
237 262
238 if not res.traces or not calc_total: 263 if not res.traces or not calc_total:
239 return res 264 return res
240 265
241 # Assume all traces have the same structure. 266 # Assume all traces have the same structure.
(...skipping 22 matching lines...) Expand all
264 289
265 Args: 290 Args:
266 graph_names: List of names that configure the base path of the traces. E.g. 291 graph_names: List of names that configure the base path of the traces. E.g.
267 ['v8', 'Octane']. 292 ['v8', 'Octane'].
268 suite_units: Measurement default units as defined by the benchmark suite. 293 suite_units: Measurement default units as defined by the benchmark suite.
269 iter_output: Iterator over the standard output of each test run. 294 iter_output: Iterator over the standard output of each test run.
270 Returns: A "Results" object. 295 Returns: A "Results" object.
271 """ 296 """
272 traces = OrderedDict() 297 traces = OrderedDict()
273 for stdout in iter_output(): 298 for stdout in iter_output():
299 if stdout is None:
300 # The None value is used as a null object to simplify logic.
301 continue
274 for line in stdout.strip().splitlines(): 302 for line in stdout.strip().splitlines():
275 match = GENERIC_RESULTS_RE.match(line) 303 match = GENERIC_RESULTS_RE.match(line)
276 if match: 304 if match:
277 stddev = "" 305 stddev = ""
278 graph = match.group(1) 306 graph = match.group(1)
279 trace = match.group(2) 307 trace = match.group(2)
280 body = match.group(3) 308 body = match.group(3)
281 units = match.group(4) 309 units = match.group(4)
282 match_stddev = RESULT_STDDEV_RE.match(body) 310 match_stddev = RESULT_STDDEV_RE.match(body)
283 match_list = RESULT_LIST_RE.match(body) 311 match_list = RESULT_LIST_RE.match(body)
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 stddev_default = None 415 stddev_default = None
388 self.stddev_regexp = suite.get("stddev_regexp", stddev_default) 416 self.stddev_regexp = suite.get("stddev_regexp", stddev_default)
389 417
390 418
391 class TraceConfig(GraphConfig): 419 class TraceConfig(GraphConfig):
392 """Represents a leaf in the suite tree structure.""" 420 """Represents a leaf in the suite tree structure."""
393 def __init__(self, suite, parent, arch): 421 def __init__(self, suite, parent, arch):
394 super(TraceConfig, self).__init__(suite, parent, arch) 422 super(TraceConfig, self).__init__(suite, parent, arch)
395 assert self.results_regexp 423 assert self.results_regexp
396 424
397 def CreateMeasurement(self): 425 def CreateMeasurement(self, trybot, no_patch):
426 if not trybot and no_patch:
427 # Use null object for no-patch logic if this is not a trybot run.
428 return NullMeasurement()
429
398 return Measurement( 430 return Measurement(
399 self.graphs, 431 self.graphs,
400 self.units, 432 self.units,
401 self.results_regexp, 433 self.results_regexp,
402 self.stddev_regexp, 434 self.stddev_regexp,
403 ) 435 )
404 436
405 437
406 class RunnableConfig(GraphConfig): 438 class RunnableConfig(GraphConfig):
407 """Represents a runnable suite definition (i.e. has a main file). 439 """Represents a runnable suite definition (i.e. has a main file).
(...skipping 13 matching lines...) Expand all
421 453
422 def GetCommandFlags(self, extra_flags=None): 454 def GetCommandFlags(self, extra_flags=None):
423 suffix = ["--"] + self.test_flags if self.test_flags else [] 455 suffix = ["--"] + self.test_flags if self.test_flags else []
424 return self.flags + (extra_flags or []) + [self.main] + suffix 456 return self.flags + (extra_flags or []) + [self.main] + suffix
425 457
426 def GetCommand(self, shell_dir, extra_flags=None): 458 def GetCommand(self, shell_dir, extra_flags=None):
427 # TODO(machenbach): This requires +.exe if run on windows. 459 # TODO(machenbach): This requires +.exe if run on windows.
428 cmd = [os.path.join(shell_dir, self.binary)] 460 cmd = [os.path.join(shell_dir, self.binary)]
429 return cmd + self.GetCommandFlags(extra_flags=extra_flags) 461 return cmd + self.GetCommandFlags(extra_flags=extra_flags)
430 462
431 def Run(self, runner): 463 def Run(self, runner, trybot):
432 """Iterates over several runs and handles the output for all traces.""" 464 """Iterates over several runs and handles the output for all traces."""
433 return AccumulateResults(self.graphs, self._children, runner, self.total) 465 stdout_with_patch, stdout_no_patch = Unzip(runner())
466 return (
467 AccumulateResults(
468 self.graphs,
469 self._children,
470 iter_output=stdout_with_patch,
471 trybot=trybot,
472 no_patch=False,
473 calc_total=self.total,
474 ),
475 AccumulateResults(
476 self.graphs,
477 self._children,
478 iter_output=stdout_no_patch,
479 trybot=trybot,
480 no_patch=True,
481 calc_total=self.total,
482 ),
483 )
434 484
435 485
436 class RunnableTraceConfig(TraceConfig, RunnableConfig): 486 class RunnableTraceConfig(TraceConfig, RunnableConfig):
437 """Represents a runnable suite definition that is a leaf.""" 487 """Represents a runnable suite definition that is a leaf."""
438 def __init__(self, suite, parent, arch): 488 def __init__(self, suite, parent, arch):
439 super(RunnableTraceConfig, self).__init__(suite, parent, arch) 489 super(RunnableTraceConfig, self).__init__(suite, parent, arch)
440 490
441 def Run(self, runner): 491 def Run(self, runner, trybot):
442 """Iterates over several runs and handles the output.""" 492 """Iterates over several runs and handles the output."""
443 measurement = self.CreateMeasurement() 493 measurement_with_patch = self.CreateMeasurement(trybot, False)
444 for stdout in runner(): 494 measurement_no_patch = self.CreateMeasurement(trybot, True)
445 measurement.ConsumeOutput(stdout) 495 for stdout_with_patch, stdout_no_patch in runner():
446 return measurement.GetResults() 496 measurement_with_patch.ConsumeOutput(stdout_with_patch)
497 measurement_no_patch.ConsumeOutput(stdout_no_patch)
498 return (
499 measurement_with_patch.GetResults(),
500 measurement_no_patch.GetResults(),
501 )
447 502
448 503
449 class RunnableGenericConfig(RunnableConfig): 504 class RunnableGenericConfig(RunnableConfig):
450 """Represents a runnable suite definition with generic traces.""" 505 """Represents a runnable suite definition with generic traces."""
451 def __init__(self, suite, parent, arch): 506 def __init__(self, suite, parent, arch):
452 super(RunnableGenericConfig, self).__init__(suite, parent, arch) 507 super(RunnableGenericConfig, self).__init__(suite, parent, arch)
453 508
454 def Run(self, runner): 509 def Run(self, runner, trybot):
455 return AccumulateGenericResults(self.graphs, self.units, runner) 510 stdout_with_patch, stdout_no_patch = Unzip(runner())
511 return (
512 AccumulateGenericResults(self.graphs, self.units, stdout_with_patch),
513 AccumulateGenericResults(self.graphs, self.units, stdout_no_patch),
514 )
456 515
457 516
458 def MakeGraphConfig(suite, arch, parent): 517 def MakeGraphConfig(suite, arch, parent):
459 """Factory method for making graph configuration objects.""" 518 """Factory method for making graph configuration objects."""
460 if isinstance(parent, RunnableConfig): 519 if isinstance(parent, RunnableConfig):
461 # Below a runnable can only be traces. 520 # Below a runnable can only be traces.
462 return TraceConfig(suite, parent, arch) 521 return TraceConfig(suite, parent, arch)
463 elif suite.get("main") is not None: 522 elif suite.get("main") is not None:
464 # A main file makes this graph runnable. Empty strings are accepted. 523 # A main file makes this graph runnable. Empty strings are accepted.
465 if suite.get("tests"): 524 if suite.get("tests"):
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 for child in node._children: 566 for child in node._children:
508 for result in FlattenRunnables(child, node_cb): 567 for result in FlattenRunnables(child, node_cb):
509 yield result 568 yield result
510 else: # pragma: no cover 569 else: # pragma: no cover
511 raise Exception("Invalid suite configuration.") 570 raise Exception("Invalid suite configuration.")
512 571
513 572
514 class Platform(object): 573 class Platform(object):
515 def __init__(self, options): 574 def __init__(self, options):
516 self.shell_dir = options.shell_dir 575 self.shell_dir = options.shell_dir
576 self.shell_dir_no_patch = options.shell_dir_no_patch
517 self.extra_flags = options.extra_flags.split() 577 self.extra_flags = options.extra_flags.split()
518 578
519 @staticmethod 579 @staticmethod
520 def GetPlatform(options): 580 def GetPlatform(options):
521 if options.android_build_tools: 581 if options.android_build_tools:
522 return AndroidPlatform(options) 582 return AndroidPlatform(options)
523 else: 583 else:
524 return DesktopPlatform(options) 584 return DesktopPlatform(options)
525 585
586 def _Run(self, runnable, count, no_patch=False):
587 raise NotImplementedError() # pragma: no cover
588
589 def Run(self, runnable, count):
590 """Execute the benchmark's main file.
591
592 If options.shell_dir_no_patch is specified, the benchmark is run once with
593 and once without patch.
594 Args:
595 runnable: A Runnable benchmark instance.
596 count: The number of this (repeated) run.
597 Returns: A tuple with the benchmark outputs with and without patch. The
598 latter will be None if options.shell_dir_no_patch was not
599 specified.
600 """
601 stdout = self._Run(runnable, count, no_patch=False)
602 if self.shell_dir_no_patch:
603 return stdout, self._Run(runnable, count, no_patch=True)
604 else:
605 return stdout, None
606
526 607
527 class DesktopPlatform(Platform): 608 class DesktopPlatform(Platform):
528 def __init__(self, options): 609 def __init__(self, options):
529 super(DesktopPlatform, self).__init__(options) 610 super(DesktopPlatform, self).__init__(options)
530 611
531 def PreExecution(self): 612 def PreExecution(self):
532 pass 613 pass
533 614
534 def PostExecution(self): 615 def PostExecution(self):
535 pass 616 pass
536 617
537 def PreTests(self, node, path): 618 def PreTests(self, node, path):
538 if isinstance(node, RunnableConfig): 619 if isinstance(node, RunnableConfig):
539 node.ChangeCWD(path) 620 node.ChangeCWD(path)
540 621
541 def Run(self, runnable, count): 622 def _Run(self, runnable, count, no_patch=False):
623 suffix = ' - without patch' if no_patch else ''
624 shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir
625 title = ">>> %%s (#%d)%s:" % ((count + 1), suffix)
542 try: 626 try:
543 output = commands.Execute( 627 output = commands.Execute(
544 runnable.GetCommand(self.shell_dir, self.extra_flags), 628 runnable.GetCommand(shell_dir, self.extra_flags),
545 timeout=runnable.timeout, 629 timeout=runnable.timeout,
546 ) 630 )
547 except OSError as e: 631 except OSError as e: # pragma: no cover
548 print ">>> OSError (#%d):" % (count + 1) 632 print title % "OSError"
549 print e 633 print e
550 return "" 634 return ""
551 print ">>> Stdout (#%d):" % (count + 1) 635 print title % "Stdout"
552 print output.stdout 636 print output.stdout
553 if output.stderr: # pragma: no cover 637 if output.stderr: # pragma: no cover
554 # Print stderr for debugging. 638 # Print stderr for debugging.
555 print ">>> Stderr (#%d):" % (count + 1) 639 print title % "Stderr"
556 print output.stderr 640 print output.stderr
557 if output.timed_out: 641 if output.timed_out:
558 print ">>> Test timed out after %ss." % runnable.timeout 642 print ">>> Test timed out after %ss." % runnable.timeout
559 return output.stdout 643 return output.stdout
560 644
561 645
562 class AndroidPlatform(Platform): # pragma: no cover 646 class AndroidPlatform(Platform): # pragma: no cover
563 DEVICE_DIR = "/data/local/tmp/v8/" 647 DEVICE_DIR = "/data/local/tmp/v8/"
564 648
565 def __init__(self, options): 649 def __init__(self, options):
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 # location and then copy them with a shell command. 703 # location and then copy them with a shell command.
620 output = self._SendCommand( 704 output = self._SendCommand(
621 "push %s %s" % (file_on_host, file_on_device_tmp)) 705 "push %s %s" % (file_on_host, file_on_device_tmp))
622 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)". 706 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)".
623 # Errors look like this: "failed to copy ... ". 707 # Errors look like this: "failed to copy ... ".
624 if output and not re.search('^[0-9]', output.splitlines()[-1]): 708 if output and not re.search('^[0-9]', output.splitlines()[-1]):
625 logging.critical('PUSH FAILED: ' + output) 709 logging.critical('PUSH FAILED: ' + output)
626 self._SendCommand("shell mkdir -p %s" % folder_on_device) 710 self._SendCommand("shell mkdir -p %s" % folder_on_device)
627 self._SendCommand("shell cp %s %s" % (file_on_device_tmp, file_on_device)) 711 self._SendCommand("shell cp %s %s" % (file_on_device_tmp, file_on_device))
628 712
713 def _PushExecutable(self, shell_dir, target_dir, binary):
714 self._PushFile(shell_dir, binary, target_dir)
715
716 # Push external startup data. Backwards compatible for revisions where
717 # these files didn't exist.
718 self._PushFile(
719 shell_dir,
720 "natives_blob.bin",
721 target_dir,
722 skip_if_missing=True,
723 )
724 self._PushFile(
725 shell_dir,
726 "snapshot_blob.bin",
727 target_dir,
728 skip_if_missing=True,
729 )
730
629 def PreTests(self, node, path): 731 def PreTests(self, node, path):
630 suite_dir = os.path.abspath(os.path.dirname(path)) 732 suite_dir = os.path.abspath(os.path.dirname(path))
631 if node.path: 733 if node.path:
632 bench_rel = os.path.normpath(os.path.join(*node.path)) 734 bench_rel = os.path.normpath(os.path.join(*node.path))
633 bench_abs = os.path.join(suite_dir, bench_rel) 735 bench_abs = os.path.join(suite_dir, bench_rel)
634 else: 736 else:
635 bench_rel = "." 737 bench_rel = "."
636 bench_abs = suite_dir 738 bench_abs = suite_dir
637 739
638 self._PushFile(self.shell_dir, node.binary, "bin") 740 self._PushExecutable(self.shell_dir, "bin", node.binary)
639 741 if self.shell_dir_no_patch:
640 # Push external startup data. Backwards compatible for revisions where 742 self._PushExecutable(
641 # these files didn't exist. 743 self.shell_dir_no_patch, "bin_no_patch", node.binary)
642 self._PushFile(
643 self.shell_dir,
644 "natives_blob.bin",
645 "bin",
646 skip_if_missing=True,
647 )
648 self._PushFile(
649 self.shell_dir,
650 "snapshot_blob.bin",
651 "bin",
652 skip_if_missing=True,
653 )
654 744
655 if isinstance(node, RunnableConfig): 745 if isinstance(node, RunnableConfig):
656 self._PushFile(bench_abs, node.main, bench_rel) 746 self._PushFile(bench_abs, node.main, bench_rel)
657 for resource in node.resources: 747 for resource in node.resources:
658 self._PushFile(bench_abs, resource, bench_rel) 748 self._PushFile(bench_abs, resource, bench_rel)
659 749
660 def Run(self, runnable, count): 750 def _Run(self, runnable, count, no_patch=False):
751 suffix = ' - without patch' if no_patch else ''
752 target_dir = "bin_no_patch" if no_patch else "bin"
753 title = ">>> %%s (#%d)%s:" % ((count + 1), suffix)
661 cache = cache_control.CacheControl(self.device) 754 cache = cache_control.CacheControl(self.device)
662 cache.DropRamCaches() 755 cache.DropRamCaches()
663 binary_on_device = os.path.join( 756 binary_on_device = os.path.join(
664 AndroidPlatform.DEVICE_DIR, "bin", runnable.binary) 757 AndroidPlatform.DEVICE_DIR, target_dir, runnable.binary)
665 cmd = [binary_on_device] + runnable.GetCommandFlags(self.extra_flags) 758 cmd = [binary_on_device] + runnable.GetCommandFlags(self.extra_flags)
666 759
667 # Relative path to benchmark directory. 760 # Relative path to benchmark directory.
668 if runnable.path: 761 if runnable.path:
669 bench_rel = os.path.normpath(os.path.join(*runnable.path)) 762 bench_rel = os.path.normpath(os.path.join(*runnable.path))
670 else: 763 else:
671 bench_rel = "." 764 bench_rel = "."
672 765
673 try: 766 try:
674 output = self.device.RunShellCommand( 767 output = self.device.RunShellCommand(
675 cmd, 768 cmd,
676 cwd=os.path.join(AndroidPlatform.DEVICE_DIR, bench_rel), 769 cwd=os.path.join(AndroidPlatform.DEVICE_DIR, bench_rel),
677 timeout=runnable.timeout, 770 timeout=runnable.timeout,
678 retries=0, 771 retries=0,
679 ) 772 )
680 stdout = "\n".join(output) 773 stdout = "\n".join(output)
681 print ">>> Stdout (#%d):" % (count + 1) 774 print title % "Stdout"
682 print stdout 775 print stdout
683 except device_errors.CommandTimeoutError: 776 except device_errors.CommandTimeoutError:
684 print ">>> Test timed out after %ss." % runnable.timeout 777 print ">>> Test timed out after %ss." % runnable.timeout
685 stdout = "" 778 stdout = ""
686 return stdout 779 return stdout
687 780
688 781
689 # TODO: Implement results_processor. 782 # TODO: Implement results_processor.
690 def Main(args): 783 def Main(args):
691 logging.getLogger().setLevel(logging.INFO) 784 logging.getLogger().setLevel(logging.INFO)
692 parser = optparse.OptionParser() 785 parser = optparse.OptionParser()
693 parser.add_option("--android-build-tools", 786 parser.add_option("--android-build-tools",
694 help="Path to chromium's build/android. Specifying this " 787 help="Path to chromium's build/android. Specifying this "
695 "option will run tests using android platform.") 788 "option will run tests using android platform.")
696 parser.add_option("--arch", 789 parser.add_option("--arch",
697 help=("The architecture to run tests for, " 790 help=("The architecture to run tests for, "
698 "'auto' or 'native' for auto-detect"), 791 "'auto' or 'native' for auto-detect"),
699 default="x64") 792 default="x64")
700 parser.add_option("--buildbot", 793 parser.add_option("--buildbot",
701 help="Adapt to path structure used on buildbots", 794 help="Adapt to path structure used on buildbots",
702 default=False, action="store_true") 795 default=False, action="store_true")
703 parser.add_option("--device", 796 parser.add_option("--device",
704 help="The device ID to run Android tests on. If not given " 797 help="The device ID to run Android tests on. If not given "
705 "it will be autodetected.") 798 "it will be autodetected.")
706 parser.add_option("--extra-flags", 799 parser.add_option("--extra-flags",
707 help="Additional flags to pass to the test executable", 800 help="Additional flags to pass to the test executable",
708 default="") 801 default="")
709 parser.add_option("--json-test-results", 802 parser.add_option("--json-test-results",
710 help="Path to a file for storing json results.") 803 help="Path to a file for storing json results.")
804 parser.add_option("--json-test-results-no-patch",
805 help="Path to a file for storing json results from run "
806 "without patch.")
711 parser.add_option("--outdir", help="Base directory with compile output", 807 parser.add_option("--outdir", help="Base directory with compile output",
712 default="out") 808 default="out")
809 parser.add_option("--outdir-no-patch",
810 help="Base directory with compile output without patch")
713 (options, args) = parser.parse_args(args) 811 (options, args) = parser.parse_args(args)
714 812
715 if len(args) == 0: # pragma: no cover 813 if len(args) == 0: # pragma: no cover
716 parser.print_help() 814 parser.print_help()
717 return 1 815 return 1
718 816
719 if options.arch in ["auto", "native"]: # pragma: no cover 817 if options.arch in ["auto", "native"]: # pragma: no cover
720 options.arch = ARCH_GUESS 818 options.arch = ARCH_GUESS
721 819
722 if not options.arch in SUPPORTED_ARCHS: # pragma: no cover 820 if not options.arch in SUPPORTED_ARCHS: # pragma: no cover
723 print "Unknown architecture %s" % options.arch 821 print "Unknown architecture %s" % options.arch
724 return 1 822 return 1
725 823
726 if (options.device and not options.android_build_tools): # pragma: no cover 824 if options.device and not options.android_build_tools: # pragma: no cover
727 print "Specifying a device requires Android build tools." 825 print "Specifying a device requires Android build tools."
728 return 1 826 return 1
729 827
828 if (options.json_test_results_no_patch and
829 not options.outdir_no_patch): # pragma: no cover
830 print("For writing json test results without patch, an outdir without "
831 "patch must be specified.")
832 return 1
833
730 workspace = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) 834 workspace = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
731 835
732 if options.buildbot: 836 if options.buildbot:
733 options.shell_dir = os.path.join(workspace, options.outdir, "Release") 837 build_config = "Release"
734 else: 838 else:
735 options.shell_dir = os.path.join(workspace, options.outdir, 839 build_config = "%s.release" % options.arch
736 "%s.release" % options.arch) 840
841 options.shell_dir = os.path.join(workspace, options.outdir, build_config)
842
843 if options.outdir_no_patch:
844 options.shell_dir_no_patch = os.path.join(
845 workspace, options.outdir_no_patch, build_config)
846 else:
847 options.shell_dir_no_patch = None
737 848
738 platform = Platform.GetPlatform(options) 849 platform = Platform.GetPlatform(options)
739 850
740 results = Results() 851 results = Results()
852 results_no_patch = Results()
741 for path in args: 853 for path in args:
742 path = os.path.abspath(path) 854 path = os.path.abspath(path)
743 855
744 if not os.path.exists(path): # pragma: no cover 856 if not os.path.exists(path): # pragma: no cover
745 results.errors.append("Configuration file %s does not exist." % path) 857 results.errors.append("Configuration file %s does not exist." % path)
746 continue 858 continue
747 859
748 with open(path) as f: 860 with open(path) as f:
749 suite = json.loads(f.read()) 861 suite = json.loads(f.read())
750 862
(...skipping 15 matching lines...) Expand all
766 print ">>> Running suite: %s" % "/".join(runnable.graphs) 878 print ">>> Running suite: %s" % "/".join(runnable.graphs)
767 879
768 def Runner(): 880 def Runner():
769 """Output generator that reruns several times.""" 881 """Output generator that reruns several times."""
770 for i in xrange(0, max(1, runnable.run_count)): 882 for i in xrange(0, max(1, runnable.run_count)):
771 # TODO(machenbach): Allow timeout per arch like with run_count per 883 # TODO(machenbach): Allow timeout per arch like with run_count per
772 # arch. 884 # arch.
773 yield platform.Run(runnable, i) 885 yield platform.Run(runnable, i)
774 886
775 # Let runnable iterate over all runs and handle output. 887 # Let runnable iterate over all runs and handle output.
776 results += runnable.Run(Runner) 888 result, result_no_patch = runnable.Run(
777 889 Runner, trybot=options.shell_dir_no_patch)
890 results += result
891 results_no_patch += result_no_patch
778 platform.PostExecution() 892 platform.PostExecution()
779 893
780 if options.json_test_results: 894 if options.json_test_results:
781 results.WriteToFile(options.json_test_results) 895 results.WriteToFile(options.json_test_results)
782 else: # pragma: no cover 896 else: # pragma: no cover
783 print results 897 print results
784 898
899 if options.json_test_results_no_patch:
900 results_no_patch.WriteToFile(options.json_test_results_no_patch)
901 else: # pragma: no cover
902 print results_no_patch
903
785 return min(1, len(results.errors)) 904 return min(1, len(results.errors))
786 905
787 if __name__ == "__main__": # pragma: no cover 906 if __name__ == "__main__": # pragma: no cover
788 sys.exit(Main(sys.argv[1:])) 907 sys.exit(Main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | tools/unittests/run_perf_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698