[Android] Switch gtests to platform mode. (RELAND)
BUG=428729 Review URL: https://codereview.chromium.org/1358593002 Cr-Commit-Position: refs/heads/master@{#349931}
This commit is contained in:
@ -3,9 +3,9 @@
|
||||
# found in the LICENSE file.
|
||||
|
||||
from pylib.gtest import gtest_test_instance
|
||||
from pylib.gtest import local_device_gtest_run
|
||||
from pylib.instrumentation import instrumentation_test_instance
|
||||
from pylib.local.device import local_device_environment
|
||||
from pylib.local.device import local_device_gtest_run
|
||||
from pylib.local.device import local_device_instrumentation_test_run
|
||||
from pylib.remote.device import remote_device_environment
|
||||
from pylib.remote.device import remote_device_gtest_run
|
||||
|
@ -23,6 +23,8 @@ BROWSER_TEST_SUITES = [
|
||||
'content_browsertests',
|
||||
]
|
||||
|
||||
RUN_IN_SUB_THREAD_TEST_SUITES = ['net_unittests']
|
||||
|
||||
|
||||
_DEFAULT_ISOLATE_FILE_PATHS = {
|
||||
'base_unittests': 'base/base_unittests.isolate',
|
||||
@ -73,6 +75,8 @@ _DEPS_EXCLUSION_LIST = [
|
||||
_EXTRA_NATIVE_TEST_ACTIVITY = (
|
||||
'org.chromium.native_test.NativeTestInstrumentationTestRunner.'
|
||||
'NativeTestActivity')
|
||||
_EXTRA_RUN_IN_SUB_THREAD = (
|
||||
'org.chromium.native_test.NativeTestActivity.RunInSubThread')
|
||||
_EXTRA_SHARD_SIZE_LIMIT = (
|
||||
'org.chromium.native_test.NativeTestInstrumentationTestRunner.'
|
||||
'ShardSizeLimit')
|
||||
@ -148,6 +152,8 @@ class GtestTestInstance(test_instance.TestInstance):
|
||||
self._extras = {
|
||||
_EXTRA_NATIVE_TEST_ACTIVITY: self._activity,
|
||||
}
|
||||
if self._suite in RUN_IN_SUB_THREAD_TEST_SUITES:
|
||||
self._extras[_EXTRA_RUN_IN_SUB_THREAD] = 1
|
||||
if self._suite in BROWSER_TEST_SUITES:
|
||||
self._extras[_EXTRA_SHARD_SIZE_LIMIT] = 1
|
||||
|
||||
|
@ -16,8 +16,8 @@ from devil.android.sdk import intent
|
||||
from pylib import constants
|
||||
from pylib import pexpect
|
||||
from pylib.gtest import gtest_test_instance
|
||||
from pylib.gtest import local_device_gtest_run
|
||||
from pylib.gtest.test_package import TestPackage
|
||||
from pylib.local.device import local_device_gtest_run
|
||||
|
||||
|
||||
class TestPackageApk(TestPackage):
|
||||
@ -40,7 +40,9 @@ class TestPackageApk(TestPackage):
|
||||
self._package_info = constants.PACKAGE_INFO['gtest']
|
||||
|
||||
if suite_name == 'net_unittests':
|
||||
self._extras = {'RunInSubThread': None}
|
||||
self._extras = {
|
||||
'org.chromium.native_test.NativeTestActivity.RunInSubThread': None
|
||||
}
|
||||
else:
|
||||
self._extras = []
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from devil.android import device_blacklist
|
||||
from devil.android import device_errors
|
||||
from devil.android import device_utils
|
||||
@ -17,6 +20,7 @@ class LocalDeviceEnvironment(environment.Environment):
|
||||
if args.blacklist_file
|
||||
else None)
|
||||
self._device_serial = args.test_device
|
||||
self._devices_lock = threading.Lock()
|
||||
self._devices = []
|
||||
self._max_tries = 1 + args.num_retries
|
||||
self._tool_name = args.tool
|
||||
@ -38,11 +42,13 @@ class LocalDeviceEnvironment(environment.Environment):
|
||||
|
||||
@property
|
||||
def devices(self):
|
||||
if not self._devices:
|
||||
raise device_errors.NoDevicesError()
|
||||
return self._devices
|
||||
|
||||
@property
|
||||
def parallel_devices(self):
|
||||
return parallelizer.SyncParallelizer(self._devices)
|
||||
return parallelizer.SyncParallelizer(self.devices)
|
||||
|
||||
@property
|
||||
def max_tries(self):
|
||||
@ -56,3 +62,15 @@ class LocalDeviceEnvironment(environment.Environment):
|
||||
def TearDown(self):
|
||||
pass
|
||||
|
||||
def BlacklistDevice(self, device):
|
||||
if not self._blacklist:
|
||||
logging.warning(
|
||||
'Attempted to blacklist %s, but no blacklist was provided.',
|
||||
str(device))
|
||||
return
|
||||
|
||||
device_serial = device.adb.GetDeviceSerial()
|
||||
self._blacklist.Extend([device_serial])
|
||||
with self._devices_lock:
|
||||
self._devices = [d for d in self._devices if str(d) != device_serial]
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
# found in the LICENSE file.
|
||||
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import posixpath
|
||||
|
||||
@ -108,10 +107,13 @@ class _ExeDelegate(object):
|
||||
device.PushChangedFiles(host_device_tuples)
|
||||
|
||||
def Run(self, test, device, flags=None, **kwargs):
|
||||
cmd = [
|
||||
self._test_run.GetTool(device).GetTestWrapper(),
|
||||
self._exe_device_path,
|
||||
]
|
||||
tool = self._test_run.GetTool(device).GetTestWrapper()
|
||||
if tool:
|
||||
cmd = [tool]
|
||||
else:
|
||||
cmd = []
|
||||
cmd.append(self._exe_device_path)
|
||||
|
||||
if test:
|
||||
cmd.append('--gtest_filter=%s' % ':'.join(test))
|
||||
if flags:
|
||||
@ -130,14 +132,8 @@ class _ExeDelegate(object):
|
||||
except (device_errors.CommandFailedError, KeyError):
|
||||
pass
|
||||
|
||||
# TODO(jbudorick): Switch to just RunShellCommand once perezju@'s CL
|
||||
# for long shell commands lands.
|
||||
with device_temp_file.DeviceTempFile(device.adb) as script_file:
|
||||
script_contents = ' '.join(cmd)
|
||||
logging.info('script contents: %r', script_contents)
|
||||
device.WriteFile(script_file.name, script_contents)
|
||||
output = device.RunShellCommand(['sh', script_file.name], cwd=cwd,
|
||||
env=env, **kwargs)
|
||||
output = device.RunShellCommand(
|
||||
cmd, cwd=cwd, env=env, check_return=True, large_output=True, **kwargs)
|
||||
return output
|
||||
|
||||
def PullAppFiles(self, device, files, directory):
|
||||
@ -168,6 +164,7 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun):
|
||||
#override
|
||||
def SetUp(self):
|
||||
|
||||
@local_device_test_run.handle_shard_failures
|
||||
def individual_device_set_up(dev, host_device_tuples):
|
||||
# Install test APK.
|
||||
self._delegate.Install(dev)
|
||||
@ -207,10 +204,16 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun):
|
||||
|
||||
#override
|
||||
def _GetTests(self):
|
||||
tests = self._delegate.Run(
|
||||
None, self._env.devices[0], flags='--gtest_list_tests')
|
||||
tests = gtest_test_instance.ParseGTestListTests(tests)
|
||||
tests = self._test_instance.FilterTests(tests)
|
||||
@local_device_test_run.handle_shard_failures
|
||||
def list_tests(dev):
|
||||
tests = self._delegate.Run(
|
||||
None, dev, flags='--gtest_list_tests', timeout=10)
|
||||
tests = gtest_test_instance.ParseGTestListTests(tests)
|
||||
tests = self._test_instance.FilterTests(tests)
|
||||
return tests
|
||||
|
||||
test_lists = self._env.parallel_devices.pMap(list_tests).pGet(None)
|
||||
tests = list(sorted(set().union(*[set(tl) for tl in test_lists if tl])))
|
||||
return tests
|
||||
|
||||
#override
|
||||
@ -233,6 +236,7 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun):
|
||||
|
||||
#override
|
||||
def TearDown(self):
|
||||
@local_device_test_run.handle_shard_failures
|
||||
def individual_device_tear_down(dev):
|
||||
for s in self._servers[str(dev)]:
|
||||
s.TearDown()
|
@ -11,6 +11,27 @@ from pylib.base import test_run
|
||||
from pylib.base import test_collection
|
||||
|
||||
|
||||
def handle_shard_failures(f):
|
||||
"""A decorator that handles device failures for per-device functions.
|
||||
|
||||
Args:
|
||||
f: the function being decorated. The function must take at least one
|
||||
argument, and that argument must be the device.
|
||||
"""
|
||||
def wrapper(dev, *args, **kwargs):
|
||||
try:
|
||||
return f(dev, *args, **kwargs)
|
||||
except device_errors.CommandFailedError:
|
||||
logging.exception('Shard failed: %s(%s)', f.__name__, str(dev))
|
||||
except device_errors.CommandTimeoutError:
|
||||
logging.exception('Shard timed out: %s(%s)', f.__name__, str(dev))
|
||||
except device_errors.DeviceUnreachableError:
|
||||
logging.exception('Shard died: %s(%s)', f.__name__, str(dev))
|
||||
return None
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class LocalDeviceTestRun(test_run.TestRun):
|
||||
|
||||
def __init__(self, env, test_instance):
|
||||
@ -21,6 +42,7 @@ class LocalDeviceTestRun(test_run.TestRun):
|
||||
def RunTests(self):
|
||||
tests = self._GetTests()
|
||||
|
||||
@handle_shard_failures
|
||||
def run_tests_on_device(dev, tests, results):
|
||||
for test in tests:
|
||||
try:
|
||||
@ -52,21 +74,14 @@ class LocalDeviceTestRun(test_run.TestRun):
|
||||
for t in tests:
|
||||
logging.debug(' %s', t)
|
||||
|
||||
try:
|
||||
try_results = base_test_result.TestRunResults()
|
||||
if self._ShouldShard():
|
||||
tc = test_collection.TestCollection(self._CreateShards(tests))
|
||||
self._env.parallel_devices.pMap(
|
||||
run_tests_on_device, tc, try_results).pGet(None)
|
||||
else:
|
||||
self._env.parallel_devices.pMap(
|
||||
run_tests_on_device, tests, try_results).pGet(None)
|
||||
except device_errors.CommandFailedError:
|
||||
logging.exception('Shard terminated: command failed')
|
||||
except device_errors.CommandTimeoutError:
|
||||
logging.exception('Shard terminated: command timed out')
|
||||
except device_errors.DeviceUnreachableError:
|
||||
logging.exception('Shard terminated: device became unreachable')
|
||||
try_results = base_test_result.TestRunResults()
|
||||
if self._ShouldShard():
|
||||
tc = test_collection.TestCollection(self._CreateShards(tests))
|
||||
self._env.parallel_devices.pMap(
|
||||
run_tests_on_device, tc, try_results).pGet(None)
|
||||
else:
|
||||
self._env.parallel_devices.pMap(
|
||||
run_tests_on_device, tests, try_results).pGet(None)
|
||||
|
||||
for result in try_results.GetAll():
|
||||
if result.GetType() in (base_test_result.ResultType.PASS,
|
||||
|
@ -32,8 +32,6 @@ from pylib.base import test_dispatcher
|
||||
from pylib.base import test_instance_factory
|
||||
from pylib.base import test_run_factory
|
||||
from pylib.gtest import gtest_config
|
||||
# TODO(jbudorick): Remove this once we stop selectively enabling platform mode.
|
||||
from pylib.gtest import gtest_test_instance
|
||||
from pylib.gtest import setup as gtest_setup
|
||||
from pylib.gtest import test_options as gtest_test_options
|
||||
from pylib.linker import setup as linker_setup
|
||||
@ -944,9 +942,7 @@ def RunTestsCommand(args, parser): # pylint: disable=too-many-return-statements
|
||||
raise Exception('Failed to reset test server port.')
|
||||
|
||||
if command == 'gtest':
|
||||
if args.suite_name[0] in gtest_test_instance.BROWSER_TEST_SUITES:
|
||||
return RunTestsInPlatformMode(args, parser)
|
||||
return _RunGTests(args, devices)
|
||||
return RunTestsInPlatformMode(args, parser)
|
||||
elif command == 'linker':
|
||||
return _RunLinkerTests(args, devices)
|
||||
elif command == 'instrumentation':
|
||||
@ -975,13 +971,16 @@ _SUPPORTED_IN_PLATFORM_MODE = [
|
||||
|
||||
def RunTestsInPlatformMode(args, parser):
|
||||
|
||||
if args.command not in _SUPPORTED_IN_PLATFORM_MODE:
|
||||
parser.error('%s is not yet supported in platform mode' % args.command)
|
||||
def infra_error(message):
|
||||
parser.exit(status=constants.INFRA_EXIT_CODE, message=message)
|
||||
|
||||
with environment_factory.CreateEnvironment(args, parser.error) as env:
|
||||
with test_instance_factory.CreateTestInstance(args, parser.error) as test:
|
||||
if args.command not in _SUPPORTED_IN_PLATFORM_MODE:
|
||||
infra_error('%s is not yet supported in platform mode' % args.command)
|
||||
|
||||
with environment_factory.CreateEnvironment(args, infra_error) as env:
|
||||
with test_instance_factory.CreateTestInstance(args, infra_error) as test:
|
||||
with test_run_factory.CreateTestRun(
|
||||
args, env, test, parser.error) as test_run:
|
||||
args, env, test, infra_error) as test_run:
|
||||
results = test_run.RunTests()
|
||||
|
||||
if args.environment == 'remote_device' and args.trigger:
|
||||
|
@ -24,7 +24,8 @@ found in the LICENSE file.
|
||||
android:name="org.chromium.base.BaseChromiumApplication">
|
||||
<activity android:name=".NativeUnitTestActivity"
|
||||
android:label="NativeTest"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:process=":test_process">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
@ -15,7 +15,7 @@ import java.io.File;
|
||||
*/
|
||||
public abstract class NativeBrowserTestActivity extends NativeTestActivity {
|
||||
|
||||
private static final String TAG = "cr.native_test";
|
||||
private static final String TAG = "cr_NativeTest";
|
||||
|
||||
private static final String BROWSER_TESTS_FLAGS[] = {
|
||||
// content::kSingleProcessTestsFlag
|
||||
|
@ -32,13 +32,14 @@ public class NativeTestActivity extends Activity {
|
||||
"org.chromium.native_test.NativeTestActivity.CommandLineFile";
|
||||
public static final String EXTRA_COMMAND_LINE_FLAGS =
|
||||
"org.chromium.native_test.NativeTestActivity.CommandLineFlags";
|
||||
public static final String EXTRA_RUN_IN_SUB_THREAD =
|
||||
"org.chromium.native_test.NativeTestActivity.RunInSubThread";
|
||||
public static final String EXTRA_SHARD =
|
||||
"org.chromium.native_test.NativeTestActivity.Shard";
|
||||
public static final String EXTRA_STDOUT_FILE =
|
||||
"org.chromium.native_test.NativeTestActivity.StdoutFile";
|
||||
|
||||
private static final String TAG = "cr.native_test";
|
||||
private static final String EXTRA_RUN_IN_SUB_THREAD = "RunInSubThread";
|
||||
private static final String TAG = "cr_NativeTest";
|
||||
|
||||
private String mCommandLineFilePath;
|
||||
private StringBuilder mCommandLineFlags = new StringBuilder();
|
||||
@ -57,6 +58,12 @@ public class NativeTestActivity extends Activity {
|
||||
}
|
||||
|
||||
private void parseArgumentsFromIntent(Intent intent) {
|
||||
Log.i(TAG, "Extras:");
|
||||
Bundle extras = intent.getExtras();
|
||||
for (String s : extras.keySet()) {
|
||||
Log.i(TAG, " %s", s);
|
||||
}
|
||||
|
||||
mCommandLineFilePath = intent.getStringExtra(EXTRA_COMMAND_LINE_FILE);
|
||||
if (mCommandLineFilePath == null) {
|
||||
mCommandLineFilePath = "";
|
||||
|
@ -52,7 +52,7 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation {
|
||||
public static final String EXTRA_TEST_LIST_FILE =
|
||||
"org.chromium.native_test.NativeTestInstrumentationTestRunner.TestList";
|
||||
|
||||
private static final String TAG = "cr.native_test";
|
||||
private static final String TAG = "cr_NativeTest";
|
||||
|
||||
private static final long DEFAULT_SHARD_NANO_TIMEOUT = 60 * 1000000000L;
|
||||
// Default to no size limit.
|
||||
@ -63,11 +63,10 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation {
|
||||
Pattern.compile("\\[ *([^ ]*) *\\] ?([^ ]+)( .*)?$");
|
||||
|
||||
private ResultsBundleGenerator mBundleGenerator = new RobotiumBundleGenerator();
|
||||
private String mCommandLineFile;
|
||||
private String mCommandLineFlags;
|
||||
private Handler mHandler = new Handler();
|
||||
private String mNativeTestActivity;
|
||||
private Bundle mLogBundle = new Bundle();
|
||||
private SparseArray<ShardMonitor> mMonitors = new SparseArray<ShardMonitor>();
|
||||
private String mNativeTestActivity;
|
||||
private TestStatusReceiver mReceiver;
|
||||
private Map<String, ResultsBundleGenerator.TestResult> mResults =
|
||||
new HashMap<String, ResultsBundleGenerator.TestResult>();
|
||||
@ -75,20 +74,23 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation {
|
||||
private long mShardNanoTimeout = DEFAULT_SHARD_NANO_TIMEOUT;
|
||||
private int mShardSizeLimit = DEFAULT_SHARD_SIZE_LIMIT;
|
||||
private File mStdoutFile;
|
||||
private SparseArray<ShardMonitor> mMonitors = new SparseArray<ShardMonitor>();
|
||||
private Bundle mTransparentArguments;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle arguments) {
|
||||
mCommandLineFile = arguments.getString(NativeTestActivity.EXTRA_COMMAND_LINE_FILE);
|
||||
mCommandLineFlags = arguments.getString(NativeTestActivity.EXTRA_COMMAND_LINE_FLAGS);
|
||||
mTransparentArguments = new Bundle(arguments);
|
||||
|
||||
mNativeTestActivity = arguments.getString(EXTRA_NATIVE_TEST_ACTIVITY);
|
||||
if (mNativeTestActivity == null) mNativeTestActivity = DEFAULT_NATIVE_TEST_ACTIVITY;
|
||||
mTransparentArguments.remove(EXTRA_NATIVE_TEST_ACTIVITY);
|
||||
|
||||
String shardNanoTimeout = arguments.getString(EXTRA_SHARD_NANO_TIMEOUT);
|
||||
if (shardNanoTimeout != null) mShardNanoTimeout = Long.parseLong(shardNanoTimeout);
|
||||
mTransparentArguments.remove(EXTRA_SHARD_NANO_TIMEOUT);
|
||||
|
||||
String shardSizeLimit = arguments.getString(EXTRA_SHARD_SIZE_LIMIT);
|
||||
if (shardSizeLimit != null) mShardSizeLimit = Integer.parseInt(shardSizeLimit);
|
||||
mTransparentArguments.remove(EXTRA_SHARD_SIZE_LIMIT);
|
||||
|
||||
String testListFilePath = arguments.getString(EXTRA_TEST_LIST_FILE);
|
||||
if (testListFilePath != null) {
|
||||
@ -116,6 +118,7 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation {
|
||||
Log.e(TAG, "Error reading %s", testListFile.getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
mTransparentArguments.remove(EXTRA_TEST_LIST_FILE);
|
||||
|
||||
try {
|
||||
mStdoutFile = File.createTempFile(
|
||||
@ -220,14 +223,7 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation {
|
||||
Intent i = new Intent(Intent.ACTION_MAIN);
|
||||
i.setComponent(new ComponentName(getContext().getPackageName(), mNativeTestActivity));
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (mCommandLineFile != null) {
|
||||
Log.i(TAG, "Passing command line file extra: %s", mCommandLineFile);
|
||||
i.putExtra(NativeTestActivity.EXTRA_COMMAND_LINE_FILE, mCommandLineFile);
|
||||
}
|
||||
if (mCommandLineFlags != null) {
|
||||
Log.i(TAG, "Passing command line flag extra: %s", mCommandLineFlags);
|
||||
i.putExtra(NativeTestActivity.EXTRA_COMMAND_LINE_FLAGS, mCommandLineFlags);
|
||||
}
|
||||
i.putExtras(mTransparentArguments);
|
||||
if (mShards != null && !mShards.isEmpty()) {
|
||||
ArrayList<String> shard = mShards.remove();
|
||||
i.putStringArrayListExtra(NativeTestActivity.EXTRA_SHARD, shard);
|
||||
|
@ -17,7 +17,7 @@ import org.chromium.base.library_loader.NativeLibraries;
|
||||
*/
|
||||
public class NativeUnitTestActivity extends NativeTestActivity {
|
||||
|
||||
private static final String TAG = "cr.native_test";
|
||||
private static final String TAG = "cr_NativeTest";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
Reference in New Issue
Block a user