Skip to content

Commit

Permalink
cros: Run gtest perf test on device
Browse files Browse the repository at this point in the history
- Add --trace-dir=PATH to chromeos/test_runner.py
  When present, test_runner script passes the switch with
  device local path (e.g. /tmp) to gtest to generate trace
  file on device and collects the trace files back to PATH
  on host afterwards.
- Update run_gtest_benchmark.py to map the trace file path
  in the test result json collected by test_runner script
  so that processor scripts could find and computer metrics
  from the trace file.

Example usage:

For developers:
  tools/perf/run_gtest_benchmark.py
    out_${SDK_BOARD}/Release/bin/run_interactive_ui_tests
    --device=$DUT
    --gtest_filter=All/OverviewAnimationsTest.EnterExit/7
    --output-dir=/tmp/perf_output
    --output-format=histograms
    --dbus-stub --stop-ui

For perf bots:
  testing/scripts/run_performance_tests.py
    --isolated-script-test-output=/tmp/perf_output/output.json
    --non-telemetry=true
    --use-gtest-benchmark-script
    --gtest-benchmark-name=interactive_ui_tests
    tools/perf/run_gtest_benchmark.py
      out_${SDK_BOARD}/Release/bin/run_interactive_ui_tests
      --device=$DUT
      --output-format=histograms
      --dbus-stub --stop-ui

Bug: 945711
Change-Id: Ia6911921b8354d7763be96c30a8877c9d598f103
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1974587
Commit-Queue: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Ben Pastene <bpastene@chromium.org>
Reviewed-by: Caleb Rouleau <crouleau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726402}
  • Loading branch information
Xiyuan Xia authored and Commit Bot committed Dec 19, 2019
1 parent 28067db commit 3660711
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
30 changes: 30 additions & 0 deletions build/chromeos/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ def __init__(self, args, unknown_args):

self._on_device_script = None
self._stop_ui = args.stop_ui
self._trace_dir = args.trace_dir

@property
def suite_name(self):
Expand Down Expand Up @@ -443,6 +444,22 @@ def build_test_command(self):
result_dir,
]

if self._trace_dir and self._logs_dir:
trace_path = os.path.dirname(self._trace_dir) or '.'
if os.path.abspath(trace_path) != os.path.abspath(self._logs_dir):
raise TestFormatError(
'--trace-dir and --logs-dir must point to the same directory.')

if self._trace_dir:
trace_path, trace_dirname = os.path.split(self._trace_dir)
device_trace_dir = '/tmp/%s' % trace_dirname
self._test_cmd += [
'--results-src',
device_trace_dir,
'--results-dest-dir',
trace_path,
]

# Build the shell script that will be used on the device to invoke the test.
device_test_script_contents = self.BASIC_SHELL_SCRIPT[:]
if self._llvm_profile_var:
Expand All @@ -468,6 +485,14 @@ def build_test_command(self):
if self._test_launcher_summary_output:
test_invocation += ' --test-launcher-summary-output=%s' % (
device_result_file)

if self._trace_dir:
device_test_script_contents.extend([
'rm -rf %s' % device_trace_dir,
'su chronos -c -- "mkdir -p %s"' % device_trace_dir,
])
test_invocation += ' --trace-dir=%s' % device_trace_dir

if self._additional_args:
test_invocation += ' %s' % ' '.join(self._additional_args)

Expand Down Expand Up @@ -805,6 +830,11 @@ def main():
'--stop-ui',
action='store_true',
help='Will stop the UI service in the device before running the test.')
gtest_parser.add_argument(
'--trace-dir',
type=str,
help='When set, will pass down to the test to generate the trace and '
'retrieve the trace files to the specified location.')

# Tast test args.
# pylint: disable=line-too-long
Expand Down
37 changes: 35 additions & 2 deletions tools/perf/run_gtest_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""

import argparse
import json
import os
import shutil
import sys
Expand Down Expand Up @@ -49,8 +50,40 @@ def RunGTest(options, gtest_args):
return return_code


def _MapDeviceTracePath(trace_dir, result_json):
"""Maps trace file paths to |trace_dir|. It is needed when gtest runs
on a real device and trace file is the absolute path on the device. If
gtest runs on a bot, the returned result should be the same as input.
Args:
result_json: JSON string of a test result.
Returns the JSON string of a LUCI test result with trace file path mapped.
"""
result = json.loads(result_json)
test_result = result.get('testResult', {})
artifacts = test_result.get('outputArtifacts', {})
trace_names = [name for name in artifacts if name.startswith('trace/')]
for name in trace_names:
trace_file = artifacts[name]['filePath']
trace_file = os.path.join(trace_dir, os.path.basename(trace_file))
artifacts[name]['filePath'] = trace_file

if artifacts:
result['testResult']['outputArtifacts'] = artifacts

return json.dumps(result)


def _MergeResultsJson(trace_dir, output_file):
"""Merge results json files generated in each test case into output_file."""
"""Merge results json files generated in each test case into output_file.
Gtest test cases store results in LUCI test results format.
See: go/luci-test-results-design
This function reads the individual LUCI test results JSON files and
concatenates them into a jsonl file to feed result processor scripts later on.
"""
result_files = [
os.path.join(trace_dir, trace)
for trace in os.listdir(trace_dir)
Expand All @@ -61,7 +94,7 @@ def _MergeResultsJson(trace_dir, output_file):
with open(result_file) as f:
stripped_lines = [line.rstrip() for line in f]
for line in stripped_lines:
output.write('%s\n' % line)
output.write('%s\n' % _MapDeviceTracePath(trace_dir, line))


def ProcessResults(options):
Expand Down

0 comments on commit 3660711

Please sign in to comment.