blob: 1aa1c228f0ae2f1485ec6e42952f478be7f28419 [file] [log] [blame]
kbr213b4f22015-11-26 00:49:281#!/usr/bin/env python
2# Copyright 2015 The Chromium 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.
5
6"""Runs an isolate bundled Telemetry benchmark.
7
8This script attempts to emulate the contract of gtest-style tests
9invoked via recipes. The main contract is that the caller passes the
10argument:
11
12 --isolated-script-test-output=[FILENAME]
13
Ashley Enstad8148f5f2017-08-02 03:08:5714json is written to that file in the format detailed here:
15https://www.chromium.org/developers/the-json-test-results-format
kbr213b4f22015-11-26 00:49:2816
Kenneth Russell40274052017-11-14 00:57:4417Optional argument:
18
Kenneth Russella649a46122017-11-21 06:39:5919 --isolated-script-test-filter=[TEST_NAMES]
Kenneth Russell40274052017-11-14 00:57:4420
Kenneth Russella649a46122017-11-21 06:39:5921is a double-colon-separated ("::") list of test names, to run just that subset
22of tests. This list is parsed by this harness and sent down via the
23--story-filter argument.
Kenneth Russell40274052017-11-14 00:57:4424
kbr213b4f22015-11-26 00:49:2825This script is intended to be the base command invoked by the isolate,
26followed by a subsequent Python script. It could be generalized to
27invoke an arbitrary executable.
Kenneth Russella649a46122017-11-21 06:39:5928
kbr213b4f22015-11-26 00:49:2829"""
30
31import argparse
32import json
33import os
34import shutil
35import sys
36import tempfile
37import traceback
38
39import common
40
41# Add src/testing/ into sys.path for importing xvfb.
42sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
43import xvfb
nednguyena8950e42018-05-18 22:42:0644import test_env
kbr213b4f22015-11-26 00:49:2845
kbr00ab61a2015-12-08 05:06:3346# Unfortunately we need to copy these variables from ../test_env.py.
47# Importing it and using its get_sandbox_env breaks test runs on Linux
48# (it seems to unset DISPLAY).
49CHROME_SANDBOX_ENV = 'CHROME_DEVEL_SANDBOX'
50CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox'
kbr213b4f22015-11-26 00:49:2851
52def main():
53 parser = argparse.ArgumentParser()
54 parser.add_argument(
55 '--isolated-script-test-output', type=argparse.FileType('w'),
56 required=True)
eyaich4e297012016-09-20 13:40:4857 parser.add_argument(
eyaichda48d3aa2016-09-23 18:42:5158 '--isolated-script-test-chartjson-output', required=False)
Ethan Kuefner9d009517232017-08-14 20:56:4259 parser.add_argument(
60 '--isolated-script-test-perf-output', required=False)
Kenneth Russell40274052017-11-14 00:57:4461 parser.add_argument(
Kenneth Russella649a46122017-11-21 06:39:5962 '--isolated-script-test-filter', type=str, required=False)
kbr213b4f22015-11-26 00:49:2863 parser.add_argument('--xvfb', help='Start xvfb.', action='store_true')
Dave Tuaabd0b32017-08-24 08:11:2964 parser.add_argument('--output-format', action='append')
kbr213b4f22015-11-26 00:49:2865 args, rest_args = parser.parse_known_args()
Dave Tuaabd0b32017-08-24 08:11:2966 for output_format in args.output_format:
67 rest_args.append('--output-format=' + output_format)
Stephen Martinis0b18efa102017-09-25 22:55:1268
nednguyena8950e42018-05-18 22:42:0669 rc, perf_results, json_test_results, _ = run_benchmark(args, rest_args,
Emily Hanley69ccba22018-02-09 20:15:2570 'histograms' in args.output_format)
Stephen Martinis0b18efa102017-09-25 22:55:1271
Ethan Kuefnereaf808252017-09-26 21:13:2072 if perf_results:
Stephen Martinis0b18efa102017-09-25 22:55:1273 if args.isolated_script_test_perf_output:
74 filename = args.isolated_script_test_perf_output
75 elif args.isolated_script_test_chartjson_output:
76 filename = args.isolated_script_test_chartjson_output
77 else:
78 filename = None
79
80 if filename is not None:
Ethan Kuefnereaf808252017-09-26 21:13:2081 with open(filename, 'w') as perf_results_output_file:
82 json.dump(perf_results, perf_results_output_file)
Stephen Martinis0b18efa102017-09-25 22:55:1283
84 json.dump(json_test_results, args.isolated_script_test_output)
85
86 return rc
87
Emily Hanley69ccba22018-02-09 20:15:2588def run_benchmark(args, rest_args, histogram_results):
nednguyena8950e42018-05-18 22:42:0689 """ Run benchmark with args.
90
91 Args:
92 args: the option object resulted from parsing commandline args required for
93 IsolatedScriptTest contract (see
94 https://cs.chromium.org/chromium/build/scripts/slave/recipe_modules/chromium_tests/steps.py?rcl=d31f256fb860701e6dc02544f2beffe4e17c9b92&l=1639).
95 rest_args: the args (list of strings) for running Telemetry benchmark.
96 histogram_results: a boolean describes whether to output histograms format
97 for the benchmark.
98
99 Returns: a tuple of (rc, perf_results, json_test_results, benchmark_log)
100 rc: the return code of benchmark
101 perf_results: json object contains the perf test results
102 json_test_results: json object contains the Pass/Fail data of the benchmark.
103 benchmark_log: string contains the stdout/stderr of the benchmark run.
104 """
kbr213b4f22015-11-26 00:49:28105 env = os.environ.copy()
Dirk Prankeeb695f62017-12-18 23:16:31106 env['CHROME_HEADLESS'] = '1'
107
kbr00ab61a2015-12-08 05:06:33108 # Assume we want to set up the sandbox environment variables all the
109 # time; doing so is harmless on non-Linux platforms and is needed
110 # all the time on Linux.
111 env[CHROME_SANDBOX_ENV] = CHROME_SANDBOX_PATH
Yuzhu Shen0fdf0202017-08-01 20:14:01112 tempfile_dir = tempfile.mkdtemp('telemetry')
nednguyena8950e42018-05-18 22:42:06113 benchmark_log = ''
114 stdoutfile = os.path.join(tempfile_dir, 'benchmark_log.txt')
Yuzhu Shen0fdf0202017-08-01 20:14:01115 valid = True
Ashley Enstad8148f5f2017-08-02 03:08:57116 num_failures = 0
Ethan Kuefnereaf808252017-09-26 21:13:20117 perf_results = None
Yuzhu Shen0fdf0202017-08-01 20:14:01118 json_test_results = None
119
120 results = None
Kenneth Russell40274052017-11-14 00:57:44121 cmd_args = rest_args
Kenneth Russella649a46122017-11-21 06:39:59122 if args.isolated_script_test_filter:
123 filter_list = common.extract_filter_list(args.isolated_script_test_filter)
Kenneth Russell40274052017-11-14 00:57:44124 # Need to convert this to a valid regex.
125 filter_regex = '(' + '|'.join(filter_list) + ')'
126 cmd_args = cmd_args + [
127 '--story-filter=' + filter_regex
128 ]
kbr213b4f22015-11-26 00:49:28129 try:
Kenneth Russell40274052017-11-14 00:57:44130 cmd = [sys.executable] + cmd_args + [
Yuzhu Shen0fdf0202017-08-01 20:14:01131 '--output-dir', tempfile_dir,
132 '--output-format=json-test-results',
133 ]
134 if args.xvfb:
nednguyena8950e42018-05-18 22:42:06135 rc = xvfb.run_executable(cmd, env=env, stdoutfile=stdoutfile)
Yuzhu Shen0fdf0202017-08-01 20:14:01136 else:
nednguyena8950e42018-05-18 22:42:06137 rc = test_env.run_command_with_output(cmd, env=env, stdoutfile=stdoutfile)
138
139 with open(stdoutfile) as f:
140 benchmark_log = f.read()
martinissbe66fed2017-04-04 01:22:01141
Yuzhu Shen0fdf0202017-08-01 20:14:01142 # If we have also output chartjson read it in and return it.
143 # results-chart.json is the file name output by telemetry when the
144 # chartjson output format is included
Emily Hanley69ccba22018-02-09 20:15:25145 tempfile_name = None
146 if histogram_results:
Ethan Kuefnereaf808252017-09-26 21:13:20147 tempfile_name = os.path.join(tempfile_dir, 'histograms.json')
Ethan Kuefnereaf808252017-09-26 21:13:20148 else:
Emily Hanley69ccba22018-02-09 20:15:25149 tempfile_name = os.path.join(tempfile_dir, 'results-chart.json')
Ethan Kuefnereaf808252017-09-26 21:13:20150
151 if tempfile_name is not None:
152 with open(tempfile_name) as f:
153 perf_results = json.load(f)
ashleymarie1b0335db2017-07-12 16:14:01154
Ashley Enstad81d004bf32017-08-07 15:52:57155 # test-results.json is the file name output by telemetry when the
156 # json-test-results format is included
157 tempfile_name = os.path.join(tempfile_dir, 'test-results.json')
158 with open(tempfile_name) as f:
159 json_test_results = json.load(f)
160 num_failures = json_test_results['num_failures_by_type'].get('FAIL', 0)
161 valid = bool(rc == 0 or num_failures != 0)
Ashley Enstad8148f5f2017-08-02 03:08:57162
Yuzhu Shen0fdf0202017-08-01 20:14:01163 except Exception:
164 traceback.print_exc()
165 if results:
166 print 'results, which possibly caused exception: %s' % json.dumps(
167 results, indent=2)
168 valid = False
kbr213b4f22015-11-26 00:49:28169 finally:
Ned Nguyenafc2ba22018-07-20 14:39:53170 # Add ignore_errors=True because otherwise rmtree may fail due to leaky
171 # processes of tests are still holding opened handles to files under
172 # |tempfile_dir|. For example, see crbug.com/865896
173 shutil.rmtree(tempfile_dir, ignore_errors=True)
Yuzhu Shen0fdf0202017-08-01 20:14:01174
Ashley Enstad8148f5f2017-08-02 03:08:57175 if not valid and num_failures == 0:
Yuzhu Shen0fdf0202017-08-01 20:14:01176 if rc == 0:
177 rc = 1 # Signal an abnormal exit.
178
nednguyena8950e42018-05-18 22:42:06179 return rc, perf_results, json_test_results, benchmark_log
kbr213b4f22015-11-26 00:49:28180
181
182# This is not really a "script test" so does not need to manually add
183# any additional compile targets.
184def main_compile_targets(args):
185 json.dump([], args.output)
186
187
188if __name__ == '__main__':
189 # Conform minimally to the protocol defined by ScriptTest.
190 if 'compile_targets' in sys.argv:
191 funcs = {
192 'run': None,
193 'compile_targets': main_compile_targets,
194 }
195 sys.exit(common.run_script(sys.argv[1:], funcs))
196 sys.exit(main())