| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Base class for running tests on a single device.""" | 5 """Base class for running tests on a single device.""" |
| 6 | 6 |
| 7 import logging | 7 import logging |
| 8 import time | 8 import time |
| 9 | 9 |
| 10 from pylib import android_commands | |
| 11 from pylib import ports | 10 from pylib import ports |
| 12 from pylib.chrome_test_server_spawner import SpawningServer | 11 from pylib.chrome_test_server_spawner import SpawningServer |
| 12 from pylib.device import device_utils |
| 13 from pylib.forwarder import Forwarder | 13 from pylib.forwarder import Forwarder |
| 14 from pylib.valgrind_tools import CreateTool | 14 from pylib.valgrind_tools import CreateTool |
| 15 # TODO(frankf): Move this to pylib/utils | 15 # TODO(frankf): Move this to pylib/utils |
| 16 import lighttpd_server | 16 import lighttpd_server |
| 17 | 17 |
| 18 | 18 |
| 19 # A file on device to store ports of net test server. The format of the file is | 19 # A file on device to store ports of net test server. The format of the file is |
| 20 # test-spawner-server-port:test-server-port | 20 # test-spawner-server-port:test-server-port |
| 21 NET_TEST_SERVER_PORT_INFO_FILE = 'net-test-server-ports' | 21 NET_TEST_SERVER_PORT_INFO_FILE = 'net-test-server-ports' |
| 22 | 22 |
| 23 | 23 |
| 24 class BaseTestRunner(object): | 24 class BaseTestRunner(object): |
| 25 """Base class for running tests on a single device.""" | 25 """Base class for running tests on a single device.""" |
| 26 | 26 |
| 27 def __init__(self, device, tool, push_deps=True, cleanup_test_files=False): | 27 def __init__(self, device_serial, tool, push_deps=True, |
| 28 cleanup_test_files=False): |
| 28 """ | 29 """ |
| 29 Args: | 30 Args: |
| 30 device: Tests will run on the device of this ID. | 31 device: Tests will run on the device of this ID. |
| 31 tool: Name of the Valgrind tool. | 32 tool: Name of the Valgrind tool. |
| 32 push_deps: If True, push all dependencies to the device. | 33 push_deps: If True, push all dependencies to the device. |
| 33 cleanup_test_files: Whether or not to cleanup test files on device. | 34 cleanup_test_files: Whether or not to cleanup test files on device. |
| 34 """ | 35 """ |
| 35 self.device = device | 36 self.device_serial = device_serial |
| 36 self.adb = android_commands.AndroidCommands(device=device) | 37 self.device = device_utils.DeviceUtils(device_serial) |
| 37 self.tool = CreateTool(tool, self.adb) | 38 self.tool = CreateTool(tool, self.device) |
| 38 self._http_server = None | 39 self._http_server = None |
| 39 self._forwarder_device_port = 8000 | 40 self._forwarder_device_port = 8000 |
| 40 self.forwarder_base_url = ('http://localhost:%d' % | 41 self.forwarder_base_url = ('http://localhost:%d' % |
| 41 self._forwarder_device_port) | 42 self._forwarder_device_port) |
| 42 self._spawning_server = None | 43 self._spawning_server = None |
| 43 # We will allocate port for test server spawner when calling method | 44 # We will allocate port for test server spawner when calling method |
| 44 # LaunchChromeTestServerSpawner and allocate port for test server when | 45 # LaunchChromeTestServerSpawner and allocate port for test server when |
| 45 # starting it in TestServerThread. | 46 # starting it in TestServerThread. |
| 46 self.test_server_spawner_port = 0 | 47 self.test_server_spawner_port = 0 |
| 47 self.test_server_port = 0 | 48 self.test_server_port = 0 |
| 48 self._push_deps = push_deps | 49 self._push_deps = push_deps |
| 49 self._cleanup_test_files = cleanup_test_files | 50 self._cleanup_test_files = cleanup_test_files |
| 50 | 51 |
| 51 def _PushTestServerPortInfoToDevice(self): | 52 def _PushTestServerPortInfoToDevice(self): |
| 52 """Pushes the latest port information to device.""" | 53 """Pushes the latest port information to device.""" |
| 53 self.adb.SetFileContents(self.adb.GetExternalStorage() + '/' + | 54 self.device.old_interface.SetFileContents( |
| 54 NET_TEST_SERVER_PORT_INFO_FILE, | 55 self.device.old_interface.GetExternalStorage() + '/' + |
| 55 '%d:%d' % (self.test_server_spawner_port, | 56 NET_TEST_SERVER_PORT_INFO_FILE, |
| 56 self.test_server_port)) | 57 '%d:%d' % (self.test_server_spawner_port, self.test_server_port)) |
| 57 | 58 |
| 58 def RunTest(self, test): | 59 def RunTest(self, test): |
| 59 """Runs a test. Needs to be overridden. | 60 """Runs a test. Needs to be overridden. |
| 60 | 61 |
| 61 Args: | 62 Args: |
| 62 test: A test to run. | 63 test: A test to run. |
| 63 | 64 |
| 64 Returns: | 65 Returns: |
| 65 Tuple containing: | 66 Tuple containing: |
| 66 (base_test_result.TestRunResults, tests to rerun or None) | 67 (base_test_result.TestRunResults, tests to rerun or None) |
| 67 """ | 68 """ |
| 68 raise NotImplementedError | 69 raise NotImplementedError |
| 69 | 70 |
| 70 def InstallTestPackage(self): | 71 def InstallTestPackage(self): |
| 71 """Installs the test package once before all tests are run.""" | 72 """Installs the test package once before all tests are run.""" |
| 72 pass | 73 pass |
| 73 | 74 |
| 74 def PushDataDeps(self): | 75 def PushDataDeps(self): |
| 75 """Push all data deps to device once before all tests are run.""" | 76 """Push all data deps to device once before all tests are run.""" |
| 76 pass | 77 pass |
| 77 | 78 |
| 78 def SetUp(self): | 79 def SetUp(self): |
| 79 """Run once before all tests are run.""" | 80 """Run once before all tests are run.""" |
| 80 self.InstallTestPackage() | 81 self.InstallTestPackage() |
| 81 push_size_before = self.adb.GetPushSizeInfo() | 82 push_size_before = self.device.old_interface.GetPushSizeInfo() |
| 82 if self._push_deps: | 83 if self._push_deps: |
| 83 logging.warning('Pushing data files to device.') | 84 logging.warning('Pushing data files to device.') |
| 84 self.PushDataDeps() | 85 self.PushDataDeps() |
| 85 push_size_after = self.adb.GetPushSizeInfo() | 86 push_size_after = self.device.old_interface.GetPushSizeInfo() |
| 86 logging.warning( | 87 logging.warning( |
| 87 'Total data: %0.3fMB' % | 88 'Total data: %0.3fMB' % |
| 88 ((push_size_after[0] - push_size_before[0]) / float(2 ** 20))) | 89 ((push_size_after[0] - push_size_before[0]) / float(2 ** 20))) |
| 89 logging.warning( | 90 logging.warning( |
| 90 'Total data transferred: %0.3fMB' % | 91 'Total data transferred: %0.3fMB' % |
| 91 ((push_size_after[1] - push_size_before[1]) / float(2 ** 20))) | 92 ((push_size_after[1] - push_size_before[1]) / float(2 ** 20))) |
| 92 else: | 93 else: |
| 93 logging.warning('Skipping pushing data to device.') | 94 logging.warning('Skipping pushing data to device.') |
| 94 | 95 |
| 95 def TearDown(self): | 96 def TearDown(self): |
| 96 """Run once after all tests are run.""" | 97 """Run once after all tests are run.""" |
| 97 self.ShutdownHelperToolsForTestSuite() | 98 self.ShutdownHelperToolsForTestSuite() |
| 98 if self._cleanup_test_files: | 99 if self._cleanup_test_files: |
| 99 self.adb.RemovePushedFiles() | 100 self.device.old_interface.RemovePushedFiles() |
| 100 | 101 |
| 101 def LaunchTestHttpServer(self, document_root, port=None, | 102 def LaunchTestHttpServer(self, document_root, port=None, |
| 102 extra_config_contents=None): | 103 extra_config_contents=None): |
| 103 """Launches an HTTP server to serve HTTP tests. | 104 """Launches an HTTP server to serve HTTP tests. |
| 104 | 105 |
| 105 Args: | 106 Args: |
| 106 document_root: Document root of the HTTP server. | 107 document_root: Document root of the HTTP server. |
| 107 port: port on which we want to the http server bind. | 108 port: port on which we want to the http server bind. |
| 108 extra_config_contents: Extra config contents for the HTTP server. | 109 extra_config_contents: Extra config contents for the HTTP server. |
| 109 """ | 110 """ |
| 110 self._http_server = lighttpd_server.LighttpdServer( | 111 self._http_server = lighttpd_server.LighttpdServer( |
| 111 document_root, port=port, extra_config_contents=extra_config_contents) | 112 document_root, port=port, extra_config_contents=extra_config_contents) |
| 112 if self._http_server.StartupHttpServer(): | 113 if self._http_server.StartupHttpServer(): |
| 113 logging.info('http server started: http://localhost:%s', | 114 logging.info('http server started: http://localhost:%s', |
| 114 self._http_server.port) | 115 self._http_server.port) |
| 115 else: | 116 else: |
| 116 logging.critical('Failed to start http server') | 117 logging.critical('Failed to start http server') |
| 117 self._ForwardPortsForHttpServer() | 118 self._ForwardPortsForHttpServer() |
| 118 return (self._forwarder_device_port, self._http_server.port) | 119 return (self._forwarder_device_port, self._http_server.port) |
| 119 | 120 |
| 120 def _ForwardPorts(self, port_pairs): | 121 def _ForwardPorts(self, port_pairs): |
| 121 """Forwards a port.""" | 122 """Forwards a port.""" |
| 122 Forwarder.Map(port_pairs, self.adb, self.tool) | 123 Forwarder.Map(port_pairs, self.device, self.tool) |
| 123 | 124 |
| 124 def _UnmapPorts(self, port_pairs): | 125 def _UnmapPorts(self, port_pairs): |
| 125 """Unmap previously forwarded ports.""" | 126 """Unmap previously forwarded ports.""" |
| 126 for (device_port, _) in port_pairs: | 127 for (device_port, _) in port_pairs: |
| 127 Forwarder.UnmapDevicePort(device_port, self.adb) | 128 Forwarder.UnmapDevicePort(device_port, self.device) |
| 128 | 129 |
| 129 # Deprecated: Use ForwardPorts instead. | 130 # Deprecated: Use ForwardPorts instead. |
| 130 def StartForwarder(self, port_pairs): | 131 def StartForwarder(self, port_pairs): |
| 131 """Starts TCP traffic forwarding for the given |port_pairs|. | 132 """Starts TCP traffic forwarding for the given |port_pairs|. |
| 132 | 133 |
| 133 Args: | 134 Args: |
| 134 host_port_pairs: A list of (device_port, local_port) tuples to forward. | 135 host_port_pairs: A list of (device_port, local_port) tuples to forward. |
| 135 """ | 136 """ |
| 136 self._ForwardPorts(port_pairs) | 137 self._ForwardPorts(port_pairs) |
| 137 | 138 |
| 138 def _ForwardPortsForHttpServer(self): | 139 def _ForwardPortsForHttpServer(self): |
| 139 """Starts a forwarder for the HTTP server. | 140 """Starts a forwarder for the HTTP server. |
| 140 | 141 |
| 141 The forwarder forwards HTTP requests and responses between host and device. | 142 The forwarder forwards HTTP requests and responses between host and device. |
| 142 """ | 143 """ |
| 143 self._ForwardPorts([(self._forwarder_device_port, self._http_server.port)]) | 144 self._ForwardPorts([(self._forwarder_device_port, self._http_server.port)]) |
| 144 | 145 |
| 145 def _RestartHttpServerForwarderIfNecessary(self): | 146 def _RestartHttpServerForwarderIfNecessary(self): |
| 146 """Restarts the forwarder if it's not open.""" | 147 """Restarts the forwarder if it's not open.""" |
| 147 # Checks to see if the http server port is being used. If not forwards the | 148 # Checks to see if the http server port is being used. If not forwards the |
| 148 # request. | 149 # request. |
| 149 # TODO(dtrainor): This is not always reliable because sometimes the port | 150 # TODO(dtrainor): This is not always reliable because sometimes the port |
| 150 # will be left open even after the forwarder has been killed. | 151 # will be left open even after the forwarder has been killed. |
| 151 if not ports.IsDevicePortUsed(self.adb, self._forwarder_device_port): | 152 if not ports.IsDevicePortUsed(self.device, self._forwarder_device_port): |
| 152 self._ForwardPortsForHttpServer() | 153 self._ForwardPortsForHttpServer() |
| 153 | 154 |
| 154 def ShutdownHelperToolsForTestSuite(self): | 155 def ShutdownHelperToolsForTestSuite(self): |
| 155 """Shuts down the server and the forwarder.""" | 156 """Shuts down the server and the forwarder.""" |
| 156 if self._http_server: | 157 if self._http_server: |
| 157 self._UnmapPorts([(self._forwarder_device_port, self._http_server.port)]) | 158 self._UnmapPorts([(self._forwarder_device_port, self._http_server.port)]) |
| 158 self._http_server.ShutdownHttpServer() | 159 self._http_server.ShutdownHttpServer() |
| 159 if self._spawning_server: | 160 if self._spawning_server: |
| 160 self._spawning_server.Stop() | 161 self._spawning_server.Stop() |
| 161 | 162 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 174 error_msgs = [] | 175 error_msgs = [] |
| 175 # TODO(pliard): deflake this function. The for loop should be removed as | 176 # TODO(pliard): deflake this function. The for loop should be removed as |
| 176 # well as IsHttpServerConnectable(). spawning_server.Start() should also | 177 # well as IsHttpServerConnectable(). spawning_server.Start() should also |
| 177 # block until the server is ready. | 178 # block until the server is ready. |
| 178 # Try 3 times to launch test spawner server. | 179 # Try 3 times to launch test spawner server. |
| 179 for _ in xrange(0, 3): | 180 for _ in xrange(0, 3): |
| 180 self.test_server_spawner_port = ports.AllocateTestServerPort() | 181 self.test_server_spawner_port = ports.AllocateTestServerPort() |
| 181 self._ForwardPorts( | 182 self._ForwardPorts( |
| 182 [(self.test_server_spawner_port, self.test_server_spawner_port)]) | 183 [(self.test_server_spawner_port, self.test_server_spawner_port)]) |
| 183 self._spawning_server = SpawningServer(self.test_server_spawner_port, | 184 self._spawning_server = SpawningServer(self.test_server_spawner_port, |
| 184 self.adb, | 185 self.device, |
| 185 self.tool) | 186 self.tool) |
| 186 self._spawning_server.Start() | 187 self._spawning_server.Start() |
| 187 server_ready, error_msg = ports.IsHttpServerConnectable( | 188 server_ready, error_msg = ports.IsHttpServerConnectable( |
| 188 '127.0.0.1', self.test_server_spawner_port, path='/ping', | 189 '127.0.0.1', self.test_server_spawner_port, path='/ping', |
| 189 expected_read='ready') | 190 expected_read='ready') |
| 190 if server_ready: | 191 if server_ready: |
| 191 break | 192 break |
| 192 else: | 193 else: |
| 193 error_msgs.append(error_msg) | 194 error_msgs.append(error_msg) |
| 194 self._spawning_server.Stop() | 195 self._spawning_server.Stop() |
| 195 # Wait for 2 seconds then restart. | 196 # Wait for 2 seconds then restart. |
| 196 time.sleep(2) | 197 time.sleep(2) |
| 197 if not server_ready: | 198 if not server_ready: |
| 198 logging.error(';'.join(error_msgs)) | 199 logging.error(';'.join(error_msgs)) |
| 199 raise Exception('Can not start the test spawner server.') | 200 raise Exception('Can not start the test spawner server.') |
| 200 self._PushTestServerPortInfoToDevice() | 201 self._PushTestServerPortInfoToDevice() |
| OLD | NEW |