setup.py revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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 psutil
12import signal
13import shutil
14import time
15
16from pylib import android_commands
17from pylib import cmd_helper
18from pylib import constants
19from pylib import forwarder
20from pylib import ports
21
22import test_runner
23
24
25def _KillPendingServers():
26  for retry in range(5):
27    for server in ['lighttpd', 'web-page-replay']:
28      pids = [p.pid for p in psutil.process_iter() if server in p.name]
29      for pid in pids:
30        try:
31          logging.warning('Killing %s %s', server, pid)
32          os.kill(pid, signal.SIGQUIT)
33        except Exception as e:
34          logging.warning('Failed killing %s %s %s', server, pid, e)
35  # Restart the adb server with taskset to set a single CPU affinity.
36  cmd_helper.RunCmd(['adb', 'kill-server'])
37  cmd_helper.RunCmd(['taskset', '-c', '0', 'adb', 'start-server'])
38  cmd_helper.RunCmd(['taskset', '-c', '0', 'adb', 'root'])
39  i = 1
40  while not android_commands.GetAttachedDevices():
41    time.sleep(i)
42    i *= 2
43    if i > 10:
44      break
45  # Reset the test port allocation. It's important to do it before starting
46  # to dispatch any step.
47  if not ports.ResetTestServerPortAllocation():
48    raise Exception('Failed to reset test server port.')
49
50  forwarder.Forwarder.UseMultiprocessing()
51
52
53def Setup(test_options):
54  """Create and return the test runner factory and tests.
55
56  Args:
57    test_options: A PerformanceOptions object.
58
59  Returns:
60    A tuple of (TestRunnerFactory, tests).
61  """
62  if os.path.exists(constants.PERF_OUTPUT_DIR):
63    shutil.rmtree(constants.PERF_OUTPUT_DIR)
64  os.makedirs(constants.PERF_OUTPUT_DIR)
65
66  # Before running the tests, kill any leftover server.
67  _KillPendingServers()
68
69  with file(test_options.steps, 'r') as f:
70    tests = json.load(f)
71
72  # The list is necessary to keep the steps order, but internally
73  # the format is squashed from a list of lists into a single dict:
74  # [["A", "cmd"], ["B", "cmd"]] into {"A": "cmd", "B": "cmd"}
75  sorted_test_names = [i[0] for i in tests]
76  tests_dict = dict(tests)
77
78  if test_options.test_filter:
79    sorted_test_names = fnmatch.filter(sorted_test_names,
80                                       test_options.test_filter)
81    tests_dict = dict((k, v) for k, v in tests_dict.iteritems()
82                      if k in sorted_test_names)
83
84  flaky_steps = []
85  if test_options.flaky_steps:
86    with file(test_options.flaky_steps, 'r') as f:
87      flaky_steps = json.load(f)
88
89  def TestRunnerFactory(device, shard_index):
90    return test_runner.TestRunner(
91        test_options, device, tests_dict, flaky_steps)
92
93  return (TestRunnerFactory, sorted_test_names)
94