Ben Murdoch | 342c50c | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1 | # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Generates test runner factory and tests for performance tests.""" |
| 6 | |
| 7 | import json |
| 8 | import fnmatch |
| 9 | import logging |
| 10 | import os |
| 11 | import shutil |
| 12 | |
| 13 | from devil.android import device_list |
| 14 | from devil.android import device_utils |
| 15 | from pylib import constants |
| 16 | from pylib.perf import test_runner |
| 17 | from pylib.utils import test_environment |
| 18 | |
| 19 | |
| 20 | def _GetAllDevices(active_devices, devices_path): |
| 21 | # TODO(rnephew): Delete this when recipes change to pass file path. |
| 22 | if not devices_path: |
| 23 | logging.warning('Known devices file path not being passed. For device ' |
| 24 | 'affinity to work properly, it must be passed.') |
| 25 | devices_path = os.path.join(os.environ.get('CHROMIUM_OUT_DIR', 'out'), |
| 26 | device_list.LAST_DEVICES_FILENAME) |
| 27 | try: |
| 28 | if devices_path: |
| 29 | devices = [device_utils.DeviceUtils(s) |
| 30 | for s in device_list.GetPersistentDeviceList(devices_path)] |
| 31 | else: |
| 32 | logging.warning('Known devices file path not being passed. For device ' |
| 33 | 'affinity to work properly, it must be passed.') |
| 34 | devices = active_devices |
| 35 | except IOError as e: |
| 36 | logging.error('Unable to find %s [%s]', devices_path, e) |
| 37 | devices = active_devices |
| 38 | return sorted(devices) |
| 39 | |
| 40 | |
| 41 | def _GetStepsDictFromSingleStep(test_options): |
| 42 | # Running a single command, build the tests structure. |
| 43 | steps_dict = { |
| 44 | 'version': 1, |
| 45 | 'steps': { |
| 46 | 'single_step': { |
| 47 | 'device_affinity': 0, |
| 48 | 'cmd': test_options.single_step |
| 49 | }, |
| 50 | } |
| 51 | } |
| 52 | return steps_dict |
| 53 | |
| 54 | |
| 55 | def _GetStepsDict(test_options): |
| 56 | if test_options.single_step: |
| 57 | return _GetStepsDictFromSingleStep(test_options) |
| 58 | if test_options.steps: |
| 59 | with file(test_options.steps, 'r') as f: |
| 60 | steps = json.load(f) |
| 61 | |
| 62 | # Already using the new format. |
| 63 | assert steps['version'] == 1 |
| 64 | return steps |
| 65 | |
| 66 | |
| 67 | def Setup(test_options, active_devices): |
| 68 | """Create and return the test runner factory and tests. |
| 69 | |
| 70 | Args: |
| 71 | test_options: A PerformanceOptions object. |
| 72 | |
| 73 | Returns: |
| 74 | A tuple of (TestRunnerFactory, tests, devices). |
| 75 | """ |
| 76 | # TODO(bulach): remove this once the bot side lands. BUG=318369 |
| 77 | constants.SetBuildType('Release') |
| 78 | if os.path.exists(constants.PERF_OUTPUT_DIR): |
| 79 | shutil.rmtree(constants.PERF_OUTPUT_DIR) |
| 80 | os.makedirs(constants.PERF_OUTPUT_DIR) |
| 81 | |
| 82 | # Before running the tests, kill any leftover server. |
| 83 | test_environment.CleanupLeftoverProcesses(active_devices) |
| 84 | |
| 85 | # We want to keep device affinity, so return all devices ever seen. |
| 86 | all_devices = _GetAllDevices(active_devices, test_options.known_devices_file) |
| 87 | |
| 88 | steps_dict = _GetStepsDict(test_options) |
| 89 | sorted_step_names = sorted(steps_dict['steps'].keys()) |
| 90 | |
| 91 | if test_options.test_filter: |
| 92 | sorted_step_names = fnmatch.filter(sorted_step_names, |
| 93 | test_options.test_filter) |
| 94 | |
| 95 | flaky_steps = [] |
| 96 | if test_options.flaky_steps: |
| 97 | with file(test_options.flaky_steps, 'r') as f: |
| 98 | flaky_steps = json.load(f) |
| 99 | |
| 100 | def TestRunnerFactory(device, shard_index): |
| 101 | return test_runner.TestRunner( |
| 102 | test_options, device, shard_index, len(all_devices), |
| 103 | steps_dict, flaky_steps) |
| 104 | |
| 105 | return (TestRunnerFactory, sorted_step_names, all_devices) |