media/webrtc/trunk/build/android/pylib/base_test_runner.py

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

michael@0 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 # Use of this source code is governed by a BSD-style license that can be
michael@0 3 # found in the LICENSE file.
michael@0 4
michael@0 5 import contextlib
michael@0 6 import httplib
michael@0 7 import logging
michael@0 8 import os
michael@0 9 import tempfile
michael@0 10 import time
michael@0 11
michael@0 12 import android_commands
michael@0 13 import constants
michael@0 14 from chrome_test_server_spawner import SpawningServer
michael@0 15 import constants
michael@0 16 from flag_changer import FlagChanger
michael@0 17 from forwarder import Forwarder
michael@0 18 import lighttpd_server
michael@0 19 import ports
michael@0 20 from valgrind_tools import CreateTool
michael@0 21
michael@0 22
michael@0 23 # A file on device to store ports of net test server. The format of the file is
michael@0 24 # test-spawner-server-port:test-server-port
michael@0 25 NET_TEST_SERVER_PORT_INFO_FILE = 'net-test-server-ports'
michael@0 26
michael@0 27
michael@0 28 class BaseTestRunner(object):
michael@0 29 """Base class for running tests on a single device.
michael@0 30
michael@0 31 A subclass should implement RunTests() with no parameter, so that calling
michael@0 32 the Run() method will set up tests, run them and tear them down.
michael@0 33 """
michael@0 34
michael@0 35 def __init__(self, device, tool, shard_index, build_type):
michael@0 36 """
michael@0 37 Args:
michael@0 38 device: Tests will run on the device of this ID.
michael@0 39 shard_index: Index number of the shard on which the test suite will run.
michael@0 40 build_type: 'Release' or 'Debug'.
michael@0 41 """
michael@0 42 self.device = device
michael@0 43 self.adb = android_commands.AndroidCommands(device=device)
michael@0 44 self.tool = CreateTool(tool, self.adb)
michael@0 45 self._http_server = None
michael@0 46 self._forwarder = None
michael@0 47 self._forwarder_device_port = 8000
michael@0 48 self.forwarder_base_url = ('http://localhost:%d' %
michael@0 49 self._forwarder_device_port)
michael@0 50 self.flags = FlagChanger(self.adb)
michael@0 51 self.shard_index = shard_index
michael@0 52 self.flags.AddFlags(['--disable-fre'])
michael@0 53 self._spawning_server = None
michael@0 54 self._spawner_forwarder = None
michael@0 55 # We will allocate port for test server spawner when calling method
michael@0 56 # LaunchChromeTestServerSpawner and allocate port for test server when
michael@0 57 # starting it in TestServerThread.
michael@0 58 self.test_server_spawner_port = 0
michael@0 59 self.test_server_port = 0
michael@0 60 self.build_type = build_type
michael@0 61
michael@0 62 def _PushTestServerPortInfoToDevice(self):
michael@0 63 """Pushes the latest port information to device."""
michael@0 64 self.adb.SetFileContents(self.adb.GetExternalStorage() + '/' +
michael@0 65 NET_TEST_SERVER_PORT_INFO_FILE,
michael@0 66 '%d:%d' % (self.test_server_spawner_port,
michael@0 67 self.test_server_port))
michael@0 68
michael@0 69 def Run(self):
michael@0 70 """Calls subclass functions to set up tests, run them and tear them down.
michael@0 71
michael@0 72 Returns:
michael@0 73 Test results returned from RunTests().
michael@0 74 """
michael@0 75 if not self.HasTests():
michael@0 76 return True
michael@0 77 self.SetUp()
michael@0 78 try:
michael@0 79 return self.RunTests()
michael@0 80 finally:
michael@0 81 self.TearDown()
michael@0 82
michael@0 83 def SetUp(self):
michael@0 84 """Called before tests run."""
michael@0 85 pass
michael@0 86
michael@0 87 def HasTests(self):
michael@0 88 """Whether the test suite has tests to run."""
michael@0 89 return True
michael@0 90
michael@0 91 def RunTests(self):
michael@0 92 """Runs the tests. Need to be overridden."""
michael@0 93 raise NotImplementedError
michael@0 94
michael@0 95 def TearDown(self):
michael@0 96 """Called when tests finish running."""
michael@0 97 self.ShutdownHelperToolsForTestSuite()
michael@0 98
michael@0 99 def CopyTestData(self, test_data_paths, dest_dir):
michael@0 100 """Copies |test_data_paths| list of files/directories to |dest_dir|.
michael@0 101
michael@0 102 Args:
michael@0 103 test_data_paths: A list of files or directories relative to |dest_dir|
michael@0 104 which should be copied to the device. The paths must exist in
michael@0 105 |CHROME_DIR|.
michael@0 106 dest_dir: Absolute path to copy to on the device.
michael@0 107 """
michael@0 108 for p in test_data_paths:
michael@0 109 self.adb.PushIfNeeded(
michael@0 110 os.path.join(constants.CHROME_DIR, p),
michael@0 111 os.path.join(dest_dir, p))
michael@0 112
michael@0 113 def LaunchTestHttpServer(self, document_root, port=None,
michael@0 114 extra_config_contents=None):
michael@0 115 """Launches an HTTP server to serve HTTP tests.
michael@0 116
michael@0 117 Args:
michael@0 118 document_root: Document root of the HTTP server.
michael@0 119 port: port on which we want to the http server bind.
michael@0 120 extra_config_contents: Extra config contents for the HTTP server.
michael@0 121 """
michael@0 122 self._http_server = lighttpd_server.LighttpdServer(
michael@0 123 document_root, port=port, extra_config_contents=extra_config_contents)
michael@0 124 if self._http_server.StartupHttpServer():
michael@0 125 logging.info('http server started: http://localhost:%s',
michael@0 126 self._http_server.port)
michael@0 127 else:
michael@0 128 logging.critical('Failed to start http server')
michael@0 129 self.StartForwarderForHttpServer()
michael@0 130 return (self._forwarder_device_port, self._http_server.port)
michael@0 131
michael@0 132 def StartForwarder(self, port_pairs):
michael@0 133 """Starts TCP traffic forwarding for the given |port_pairs|.
michael@0 134
michael@0 135 Args:
michael@0 136 host_port_pairs: A list of (device_port, local_port) tuples to forward.
michael@0 137 """
michael@0 138 if self._forwarder:
michael@0 139 self._forwarder.Close()
michael@0 140 self._forwarder = Forwarder(
michael@0 141 self.adb, port_pairs, self.tool, '127.0.0.1', self.build_type)
michael@0 142
michael@0 143 def StartForwarderForHttpServer(self):
michael@0 144 """Starts a forwarder for the HTTP server.
michael@0 145
michael@0 146 The forwarder forwards HTTP requests and responses between host and device.
michael@0 147 """
michael@0 148 self.StartForwarder([(self._forwarder_device_port, self._http_server.port)])
michael@0 149
michael@0 150 def RestartHttpServerForwarderIfNecessary(self):
michael@0 151 """Restarts the forwarder if it's not open."""
michael@0 152 # Checks to see if the http server port is being used. If not forwards the
michael@0 153 # request.
michael@0 154 # TODO(dtrainor): This is not always reliable because sometimes the port
michael@0 155 # will be left open even after the forwarder has been killed.
michael@0 156 if not ports.IsDevicePortUsed(self.adb,
michael@0 157 self._forwarder_device_port):
michael@0 158 self.StartForwarderForHttpServer()
michael@0 159
michael@0 160 def ShutdownHelperToolsForTestSuite(self):
michael@0 161 """Shuts down the server and the forwarder."""
michael@0 162 # Forwarders should be killed before the actual servers they're forwarding
michael@0 163 # to as they are clients potentially with open connections and to allow for
michael@0 164 # proper hand-shake/shutdown.
michael@0 165 if self._forwarder or self._spawner_forwarder:
michael@0 166 # Kill all forwarders on the device and then kill the process on the host
michael@0 167 # (if it exists)
michael@0 168 self.adb.KillAll('device_forwarder')
michael@0 169 if self._forwarder:
michael@0 170 self._forwarder.Close()
michael@0 171 if self._spawner_forwarder:
michael@0 172 self._spawner_forwarder.Close()
michael@0 173 if self._http_server:
michael@0 174 self._http_server.ShutdownHttpServer()
michael@0 175 if self._spawning_server:
michael@0 176 self._spawning_server.Stop()
michael@0 177 self.flags.Restore()
michael@0 178
michael@0 179 def LaunchChromeTestServerSpawner(self):
michael@0 180 """Launches test server spawner."""
michael@0 181 server_ready = False
michael@0 182 error_msgs = []
michael@0 183 # Try 3 times to launch test spawner server.
michael@0 184 for i in xrange(0, 3):
michael@0 185 # Do not allocate port for test server here. We will allocate
michael@0 186 # different port for individual test in TestServerThread.
michael@0 187 self.test_server_spawner_port = ports.AllocateTestServerPort()
michael@0 188 self._spawning_server = SpawningServer(self.test_server_spawner_port,
michael@0 189 self.adb,
michael@0 190 self.tool,
michael@0 191 self.build_type)
michael@0 192 self._spawning_server.Start()
michael@0 193 server_ready, error_msg = ports.IsHttpServerConnectable(
michael@0 194 '127.0.0.1', self.test_server_spawner_port, path='/ping',
michael@0 195 expected_read='ready')
michael@0 196 if server_ready:
michael@0 197 break
michael@0 198 else:
michael@0 199 error_msgs.append(error_msg)
michael@0 200 self._spawning_server.Stop()
michael@0 201 # Wait for 2 seconds then restart.
michael@0 202 time.sleep(2)
michael@0 203 if not server_ready:
michael@0 204 logging.error(';'.join(error_msgs))
michael@0 205 raise Exception('Can not start the test spawner server.')
michael@0 206 self._PushTestServerPortInfoToDevice()
michael@0 207 self._spawner_forwarder = Forwarder(
michael@0 208 self.adb,
michael@0 209 [(self.test_server_spawner_port, self.test_server_spawner_port)],
michael@0 210 self.tool, '127.0.0.1', self.build_type)

mercurial