Commit cf22e8e9 authored by anton@chromium.org's avatar anton@chromium.org

Provide a maximum size on the number of tests to run in one group.

The implementation of thread local storage on Android does not free slots
in a fixed size datastructure with 256 slots. When a large number of tests
run in a single process it is easy to exceed the limit. We don't have
control over how many slots are burnt per test, so we just assume that
one slot is burnt per test. We split the tests so only 256 run in a given
process.

BUG=354405

Review URL: https://codereview.chromium.org/453953003

Cr-Commit-Position: refs/heads/master@{#289386}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289386 0039d316-1c4b-4281-b951-d872f2087c98
parent bf0e9f05
......@@ -330,9 +330,31 @@ def _TearDownRunners(runners, timeout=None):
threads.JoinAll(watchdog_timer.WatchdogTimer(timeout))
def ApplyMaxPerRun(tests, max_per_run):
"""Rearrange the tests so that no group contains more than max_per_run tests.
Args:
tests:
max_per_run:
Returns:
A list of tests with no more than max_per_run per run.
"""
tests_expanded = []
for test_group in tests:
if type(test_group) != str:
# Do not split test objects which are not strings.
tests_expanded.append(test_group)
else:
test_split = test_group.split(':')
for i in range(0, len(test_split), max_per_run):
tests_expanded.append(':'.join(test_split[i:i+max_per_run]))
return tests_expanded
def RunTests(tests, runner_factory, devices, shard=True,
test_timeout=DEFAULT_TIMEOUT, setup_timeout=DEFAULT_TIMEOUT,
num_retries=2):
num_retries=2, max_per_run=256):
"""Run all tests on attached devices, retrying tests that don't pass.
Args:
......@@ -349,6 +371,7 @@ def RunTests(tests, runner_factory, devices, shard=True,
setup_timeout: Watchdog timeout in seconds for creating and cleaning up
test runners.
num_retries: Number of retries for a test.
max_per_run: Maximum number of tests to run in any group.
Returns:
A tuple of (base_test_result.TestRunResults object, exit code).
......@@ -357,21 +380,24 @@ def RunTests(tests, runner_factory, devices, shard=True,
logging.critical('No tests to run.')
return (base_test_result.TestRunResults(), constants.ERROR_EXIT_CODE)
tests_expanded = ApplyMaxPerRun(tests, max_per_run)
if shard:
# Generate a shared _TestCollection object for all test runners, so they
# draw from a common pool of tests.
shared_test_collection = _TestCollection([_Test(t) for t in tests])
shared_test_collection = _TestCollection([_Test(t) for t in tests_expanded])
test_collection_factory = lambda: shared_test_collection
tag_results_with_device = False
log_string = 'sharded across devices'
else:
# Generate a unique _TestCollection object for each test runner, but use
# the same set of tests.
test_collection_factory = lambda: _TestCollection([_Test(t) for t in tests])
test_collection_factory = lambda: _TestCollection(
[_Test(t) for t in tests_expanded])
tag_results_with_device = True
log_string = 'replicated on each device'
logging.info('Will run %d tests (%s): %s', len(tests), log_string, str(tests))
logging.info('Will run %d tests (%s): %s',
len(tests_expanded), log_string, str(tests_expanded))
runners = _CreateRunners(runner_factory, devices, setup_timeout)
try:
return _RunAllTests(runners, test_collection_factory,
......
......@@ -22,7 +22,6 @@ from pylib.base import test_dispatcher
from pylib.utils import watchdog_timer
class TestException(Exception):
pass
......@@ -120,6 +119,11 @@ class TestFunctions(unittest.TestCase):
for i in xrange(5):
self.assertEqual(counter.GetAndIncrement(), i)
def testApplyMaxPerRun(self):
self.assertEqual(
['A:B', 'C:D', 'E', 'F:G', 'H:I'],
test_dispatcher.ApplyMaxPerRun(['A:B', 'C:D:E', 'F:G:H:I'], 2))
class TestThreadGroupFunctions(unittest.TestCase):
"""Tests test_dispatcher._RunAllTests and test_dispatcher._CreateRunners."""
......@@ -188,15 +192,6 @@ class TestShard(unittest.TestCase):
self.assertEqual(len(results.GetAll()), 0)
self.assertEqual(exit_code, constants.ERROR_EXIT_CODE)
def testTestsRemainWithAllDevicesOffline(self):
attached_devices = android_commands.GetAttachedDevices
android_commands.GetAttachedDevices = lambda: []
try:
with self.assertRaises(AssertionError):
_results, _exit_code = TestShard._RunShard(MockRunner)
finally:
android_commands.GetAttachedDevices = attached_devices
class TestReplicate(unittest.TestCase):
"""Tests test_dispatcher.RunTests with replication."""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment