Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(546)

Unified Diff: build/android/pylib/base_test_runner.py

Issue 10689132: [android] Upstream / sync most of build/android and build/android/pylib. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/android/pylib/android_commands.py ('k') | build/android/pylib/base_test_sharder.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/android/pylib/base_test_runner.py
diff --git a/build/android/pylib/base_test_runner.py b/build/android/pylib/base_test_runner.py
index 33e074103672090dd39e5165d46bd33e4b0619b0..9163e32a858083390db1067b02c92c246b651db1 100644
--- a/build/android/pylib/base_test_runner.py
+++ b/build/android/pylib/base_test_runner.py
@@ -2,20 +2,26 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import contextlib
+import httplib
import logging
import os
+import tempfile
+import time
import android_commands
from chrome_test_server_spawner import SpawningServer
+import constants
from flag_changer import FlagChanger
+from forwarder import Forwarder
import lighttpd_server
-import run_tests_helper
+import ports
+from valgrind_tools import CreateTool
-FORWARDER_PATH = '/data/local/tmp/forwarder'
-# These ports must match up with the constants in net/test/test_server.cc
-TEST_SERVER_SPAWNER_PORT = 8001
-TEST_SERVER_PORT = 8002
-TEST_SYNC_SERVER_PORT = 8003
+
+# A file on device to store ports of net test server. The format of the file is
+# test-spawner-server-port:test-server-port
+NET_TEST_SERVER_PORT_INFO_FILE = '/data/local/tmp/net-test-server-ports'
class BaseTestRunner(object):
@@ -25,7 +31,7 @@ class BaseTestRunner(object):
the Run() method will set up tests, run them and tear them down.
"""
- def __init__(self, device, shard_index):
+ def __init__(self, device, tool, shard_index):
"""
Args:
device: Tests will run on the device of this ID.
@@ -33,6 +39,7 @@ class BaseTestRunner(object):
"""
self.device = device
self.adb = android_commands.AndroidCommands(device=device)
+ self.tool = CreateTool(tool, self.adb)
# Synchronize date/time between host and device. Otherwise same file on
# host and device may have different timestamp which may cause
# AndroidCommands.PushIfNeeded failed, or a test which may compare timestamp
@@ -40,13 +47,25 @@ class BaseTestRunner(object):
self.adb.SynchronizeDateTime()
self._http_server = None
self._forwarder = None
- self._spawning_server = None
- self._spawner_forwarder = None
self._forwarder_device_port = 8000
self.forwarder_base_url = ('http://localhost:%d' %
self._forwarder_device_port)
self.flags = FlagChanger(self.adb)
self.shard_index = shard_index
+ self.flags.AddFlags(['--disable-fre'])
+ self._spawning_server = None
+ self._spawner_forwarder = None
+ # We will allocate port for test server spawner when calling method
+ # LaunchChromeTestServerSpawner and allocate port for test server when
+ # starting it in TestServerThread.
+ self.test_server_spawner_port = 0
+ self.test_server_port = 0
+
+ def _PushTestServerPortInfoToDevice(self):
+ """Pushes the latest port information to device."""
+ self.adb.SetFileContents(NET_TEST_SERVER_PORT_INFO_FILE,
+ '%d:%d' % (self.test_server_spawner_port,
+ self.test_server_port))
def Run(self):
"""Calls subclass functions to set up tests, run them and tear them down.
@@ -54,6 +73,8 @@ class BaseTestRunner(object):
Returns:
Test results returned from RunTests().
"""
+ if not self.HasTests():
+ return True
self.SetUp()
try:
return self.RunTests()
@@ -64,6 +85,10 @@ class BaseTestRunner(object):
"""Called before tests run."""
pass
+ def HasTests(self):
+ """Whether the test suite has tests to run."""
+ return True
+
def RunTests(self):
"""Runs the tests. Need to be overridden."""
raise NotImplementedError
@@ -83,42 +108,71 @@ class BaseTestRunner(object):
"""
for p in test_data_paths:
self.adb.PushIfNeeded(
- os.path.join(run_tests_helper.CHROME_DIR, p),
+ os.path.join(constants.CHROME_DIR, p),
os.path.join(dest_dir, p))
- def LaunchTestHttpServer(self, document_root, extra_config_contents=None):
+ def LinkSdCardPathsToTempDir(self, paths):
+ """Link |paths| which are under sdcard to /data/local/tmp.
+
+ For example, the test data '/sdcard/my_data' will be linked to
+ '/data/local/tmp/my_data'.
+
+ Args:
+ paths: A list of files and directories relative to /sdcard.
+ """
+ links = set()
+ for path in paths:
+ link_name = os.path.dirname(path)
+ assert link_name, 'Linked paths must be in a subdir of /sdcard/.'
+ link_name = link_name.split('/')[0]
+ if link_name not in links:
+ mapped_device_path = '/data/local/tmp/' + link_name
+ # Unlink the mapped_device_path at first in case it was mapped to
+ # a wrong path. Add option '-r' becuase the old path could be a dir.
+ self.adb.RunShellCommand('rm -r %s' % mapped_device_path)
+ self.adb.RunShellCommand(
+ 'ln -s /sdcard/%s %s' % (link_name, mapped_device_path))
+ links.add(link_name)
+
+ def LaunchTestHttpServer(self, document_root, port=None,
+ extra_config_contents=None):
"""Launches an HTTP server to serve HTTP tests.
Args:
document_root: Document root of the HTTP server.
+ port: port on which we want to the http server bind.
extra_config_contents: Extra config contents for the HTTP server.
"""
self._http_server = lighttpd_server.LighttpdServer(
- document_root, extra_config_contents=extra_config_contents)
+ document_root, port=port, extra_config_contents=extra_config_contents)
if self._http_server.StartupHttpServer():
logging.info('http server started: http://localhost:%s',
self._http_server.port)
else:
logging.critical('Failed to start http server')
- # Root access needed to make the forwarder executable work.
- self.adb.EnableAdbRoot()
self.StartForwarderForHttpServer()
- def StartForwarderForHttpServer(self):
- """Starts a forwarder for the HTTP server.
+ def StartForwarder(self, port_pairs):
+ """Starts TCP traffic forwarding for the given |port_pairs|.
- The forwarder forwards HTTP requests and responses between host and device.
+ Args:
+ host_port_pairs: A list of (device_port, local_port) tuples to forward.
"""
# Sometimes the forwarder device port may be already used. We have to kill
# all forwarder processes to ensure that the forwarder can be started since
# currently we can not associate the specified port to related pid.
- # TODO(yfriedman/wangxianzhu): This doesn't work as most of the time the
- # port is in use but the forwarder is already dead. Killing all forwarders
- # is overly destructive and breaks other tests which make use of forwarders.
- # if IsDevicePortUsed(self.adb, self._forwarder_device_port):
- # self.adb.KillAll('forwarder')
- self._forwarder = run_tests_helper.ForwardDevicePorts(
- self.adb, [(self._forwarder_device_port, self._http_server.port)])
+ self.adb.KillAll('forwarder')
+ if self._forwarder:
+ self._forwarder.Close()
+ self._forwarder = Forwarder(
+ self.adb, port_pairs, self.tool, '127.0.0.1')
+
+ def StartForwarderForHttpServer(self):
+ """Starts a forwarder for the HTTP server.
+
+ The forwarder forwards HTTP requests and responses between host and device.
+ """
+ self.StartForwarder([(self._forwarder_device_port, self._http_server.port)])
def RestartHttpServerForwarderIfNecessary(self):
"""Restarts the forwarder if it's not open."""
@@ -126,7 +180,7 @@ class BaseTestRunner(object):
# request.
# TODO(dtrainor): This is not always reliable because sometimes the port
# will be left open even after the forwarder has been killed.
- if not run_tests_helper.IsDevicePortUsed(self.adb,
+ if not ports.IsDevicePortUsed(self.adb,
self._forwarder_device_port):
self.StartForwarderForHttpServer()
@@ -140,9 +194,9 @@ class BaseTestRunner(object):
# (if it exists)
self.adb.KillAll('forwarder')
if self._forwarder:
- self._forwarder.kill()
+ self._forwarder.Close()
if self._spawner_forwarder:
- self._spawner_forwarder.kill()
+ self._spawner_forwarder.Close()
if self._http_server:
self._http_server.ShutdownHttpServer()
if self._spawning_server:
@@ -151,12 +205,32 @@ class BaseTestRunner(object):
def LaunchChromeTestServerSpawner(self):
"""Launches test server spawner."""
- self._spawning_server = SpawningServer(TEST_SERVER_SPAWNER_PORT,
- TEST_SERVER_PORT)
- self._spawning_server.Start()
- # TODO(yfriedman): Ideally we'll only try to start up a port forwarder if
- # there isn't one already running but for now we just get an error message
- # and the existing forwarder still works.
- self._spawner_forwarder = run_tests_helper.ForwardDevicePorts(
- self.adb, [(TEST_SERVER_SPAWNER_PORT, TEST_SERVER_SPAWNER_PORT),
- (TEST_SERVER_PORT, TEST_SERVER_PORT)])
+ server_ready = False
+ error_msgs = []
+ # Try 3 times to launch test spawner server.
+ for i in xrange(0, 3):
+ # Do not allocate port for test server here. We will allocate
+ # different port for individual test in TestServerThread.
+ self.test_server_spawner_port = ports.AllocateTestServerPort()
+ self._spawning_server = SpawningServer(self.test_server_spawner_port,
+ self.adb,
+ self.tool)
+ self._spawning_server.Start()
+ server_ready, error_msg = ports.IsHttpServerConnectable(
+ '127.0.0.1', self.test_server_spawner_port, path='/ping',
+ expected_read='ready')
+ if server_ready:
+ break
+ else:
+ error_msgs.append(error_msg)
+ self._spawning_server.Stop()
+ # Wait for 2 seconds then restart.
+ time.sleep(2)
+ if not server_ready:
+ logging.error(';'.join(error_msgs))
+ raise Exception('Can not start the test spawner server.')
+ self._PushTestServerPortInfoToDevice()
+ self._spawner_forwarder = Forwarder(
+ self.adb,
+ [(self.test_server_spawner_port, self.test_server_spawner_port)],
+ self.tool, '127.0.0.1')
« no previous file with comments | « build/android/pylib/android_commands.py ('k') | build/android/pylib/base_test_sharder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698