Commit 36607112 authored by Xiyuan Xia's avatar Xiyuan Xia Committed by Commit Bot

cros: Run gtest perf test on device

- 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: default avatarBen Pastene <bpastene@chromium.org>
Reviewed-by: default avatarCaleb Rouleau <crouleau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726402}
parent 28067db8
...@@ -412,6 +412,7 @@ class GTestTest(RemoteTest): ...@@ -412,6 +412,7 @@ class GTestTest(RemoteTest):
self._on_device_script = None self._on_device_script = None
self._stop_ui = args.stop_ui self._stop_ui = args.stop_ui
self._trace_dir = args.trace_dir
@property @property
def suite_name(self): def suite_name(self):
...@@ -443,6 +444,22 @@ class GTestTest(RemoteTest): ...@@ -443,6 +444,22 @@ class GTestTest(RemoteTest):
result_dir, 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. # Build the shell script that will be used on the device to invoke the test.
device_test_script_contents = self.BASIC_SHELL_SCRIPT[:] device_test_script_contents = self.BASIC_SHELL_SCRIPT[:]
if self._llvm_profile_var: if self._llvm_profile_var:
...@@ -468,6 +485,14 @@ class GTestTest(RemoteTest): ...@@ -468,6 +485,14 @@ class GTestTest(RemoteTest):
if self._test_launcher_summary_output: if self._test_launcher_summary_output:
test_invocation += ' --test-launcher-summary-output=%s' % ( test_invocation += ' --test-launcher-summary-output=%s' % (
device_result_file) 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: if self._additional_args:
test_invocation += ' %s' % ' '.join(self._additional_args) test_invocation += ' %s' % ' '.join(self._additional_args)
...@@ -805,6 +830,11 @@ def main(): ...@@ -805,6 +830,11 @@ def main():
'--stop-ui', '--stop-ui',
action='store_true', action='store_true',
help='Will stop the UI service in the device before running the test.') 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. # Tast test args.
# pylint: disable=line-too-long # pylint: disable=line-too-long
......
...@@ -8,6 +8,7 @@ Runs gtest and processes traces (run metrics) to produce perf results. ...@@ -8,6 +8,7 @@ Runs gtest and processes traces (run metrics) to produce perf results.
""" """
import argparse import argparse
import json
import os import os
import shutil import shutil
import sys import sys
...@@ -49,8 +50,40 @@ def RunGTest(options, gtest_args): ...@@ -49,8 +50,40 @@ def RunGTest(options, gtest_args):
return return_code 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): 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 = [ result_files = [
os.path.join(trace_dir, trace) os.path.join(trace_dir, trace)
for trace in os.listdir(trace_dir) for trace in os.listdir(trace_dir)
...@@ -61,7 +94,7 @@ def _MergeResultsJson(trace_dir, output_file): ...@@ -61,7 +94,7 @@ def _MergeResultsJson(trace_dir, output_file):
with open(result_file) as f: with open(result_file) as f:
stripped_lines = [line.rstrip() for line in f] stripped_lines = [line.rstrip() for line in f]
for line in stripped_lines: for line in stripped_lines:
output.write('%s\n' % line) output.write('%s\n' % _MapDeviceTracePath(trace_dir, line))
def ProcessResults(options): def ProcessResults(options):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment