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 7import json 8import fnmatch 9import logging 10import os 11import shutil 12 13from devil.android import device_list 14from devil.android import device_utils 15from pylib import constants 16from pylib.perf import test_runner 17from pylib.utils import test_environment 18 19 20def _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 41def _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 55def _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 67def 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) 106