From 08b097a938942684558910dc9ca662c2a59ce3d2 Mon Sep 17 00:00:00 2001 From: jbudorick Date: Thu, 21 May 2015 19:54:57 -0700 Subject: [Android] Refactor the native test wrappers. (RELAND) This is a reland of https://codereview.chromium.org/1126543009/, which broke gtests built by GN. BUG=476410 Review URL: https://codereview.chromium.org/1143903002 Cr-Commit-Position: refs/heads/master@{#331056} --- build/android/pylib/constants/__init__.py | 6 +- build/android/pylib/gtest/gtest_test_instance.py | 19 ++-- .../android/pylib/gtest/local_device_gtest_run.py | 34 ++++--- build/android/pylib/gtest/setup.py | 4 +- build/android/pylib/gtest/test_package_apk.py | 10 +- build/android/pylib/gtest/test_runner.py | 1 + .../instrumentation_test_instance.py | 12 +-- build/android/pylib/utils/apk_helper.py | 73 +++++++++++---- build/apk_browsertest.gypi | 43 +++++++++ build/config/android/rules.gni | 2 + .../android/unit_tests_apk/AndroidManifest.xml | 2 +- components/BUILD.gn | 16 +--- components/components_tests.gyp | 21 +---- .../browsertests_apk/AndroidManifest.xml.jinja2 | 4 + .../components_browser_tests_android.cc | 99 -------------------- .../components_browser_tests_android.h | 16 ---- .../components_browser_tests_jni_onload.cc | 10 +- .../ComponentsBrowserTestsActivity.java | 37 +++----- content/content_shell.gypi | 1 - content/content_tests.gypi | 9 +- content/shell/android/BUILD.gn | 1 - .../browsertests_apk/AndroidManifest.xml.jinja2 | 4 + .../content_browser_tests_android.cc | 101 --------------------- .../content_browser_tests_android.h | 16 ---- .../content_browser_tests_jni_onload.cc | 8 +- .../ContentBrowserTestsActivity.java | 37 +++----- content/test/BUILD.gn | 2 +- testing/android/native_test.gyp | 56 ++++++++---- testing/android/native_test/BUILD.gn | 33 +++---- .../android/native_test/java/AndroidManifest.xml | 2 +- .../native_test/NativeBrowserTestActivity.java | 46 ++++++++++ .../chromium/native_test/NativeTestActivity.java | 93 +++++++++---------- .../NativeTestInstrumentationTestRunner.java | 20 ++-- .../native_test/NativeUnitTestActivity.java | 48 ++++++++++ .../android/native_test/native_test_jni_onload.cc | 4 +- .../android/native_test/native_test_launcher.cc | 14 +-- testing/android/native_test/native_test_launcher.h | 6 ++ testing/android/native_test/native_test_util.cc | 4 +- testing/android/native_test/native_test_util.h | 4 +- 39 files changed, 423 insertions(+), 495 deletions(-) create mode 100644 build/apk_browsertest.gypi delete mode 100644 components/test/android/browsertests_apk/components_browser_tests_android.cc delete mode 100644 components/test/android/browsertests_apk/components_browser_tests_android.h delete mode 100644 content/shell/android/browsertests_apk/content_browser_tests_android.cc delete mode 100644 content/shell/android/browsertests_apk/content_browser_tests_android.h create mode 100644 testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java create mode 100644 testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java diff --git a/build/android/pylib/constants/__init__.py b/build/android/pylib/constants/__init__.py index cb5f899..4523188 100644 --- a/build/android/pylib/constants/__init__.py +++ b/build/android/pylib/constants/__init__.py @@ -102,7 +102,7 @@ PACKAGE_INFO = { 'org.chromium.android_webview.test'), 'gtest': PackageInfo( 'org.chromium.native_test', - 'org.chromium.native_test.NativeTestActivity', + 'org.chromium.native_test.NativeUnitTestActivity', '/data/local/tmp/chrome-native-tests-command-line', None, None), @@ -110,13 +110,13 @@ PACKAGE_INFO = { 'org.chromium.components_browsertests_apk', ('org.chromium.components_browsertests_apk' + '.ComponentsBrowserTestsActivity'), - '/data/local/tmp/components-browser-tests-command-line', + '/data/local/tmp/chrome-native-tests-command-line', None, None), 'content_browsertests': PackageInfo( 'org.chromium.content_browsertests_apk', 'org.chromium.content_browsertests_apk.ContentBrowserTestsActivity', - '/data/local/tmp/content-browser-tests-command-line', + '/data/local/tmp/chrome-native-tests-command-line', None, None), 'chromedriver_webview_shell': PackageInfo( diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py index b6f83b3..cea5016 100644 --- a/build/android/pylib/gtest/gtest_test_instance.py +++ b/build/android/pylib/gtest/gtest_test_instance.py @@ -17,6 +17,12 @@ sys.path.append(os.path.join( import unittest_util +BROWSER_TEST_SUITES = [ + 'components_browsertests', + 'content_browsertests', +] + + # Used for filtering large data deps at a finer grain than what's allowed in # isolate files since pushing deps to devices is expensive. # Wildcards are allowed. @@ -92,16 +98,9 @@ class GtestTestInstance(test_instance.TestInstance): raise ValueError('Platform mode currently supports only 1 gtest suite') self._suite = args.suite_name[0] - if (self._suite == 'content_browsertests' or - self._suite == 'components_browsertests'): - error_func('%s are not currently supported ' - 'in platform mode.' % self._suite) - self._apk_path = os.path.join( - constants.GetOutDirectory(), 'apks', '%s.apk' % self._suite) - else: - self._apk_path = os.path.join( - constants.GetOutDirectory(), '%s_apk' % self._suite, - '%s-debug.apk' % self._suite) + self._apk_path = os.path.join( + constants.GetOutDirectory(), '%s_apk' % self._suite, + '%s-debug.apk' % self._suite) self._exe_path = os.path.join(constants.GetOutDirectory(), self._suite) if not os.path.exists(self._apk_path): diff --git a/build/android/pylib/gtest/local_device_gtest_run.py b/build/android/pylib/gtest/local_device_gtest_run.py index 4241e85..15a58a4 100644 --- a/build/android/pylib/gtest/local_device_gtest_run.py +++ b/build/android/pylib/gtest/local_device_gtest_run.py @@ -24,6 +24,9 @@ _EXTRA_COMMAND_LINE_FILE = ( 'org.chromium.native_test.NativeTestActivity.CommandLineFile') _EXTRA_COMMAND_LINE_FLAGS = ( 'org.chromium.native_test.NativeTestActivity.CommandLineFlags') +_EXTRA_NATIVE_TEST_ACTIVITY = ( + 'org.chromium.native_test.NativeTestInstrumentationTestRunner' + '.NativeTestActivity') _MAX_SHARD_SIZE = 256 @@ -37,8 +40,11 @@ _SUITE_REQUIRES_TEST_SERVER_SPAWNER = [ class _ApkDelegate(object): def __init__(self, apk): self._apk = apk - self._package = apk_helper.GetPackageName(self._apk) - self._runner = apk_helper.GetInstrumentationName(self._apk) + + helper = apk_helper.ApkHelper(self._apk) + self._activity = helper.GetActivityName() + self._package = helper.GetPackageName() + self._runner = helper.GetInstrumentationName() self._component = '%s/%s' % (self._package, self._runner) self._enable_test_server_spawner = False @@ -51,6 +57,7 @@ class _ApkDelegate(object): extras = { _EXTRA_COMMAND_LINE_FILE: command_line_file.name, + _EXTRA_NATIVE_TEST_ACTIVITY: self._activity, } return device.StartInstrumentation( @@ -132,7 +139,7 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): #override def TestPackage(self): - return self._test_instance._suite + return self._test_instance.suite #override def SetUp(self): @@ -166,13 +173,16 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): #override def _CreateShards(self, tests): - device_count = len(self._env.devices) - shards = [] - for i in xrange(0, device_count): - unbounded_shard = tests[i::device_count] - shards += [unbounded_shard[j:j+_MAX_SHARD_SIZE] - for j in xrange(0, len(unbounded_shard), _MAX_SHARD_SIZE)] - return [':'.join(s) for s in shards] + if self._test_instance.suite in gtest_test_instance.BROWSER_TEST_SUITES: + return tests + else: + device_count = len(self._env.devices) + shards = [] + for i in xrange(0, device_count): + unbounded_shard = tests[i::device_count] + shards += [unbounded_shard[j:j+_MAX_SHARD_SIZE] + for j in xrange(0, len(unbounded_shard), _MAX_SHARD_SIZE)] + return [':'.join(s) for s in shards] #override def _GetTests(self): @@ -185,8 +195,8 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): #override def _RunTest(self, device, test): # Run the test. - output = self._delegate.RunWithFlags(device, '--gtest_filter=%s' % test, - timeout=900, retries=0) + output = self._delegate.RunWithFlags( + device, '--gtest_filter=%s' % test, timeout=900, retries=0) for s in self._servers[str(device)]: s.Reset() self._delegate.Clear(device) diff --git a/build/android/pylib/gtest/setup.py b/build/android/pylib/gtest/setup.py index d51b90e..8ba9a8d 100644 --- a/build/android/pylib/gtest/setup.py +++ b/build/android/pylib/gtest/setup.py @@ -15,6 +15,7 @@ from pylib.base import base_setup from pylib.base import base_test_result from pylib.base import test_dispatcher from pylib.device import device_utils +from pylib.gtest import gtest_test_instance from pylib.gtest import test_package_apk from pylib.gtest import test_package_exe from pylib.gtest import test_runner @@ -240,8 +241,7 @@ def Setup(test_options, devices): tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter) # Coalesce unit tests into a single test per device - if (test_options.suite_name != 'content_browsertests' and - test_options.suite_name != 'components_browsertests'): + if test_options.suite_name not in gtest_test_instance.BROWSER_TEST_SUITES: num_devices = len(devices) tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)] tests = [t for t in tests if t] diff --git a/build/android/pylib/gtest/test_package_apk.py b/build/android/pylib/gtest/test_package_apk.py index 9672f7a..6447820 100644 --- a/build/android/pylib/gtest/test_package_apk.py +++ b/build/android/pylib/gtest/test_package_apk.py @@ -30,18 +30,14 @@ class TestPackageApk(TestPackage): suite_name: Name of the test suite (e.g. base_unittests). """ TestPackage.__init__(self, suite_name) + self.suite_path = os.path.join( + constants.GetOutDirectory(), '%s_apk' % suite_name, + '%s-debug.apk' % suite_name) if suite_name == 'content_browsertests': - self.suite_path = os.path.join( - constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name) self._package_info = constants.PACKAGE_INFO['content_browsertests'] elif suite_name == 'components_browsertests': - self.suite_path = os.path.join( - constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name) self._package_info = constants.PACKAGE_INFO['components_browsertests'] else: - self.suite_path = os.path.join( - constants.GetOutDirectory(), '%s_apk' % suite_name, - '%s-debug.apk' % suite_name) self._package_info = constants.PACKAGE_INFO['gtest'] def _CreateCommandLineFileOnDevice(self, device, options): diff --git a/build/android/pylib/gtest/test_runner.py b/build/android/pylib/gtest/test_runner.py index 4926388..6d01990 100644 --- a/build/android/pylib/gtest/test_runner.py +++ b/build/android/pylib/gtest/test_runner.py @@ -11,6 +11,7 @@ from pylib import ports from pylib.base import base_test_result from pylib.base import base_test_runner from pylib.device import device_errors +from pylib.gtest import gtest_test_instance from pylib.local import local_test_server_spawner from pylib.perf import perf_control diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py index 0633f14..f9957b0 100644 --- a/build/android/pylib/instrumentation/instrumentation_test_instance.py +++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py @@ -201,8 +201,9 @@ class InstrumentationTestInstance(test_instance.TestInstance): if not os.path.exists(self._test_jar): error_func('Unable to find test JAR: %s' % self._test_jar) - self._test_package = apk_helper.GetPackageName(self.test_apk) - self._test_runner = apk_helper.GetInstrumentationName(self.test_apk) + apk = apk_helper.ApkHelper(self.test_apk) + self._test_package = apk.GetPackageName() + self._test_runner = apk.GetInstrumentationName() self._package_info = None for package_info in constants.PACKAGE_INFO.itervalues(): @@ -274,10 +275,9 @@ class InstrumentationTestInstance(test_instance.TestInstance): constants.GetOutDirectory(), constants.SDK_BUILD_APKS_DIR, 'OnDeviceInstrumentationDriver.apk') if os.path.exists(self._driver_apk): - self._driver_package = apk_helper.GetPackageName( - self._driver_apk) - self._driver_name = apk_helper.GetInstrumentationName( - self._driver_apk) + driver_apk = apk_helper.ApkHelper(self._driver_apk) + self._driver_package = driver_apk.GetPackageName() + self._driver_name = driver_apk.GetInstrumentationName() else: self._driver_apk = None diff --git a/build/android/pylib/utils/apk_helper.py b/build/android/pylib/utils/apk_helper.py index f5e9cd3..6dd209e 100644 --- a/build/android/pylib/utils/apk_helper.py +++ b/build/android/pylib/utils/apk_helper.py @@ -19,14 +19,14 @@ _MANIFEST_ELEMENT_RE = re.compile(r'\s*(?:E|N): (\S*) .*$') def GetPackageName(apk_path): """Returns the package name of the apk.""" - aapt_cmd = [_AAPT_PATH, 'dump', 'badging', apk_path] - aapt_output = cmd_helper.GetCmdOutput(aapt_cmd).split('\n') - package_name_re = re.compile(r'package: .*name=\'(\S*)\'') - for line in aapt_output: - m = package_name_re.match(line) - if m: - return m.group(1) - raise Exception('Failed to determine package name of %s' % apk_path) + return ApkHelper(apk_path).GetPackageName() + + +# TODO(jbudorick): Deprecate and remove this function once callers have been +# converted to ApkHelper.GetInstrumentationName +def GetInstrumentationName(apk_path): + """Returns the name of the Instrumentation in the apk.""" + return ApkHelper(apk_path).GetInstrumentationName() def _ParseManifestFromApk(apk_path): @@ -65,12 +65,53 @@ def _ParseManifestFromApk(apk_path): return parsed_manifest -def GetInstrumentationName( - apk_path, default='android.test.InstrumentationTestRunner'): - """Returns the name of the Instrumentation in the apk.""" +class ApkHelper(object): + def __init__(self, apk_path): + self._apk_path = apk_path + self._manifest = None + self._package_name = None + + def GetActivityName(self): + """Returns the name of the Activity in the apk.""" + manifest_info = self._GetManifest() + try: + activity = ( + manifest_info['manifest']['application']['activity'] + ['android:name'][0]) + except KeyError: + return None + if '.' not in activity: + activity = '%s.%s' % (self.GetPackageName(), activity) + elif activity.startswith('.'): + activity = '%s%s' % (self.GetPackageName(), activity) + return activity + + def GetInstrumentationName( + self, default='android.test.InstrumentationTestRunner'): + """Returns the name of the Instrumentation in the apk.""" + manifest_info = self._GetManifest() + try: + return manifest_info['manifest']['instrumentation']['android:name'][0] + except KeyError: + return default + + def GetPackageName(self): + """Returns the package name of the apk.""" + if self._package_name: + return self._package_name + + aapt_cmd = [_AAPT_PATH, 'dump', 'badging', self._apk_path] + aapt_output = cmd_helper.GetCmdOutput(aapt_cmd).split('\n') + package_name_re = re.compile(r'package: .*name=\'(\S*)\'') + for line in aapt_output: + m = package_name_re.match(line) + if m: + self._package_name = m.group(1) + return self._package_name + raise Exception('Failed to determine package name of %s' % self._apk_path) + + def _GetManifest(self): + if not self._manifest: + self._manifest = _ParseManifestFromApk(self._apk_path) + return self._manifest - try: - manifest_info = _ParseManifestFromApk(apk_path) - return manifest_info['manifest']['instrumentation']['android:name'][0] - except KeyError: - return default diff --git a/build/apk_browsertest.gypi b/build/apk_browsertest.gypi new file mode 100644 index 0000000..316f52f --- /dev/null +++ b/build/apk_browsertest.gypi @@ -0,0 +1,43 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file is meant to be included into a target to provide a rule +# to build APK-based browser test suites. +# +# To use this, create a gyp target with the following form: +# { +# 'target_name': 'test_suite_name_apk', +# 'type': 'none', +# 'variables': { +# 'test_suite_name': 'test_suite_name', # string +# 'java_in_dir': 'path/to/java/dir', +# }, +# 'includes': ['path/to/this/gypi/file'], +# } +# + +{ + 'dependencies': [ + '<(DEPTH)/base/base.gyp:base_java', + '<(DEPTH)/build/android/pylib/device/commands/commands.gyp:chromium_commands', + '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:remote_device_dummy_apk', + '<(DEPTH)/testing/android/appurify_support.gyp:appurify_support_java', + '<(DEPTH)/testing/android/native_test.gyp:native_test_java', + '<(DEPTH)/tools/android/android_tools.gyp:android_tools', + ], + 'conditions': [ + ['OS == "android"', { + 'variables': { + # These are used to configure java_apk.gypi included below. + 'apk_name': '<(test_suite_name)', + 'intermediate_dir': '<(PRODUCT_DIR)/<(test_suite_name)_apk', + 'final_apk_path': '<(intermediate_dir)/<(test_suite_name)-debug.apk', + 'native_lib_target': 'lib<(test_suite_name)', + # TODO(yfriedman, cjhopman): Support managed installs for gtests. + 'gyp_managed_install': 0, + }, + 'includes': [ 'java_apk.gypi' ], + }], # 'OS == "android" + ], # conditions +} diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 488d972..11137e7 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni @@ -1608,7 +1608,9 @@ template("unittest_apk") { android_apk(target_name) { final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk" java_files = [ + "//testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java", "//testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java", + "//testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java", "//testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java", ] android_manifest = "//testing/android/native_test/java/AndroidManifest.xml" diff --git a/chrome/test/android/unit_tests_apk/AndroidManifest.xml b/chrome/test/android/unit_tests_apk/AndroidManifest.xml index 3dde8c8..b763fd0 100644 --- a/chrome/test/android/unit_tests_apk/AndroidManifest.xml +++ b/chrome/test/android/unit_tests_apk/AndroidManifest.xml @@ -14,7 +14,7 @@ found in the LICENSE file. - diff --git a/components/BUILD.gn b/components/BUILD.gn index 700e862..61b0867 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn @@ -342,17 +342,6 @@ repack("components_tests_pak") { ] } -if (is_android) { - import("//build/config/android/rules.gni") - - generate_jni("components_browsertests_jni_headers") { - jni_package = "components_browsertests/shell" - sources = [ - "test/android/browsertests_apk/src/org/chromium/components_browsertests_apk/ComponentsBrowserTestsActivity.java", - ] - } -} - test("components_browsertests") { sources = [ "autofill/content/browser/risk/fingerprint_browsertest.cc", @@ -394,10 +383,7 @@ test("components_browsertests") { "test/android/browsertests_apk/components_browser_tests_jni_onload.cc", ] sources -= [ "autofill/content/browser/risk/fingerprint_browsertest.cc" ] - deps += [ - ":components_browsertests_jni_headers", - "//testing/android/native_test:native_test_util", - ] + deps += [ "//testing/android/native_test:native_test_support" ] use_launcher = false } diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 623dd94..00d8805 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp @@ -1209,17 +1209,6 @@ 'includes': [ '../build/android/jinja_template.gypi' ], }, { - 'target_name': 'components_browsertests_jni_headers', - 'type': 'none', - 'sources': [ - 'test/android/browsertests_apk/src/org/chromium/components_browsertests_apk/ComponentsBrowserTestsActivity.java', - ], - 'variables': { - 'jni_gen_package': 'content/shell', - }, - 'includes': [ '../build/jni_generator.gypi' ], - }, - { # TODO(GN) 'target_name': 'components_browsertests_apk', 'type': 'none', @@ -1233,14 +1222,13 @@ 'components_browsertests', ], 'variables': { - 'apk_name': 'components_browsertests', + 'test_suite_name': 'components_browsertests', 'java_in_dir': 'test/android/browsertests_apk', 'android_manifest_path': '<(SHARED_INTERMEDIATE_DIR)/components_browsertests_manifest/AndroidManifest.xml', 'resource_dir': 'test/android/browsertests_apk/res', - 'native_lib_target': 'libcomponents_browsertests', 'asset_location': '<(PRODUCT_DIR)/components_browsertests_apk_shell/assets', }, - 'includes': [ '../build/java_apk.gypi' ], + 'includes': [ '../build/apk_browsertest.gypi' ], }, ], }], @@ -1326,16 +1314,13 @@ 'conditions': [ ['OS == "android"', { 'sources' : [ - 'test/android/browsertests_apk/components_browser_tests_android.cc', - 'test/android/browsertests_apk/components_browser_tests_android.h', 'test/android/browsertests_apk/components_browser_tests_jni_onload.cc', ], 'sources!': [ 'autofill/content/browser/risk/fingerprint_browsertest.cc', ], 'dependencies': [ - '../testing/android/native_test.gyp:native_test_util', - 'components_browsertests_jni_headers', + '../testing/android/native_test.gyp:native_test_support', ], }], ['OS == "linux"', { diff --git a/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 b/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 index 3ac010d..97dae9e 100644 --- a/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 +++ b/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 @@ -47,6 +47,10 @@ {% endfor %} + + diff --git a/components/test/android/browsertests_apk/components_browser_tests_android.cc b/components/test/android/browsertests_apk/components_browser_tests_android.cc deleted file mode 100644 index baf8efe..0000000 --- a/components/test/android/browsertests_apk/components_browser_tests_android.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This class sets up the environment for running the content browser tests -// inside an android application. - -#include -#include - -#include "base/android/base_jni_registrar.h" -#include "base/android/fifo_utils.h" -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/library_loader/library_loader_hooks.h" -#include "base/android/scoped_java_ref.h" -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/strings/string_tokenizer.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "content/public/common/content_switches.h" -#include "content/public/test/test_launcher.h" -#include "jni/ComponentsBrowserTestsActivity_jni.h" -#include "media/base/media_switches.h" -#include "testing/android/native_test/native_test_util.h" - -using testing::native_test_util::ArgsToArgv; -using testing::native_test_util::ParseArgsFromCommandLineFile; -using testing::native_test_util::ScopedMainEntryLogger; - -// The main function of the program to be wrapped as an apk. -extern int main(int argc, char** argv); - -namespace { - -// The test runner script writes the command line file in -// "/data/local/tmp". -static const char kCommandLineFilePath[] = - "/data/local/tmp/components-browser-tests-command-line"; - -} // namespace - -namespace components { - -// TODO(jaekyun): Refactor and deduplicate with -// testing/android/native_test/native_test_launcher.cc (http://crbug.com/476410) -static void RunTests(JNIEnv* env, - jobject obj, - jstring jfiles_dir, - jobject app_context) { - // Command line basic initialization, will be fully initialized later. - static const char* const kInitialArgv[] = {"ComponentsBrowserTestsActivity"}; - base::CommandLine::Init(arraysize(kInitialArgv), kInitialArgv); - - // Set the application context in base. - base::android::ScopedJavaLocalRef scoped_context( - env, env->NewLocalRef(app_context)); - base::android::InitApplicationContext(env, scoped_context); - base::android::RegisterJni(env); - - std::vector args; - ParseArgsFromCommandLineFile(kCommandLineFilePath, &args); - - std::vector argv; - int argc = ArgsToArgv(args, &argv); - - // Fully initialize command line with arguments. - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - command_line->AppendArguments(base::CommandLine(argc, &argv[0]), false); - - // Append required switches. - command_line->AppendSwitch(content::kSingleProcessTestsFlag); - command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); - command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); - // Specify a socket name to not conflict with the default one used - // in content_shell. - command_line->AppendSwitchASCII(switches::kRemoteDebuggingSocketName, - "components_browsertests_devtools_remote"); - - // Create fifo and redirect stdout and stderr to it. - base::FilePath files_dir( - base::android::ConvertJavaStringToUTF8(env, jfiles_dir)); - base::FilePath fifo_path(files_dir.Append(base::FilePath("test.fifo"))); - base::android::CreateFIFO(fifo_path, 0666); - base::android::RedirectStream(stdout, fifo_path, "w+"); - dup2(STDOUT_FILENO, STDERR_FILENO); - - ScopedMainEntryLogger scoped_main_entry_logger; - main(argc, &argv[0]); -} - -bool RegisterComponentsBrowserTestsAndroid(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace components diff --git a/components/test/android/browsertests_apk/components_browser_tests_android.h b/components/test/android/browsertests_apk/components_browser_tests_android.h deleted file mode 100644 index a989706..0000000 --- a/components/test/android/browsertests_apk/components_browser_tests_android.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_TEST_ANDROID_BROWSERTESTS_APK_COMPONENTS_BROWSER_TESTS_ANDROID_H_ -#define COMPONENTS_TEST_ANDROID_BROWSERTESTS_APK_COMPONENTS_BROWSER_TESTS_ANDROID_H_ - -#include - -namespace components { - -bool RegisterComponentsBrowserTestsAndroid(JNIEnv* env); - -} // namespace components - -#endif // COMPONENTS_TEST_ANDROID_BROWSERTESTS_APK_COMPONENTS_BROWSER_TESTS_ANDROID_H_ diff --git a/components/test/android/browsertests_apk/components_browser_tests_jni_onload.cc b/components/test/android/browsertests_apk/components_browser_tests_jni_onload.cc index e47b840..6b15e3c 100644 --- a/components/test/android/browsertests_apk/components_browser_tests_jni_onload.cc +++ b/components/test/android/browsertests_apk/components_browser_tests_jni_onload.cc @@ -2,21 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/android/base_jni_registrar.h" #include "base/android/jni_android.h" #include "base/bind.h" -#include "components/test/android/browsertests_apk/components_browser_tests_android.h" #include "content/public/app/content_jni_onload.h" #include "content/public/app/content_main.h" #include "content/public/test/nested_message_pump_android.h" #include "content/shell/android/shell_jni_registrar.h" #include "content/shell/app/shell_main_delegate.h" +#include "testing/android/native_test/native_test_launcher.h" namespace { bool RegisterJNI(JNIEnv* env) { - return content::android::RegisterShellJni(env) && - content::NestedMessagePumpAndroid::RegisterJni(env) && - components::RegisterComponentsBrowserTestsAndroid(env); + return base::android::RegisterJni(env) && + content::android::RegisterShellJni(env) && + content::NestedMessagePumpAndroid::RegisterJni(env) && + testing::android::RegisterNativeTestJNI(env); } bool Init() { diff --git a/components/test/android/browsertests_apk/src/org/chromium/components_browsertests_apk/ComponentsBrowserTestsActivity.java b/components/test/android/browsertests_apk/src/org/chromium/components_browsertests_apk/ComponentsBrowserTestsActivity.java index bbf2461..ae94edc 100644 --- a/components/test/android/browsertests_apk/src/org/chromium/components_browsertests_apk/ComponentsBrowserTestsActivity.java +++ b/components/test/android/browsertests_apk/src/org/chromium/components_browsertests_apk/ComponentsBrowserTestsActivity.java @@ -4,43 +4,44 @@ package org.chromium.components_browsertests_apk; -import android.app.Activity; -import android.content.Context; import android.os.Bundle; -import android.os.Handler; -import android.util.Log; import android.view.Window; import android.view.WindowManager; -import org.chromium.base.JNINamespace; +import org.chromium.base.Log; import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.library_loader.ProcessInitException; import org.chromium.content.browser.BrowserStartupController; import org.chromium.content_shell.ShellManager; +import org.chromium.native_test.NativeBrowserTestActivity; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.WindowAndroid; /** * Android activity for running components browser tests */ -@JNINamespace("components") -public class ComponentsBrowserTestsActivity extends Activity { - private static final String TAG = "ComponentsBrowserTestsActivity"; +public class ComponentsBrowserTestsActivity extends NativeBrowserTestActivity { + private static final String TAG = Log.makeTag("native_test"); private ShellManager mShellManager; private WindowAndroid mWindowAndroid; @Override - @SuppressFBWarnings("DM_EXIT") public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + appendCommandLineFlags( + "--remote-debugging-socket-name components_browsertests_devtools_remote"); + } + @Override + @SuppressFBWarnings("DM_EXIT") + protected void initializeBrowserProcess() { try { LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(); } catch (ProcessInitException e) { - Log.i(TAG, "Cannot load components_browsertests:" + e); + Log.e(TAG, "Cannot load components_browsertests.", e); System.exit(-1); } BrowserStartupController.get(getApplicationContext(), LibraryProcessType.PROCESS_BROWSER) @@ -55,21 +56,5 @@ public class ComponentsBrowserTestsActivity extends Activity { wind.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); wind.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); wind.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - - new Handler().post(new Runnable() { - @Override - public void run() { - Log.i(TAG, "Running tests"); - runTests(); - Log.i(TAG, "Tests finished."); - finish(); - } - }); - } - - private void runTests() { - nativeRunTests(getFilesDir().getAbsolutePath(), getApplicationContext()); } - - private native void nativeRunTests(String filesDir, Context appContext); } diff --git a/content/content_shell.gypi b/content/content_shell.gypi index b50ce10..3689835 100644 --- a/content/content_shell.gypi +++ b/content/content_shell.gypi @@ -1010,7 +1010,6 @@ 'target_name': 'content_shell_jni_headers', 'type': 'none', 'sources': [ - 'shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java', 'shell/android/java/src/org/chromium/content_shell/ShellLayoutTestUtils.java', 'shell/android/java/src/org/chromium/content_shell/ShellMojoTestUtils.java', 'shell/android/java/src/org/chromium/content_shell/ShellManager.java', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index e85fd39..52b889f 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -268,8 +268,6 @@ 'content_browsertests_android_sources': [ 'browser/accessibility/android_granularity_movement_browsertest.cc', 'browser/accessibility/android_hit_testing_browsertest.cc', - 'shell/android/browsertests_apk/content_browser_tests_android.cc', - 'shell/android/browsertests_apk/content_browser_tests_android.h', 'shell/android/browsertests_apk/content_browser_tests_jni_onload.cc', ], 'content_browsertests_webrtc_sources': [ @@ -1442,7 +1440,7 @@ 'dependencies': [ 'content_shell_jni_headers', 'content_shell_lib', - '../testing/android/native_test.gyp:native_test_util', + '../testing/android/native_test.gyp:native_test_support', ], }], ['OS=="mac"', { @@ -1804,11 +1802,10 @@ 'content_shell_java', ], 'variables': { - 'apk_name': 'content_browsertests', + 'test_suite_name': 'content_browsertests', 'java_in_dir': 'shell/android/browsertests_apk', 'android_manifest_path': '<(SHARED_INTERMEDIATE_DIR)/content_browsertests_manifest/AndroidManifest.xml', 'resource_dir': 'shell/android/browsertests_apk/res', - 'native_lib_target': 'libcontent_browsertests', 'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'], 'asset_location': '<(PRODUCT_DIR)/content_shell/assets', 'conditions': [ @@ -1825,7 +1822,7 @@ }], ], }, - 'includes': [ '../build/java_apk.gypi' ], + 'includes': [ '../build/apk_browsertest.gypi' ], }, { # TODO(GN) diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn index 96a8872..c96fb94 100644 --- a/content/shell/android/BUILD.gn +++ b/content/shell/android/BUILD.gn @@ -10,7 +10,6 @@ import("//third_party/icu/config.gni") generate_jni("content_shell_jni_headers") { jni_package = "content/shell" sources = [ - "browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java", "java/src/org/chromium/content_shell/Shell.java", "java/src/org/chromium/content_shell/ShellLayoutTestUtils.java", "java/src/org/chromium/content_shell/ShellManager.java", diff --git a/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 b/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 index b76b293..aca8da7 100644 --- a/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 +++ b/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 @@ -47,6 +47,10 @@ {% endfor %} + + diff --git a/content/shell/android/browsertests_apk/content_browser_tests_android.cc b/content/shell/android/browsertests_apk/content_browser_tests_android.cc deleted file mode 100644 index 86f43b5..0000000 --- a/content/shell/android/browsertests_apk/content_browser_tests_android.cc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This class sets up the environment for running the content browser tests -// inside an android application. - -#include -#include - -#include "base/android/base_jni_registrar.h" -#include "base/android/fifo_utils.h" -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/library_loader/library_loader_hooks.h" -#include "base/android/scoped_java_ref.h" -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/strings/string_tokenizer.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "content/public/common/content_switches.h" -#include "content/public/test/test_launcher.h" -#include "content/shell/android/shell_jni_registrar.h" -#include "content/shell/app/shell_main_delegate.h" -#include "jni/ContentBrowserTestsActivity_jni.h" -#include "media/base/media_switches.h" -#include "testing/android/native_test/native_test_util.h" - -using testing::native_test_util::ArgsToArgv; -using testing::native_test_util::ParseArgsFromCommandLineFile; -using testing::native_test_util::ScopedMainEntryLogger; - -// The main function of the program to be wrapped as an apk. -extern int main(int argc, char** argv); - -namespace { - -// The test runner script writes the command line file in -// "/data/local/tmp". -static const char kCommandLineFilePath[] = - "/data/local/tmp/content-browser-tests-command-line"; - -} // namespace - -namespace content { - -// TODO(nileshagrawal): Refactor and deduplicate with -// testing/android/native_test_launcher.cc -static void RunTests(JNIEnv* env, - jobject obj, - jstring jfiles_dir, - jobject app_context) { - // Command line basic initialization, will be fully initialized later. - static const char* const kInitialArgv[] = { "ContentBrowserTestsActivity" }; - base::CommandLine::Init(arraysize(kInitialArgv), kInitialArgv); - - // Set the application context in base. - base::android::ScopedJavaLocalRef scoped_context( - env, env->NewLocalRef(app_context)); - base::android::InitApplicationContext(env, scoped_context); - base::android::RegisterJni(env); - - std::vector args; - ParseArgsFromCommandLineFile(kCommandLineFilePath, &args); - - std::vector argv; - int argc = ArgsToArgv(args, &argv); - - // Fully initialize command line with arguments. - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - command_line->AppendArguments(base::CommandLine(argc, &argv[0]), false); - - // Append required switches. - command_line->AppendSwitch(content::kSingleProcessTestsFlag); - command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); - command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); - // Specify a socket name to not conflict with the default one used - // in content_shell. - command_line->AppendSwitchASCII(switches::kRemoteDebuggingSocketName, - "content_browsertests_devtools_remote"); - - // Create fifo and redirect stdout and stderr to it. - base::FilePath files_dir( - base::android::ConvertJavaStringToUTF8(env, jfiles_dir)); - base::FilePath fifo_path(files_dir.Append(base::FilePath("test.fifo"))); - base::android::CreateFIFO(fifo_path, 0666); - base::android::RedirectStream(stdout, fifo_path, "w+"); - dup2(STDOUT_FILENO, STDERR_FILENO); - - ScopedMainEntryLogger scoped_main_entry_logger; - main(argc, &argv[0]); -} - -bool RegisterContentBrowserTestsAndroid(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace content diff --git a/content/shell/android/browsertests_apk/content_browser_tests_android.h b/content/shell/android/browsertests_apk/content_browser_tests_android.h deleted file mode 100644 index bb80784..0000000 --- a/content/shell/android/browsertests_apk/content_browser_tests_android.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_SHELL_ANDROID_BROWSERTESTS_APK_CONTENT_BROWSER_TESTS_ANDROID_H_ -#define CONTENT_SHELL_ANDROID_BROWSERTESTS_APK_CONTENT_BROWSER_TESTS_ANDROID_H_ - -#include - -namespace content { - -bool RegisterContentBrowserTestsAndroid(JNIEnv* env); - -} // namespace content - -#endif // CONTENT_SHELL_ANDROID_BROWSERTESTS_APK_CONTENT_BROWSER_TESTS_ANDROID_H_ diff --git a/content/shell/android/browsertests_apk/content_browser_tests_jni_onload.cc b/content/shell/android/browsertests_apk/content_browser_tests_jni_onload.cc index 26f93d4..8379008 100644 --- a/content/shell/android/browsertests_apk/content_browser_tests_jni_onload.cc +++ b/content/shell/android/browsertests_apk/content_browser_tests_jni_onload.cc @@ -2,21 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/android/base_jni_registrar.h" #include "base/android/jni_android.h" #include "base/bind.h" #include "content/public/app/content_jni_onload.h" #include "content/public/app/content_main.h" #include "content/public/test/nested_message_pump_android.h" -#include "content/shell/android/browsertests_apk/content_browser_tests_android.h" #include "content/shell/android/shell_jni_registrar.h" #include "content/shell/app/shell_main_delegate.h" +#include "testing/android/native_test/native_test_launcher.h" namespace { bool RegisterJNI(JNIEnv* env) { - return content::android::RegisterShellJni(env) && + return base::android::RegisterJni(env) && + content::android::RegisterShellJni(env) && content::NestedMessagePumpAndroid::RegisterJni(env) && - content::RegisterContentBrowserTestsAndroid(env); + testing::android::RegisterNativeTestJNI(env); } bool Init() { diff --git a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java index bc95f1c..d10b719 100644 --- a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java +++ b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java @@ -4,43 +4,44 @@ package org.chromium.content_browsertests_apk; -import android.app.Activity; -import android.content.Context; import android.os.Bundle; -import android.os.Handler; -import android.util.Log; import android.view.Window; import android.view.WindowManager; -import org.chromium.base.JNINamespace; +import org.chromium.base.Log; import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.library_loader.ProcessInitException; import org.chromium.content.browser.BrowserStartupController; import org.chromium.content_shell.ShellManager; +import org.chromium.native_test.NativeBrowserTestActivity; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.WindowAndroid; /** * Android activity for running content browser tests */ -@JNINamespace("content") -public class ContentBrowserTestsActivity extends Activity { - private static final String TAG = "ChromeBrowserTestsActivity"; +public class ContentBrowserTestsActivity extends NativeBrowserTestActivity { + private static final String TAG = Log.makeTag("native_test"); private ShellManager mShellManager; private WindowAndroid mWindowAndroid; @Override - @SuppressFBWarnings("DM_EXIT") public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + appendCommandLineFlags( + "--remote-debugging-socket-name content_browsertests_devtools_remote"); + } + @Override + @SuppressFBWarnings("DM_EXIT") + protected void initializeBrowserProcess() { try { LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(); } catch (ProcessInitException e) { - Log.i(TAG, "Cannot load content_browsertests:" + e); + Log.e(TAG, "Cannot load content_browsertests.", e); System.exit(-1); } BrowserStartupController.get(getApplicationContext(), LibraryProcessType.PROCESS_BROWSER) @@ -55,21 +56,5 @@ public class ContentBrowserTestsActivity extends Activity { wind.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); wind.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); wind.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - - new Handler().post(new Runnable() { - @Override - public void run() { - Log.i(TAG, "Running tests"); - runTests(); - Log.i(TAG, "Tests finished."); - finish(); - } - }); - } - - private void runTests() { - nativeRunTests(getFilesDir().getAbsolutePath(), getApplicationContext()); } - - private native void nativeRunTests(String filesDir, Context appContext); } diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 5b33e71..7fd7144 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn @@ -350,7 +350,7 @@ if (!is_mac) { deps += [ "//content/shell/android:content_shell_jni_headers", "//content/shell:content_shell_lib", - "//testing/android/native_test:native_test_util", + "//testing/android/native_test:native_test_support", ] use_launcher = false diff --git a/testing/android/native_test.gyp b/testing/android/native_test.gyp index 5993c43..fcfd7d7 100644 --- a/testing/android/native_test.gyp +++ b/testing/android/native_test.gyp @@ -7,14 +7,27 @@ ['OS=="android"', { 'targets': [ { - # GN: //testing/android:native_test_native_code - 'target_name': 'native_test_native_code', + # GN: //testing/android:native_test_jni_headers + 'target_name': 'native_test_jni_headers', + 'type': 'none', + 'sources': [ + 'native_test/java/src/org/chromium/native_test/NativeTestActivity.java' + ], + 'variables': { + 'jni_gen_package': 'testing', + }, + 'includes': [ '../../build/jni_generator.gypi' ], + }, + { + # GN: //testing/android:native_test_support + 'target_name': 'native_test_support', 'message': 'building native pieces of native test package', 'type': 'static_library', 'sources': [ - 'native_test/native_test_jni_onload.cc', 'native_test/native_test_launcher.cc', 'native_test/native_test_launcher.h', + 'native_test/native_test_util.cc', + 'native_test/native_test_util.h', ], 'dependencies': [ '../../base/base.gyp:base', @@ -22,33 +35,36 @@ '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../gtest.gyp:gtest', 'native_test_jni_headers', - 'native_test_util', ], }, { - # GN: //testing/android:native_test_jni_headers - 'target_name': 'native_test_jni_headers', - 'type': 'none', - 'sources': [ - 'native_test/java/src/org/chromium/native_test/NativeTestActivity.java' - ], - 'variables': { - 'jni_gen_package': 'testing', - }, - 'includes': [ '../../build/jni_generator.gypi' ], - }, - { - # GN: //testing/android:native_test_util - 'target_name': 'native_test_util', + # GN: //testing/android:native_test_native_code + 'target_name': 'native_test_native_code', + 'message': 'building JNI onload for native test package', 'type': 'static_library', 'sources': [ - 'native_test/native_test_util.cc', - 'native_test/native_test_util.h', + 'native_test/native_test_jni_onload.cc', ], 'dependencies': [ + 'native_test_support', '../../base/base.gyp:base', ], }, + { + 'target_name': 'native_test_java', + 'type': 'none', + 'dependencies': [ + 'appurify_support.gyp:appurify_support_java', + '../../base/base.gyp:base_native_libraries_gen', + '../../base/base.gyp:base_java', + ], + 'variables': { + 'chromium_code': '1', + 'jar_excluded_classes': [ '*/NativeLibraries.class' ], + 'java_in_dir': 'native_test/java', + }, + 'includes': [ '../../build/java.gypi' ], + }, ], }] ], diff --git a/testing/android/native_test/BUILD.gn b/testing/android/native_test/BUILD.gn index 5df47fd..0e8ffcb 100644 --- a/testing/android/native_test/BUILD.gn +++ b/testing/android/native_test/BUILD.gn @@ -4,18 +4,17 @@ import("//build/config/android/rules.gni") -# GYP: //testing/android/native_test.gyp:native_test_native_code -source_set("native_test_native_code") { +# GYP: //testing/android/native_test.gyp:native_test_support +source_set("native_test_support") { testonly = true sources = [ - "native_test_jni_onload.cc", "native_test_launcher.cc", "native_test_launcher.h", + "native_test_util.cc", + "native_test_util.h", ] - libs = [ "log" ] deps = [ ":native_test_jni_headers", - ":native_test_util", "//base", "//base/test:test_support", "//base/third_party/dynamic_annotations", @@ -23,21 +22,23 @@ source_set("native_test_native_code") { ] } -# GYP: //testing/android/native_test.gyp:native_test_jni_headers -generate_jni("native_test_jni_headers") { +# GYP: //testing/android/native_test.gyp:native_test_native_code +source_set("native_test_native_code") { + testonly = true sources = [ - "java/src/org/chromium/native_test/NativeTestActivity.java", + "native_test_jni_onload.cc", + ] + libs = [ "log" ] + deps = [ + ":native_test_support", + "//base", ] - jni_package = "testing" } -# GYP: //testing/android/native_test.gyp:native_test_util -source_set("native_test_util") { +# GYP: //testing/android/native_test.gyp:native_test_jni_headers +generate_jni("native_test_jni_headers") { sources = [ - "native_test_util.cc", - "native_test_util.h", - ] - deps = [ - "//base", + "java/src/org/chromium/native_test/NativeTestActivity.java", ] + jni_package = "testing" } diff --git a/testing/android/native_test/java/AndroidManifest.xml b/testing/android/native_test/java/AndroidManifest.xml index 37cc82d..6505014 100644 --- a/testing/android/native_test/java/AndroidManifest.xml +++ b/testing/android/native_test/java/AndroidManifest.xml @@ -22,7 +22,7 @@ found in the LICENSE file. - diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java new file mode 100644 index 0000000..ac2ddee --- /dev/null +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java @@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.native_test; + +import android.os.Bundle; + +/** + * An {@link android.app.Activity} for running native browser tests. + */ +public abstract class NativeBrowserTestActivity extends NativeTestActivity { + + private static final String BROWSER_TESTS_FLAGS[] = { + // content::kSingleProcessTestsFlag + "--single_process", + + // switches::kUseFakeDeviceForMediaStream + "--use-fake-device-for-media-stream", + + // switches::kUseFakeUIForMediaStream + "--use-fake-ui-for-media-stream" + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + for (String flag : BROWSER_TESTS_FLAGS) { + appendCommandLineFlags(flag); + } + } + + @Override + public void onStart() { + initializeBrowserProcess(); + super.onStart(); + } + + /** Initializes the browser process. + * + * This generally includes loading native libraries and switching to the native command line, + * among other things. + */ + protected abstract void initializeBrowserProcess(); + +} diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java index e8c4055..46a490b 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java @@ -6,16 +6,14 @@ package org.chromium.native_test; import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import org.chromium.base.CommandLine; +import org.chromium.base.JNINamespace; import org.chromium.base.Log; -import org.chromium.base.PathUtils; -import org.chromium.base.PowerMonitor; -import org.chromium.base.ResourceExtractor; -import org.chromium.base.library_loader.NativeLibraries; import java.io.File; @@ -24,6 +22,7 @@ import java.io.File; * Our tests need to go up to our own java classes, which is not possible using * the native activity class loader. */ +@JNINamespace("testing::android") public class NativeTestActivity extends Activity { public static final String EXTRA_COMMAND_LINE_FILE = "org.chromium.native_test.NativeTestActivity.CommandLineFile"; @@ -37,25 +36,54 @@ public class NativeTestActivity extends Activity { // We post a delayed task to run tests so that we do not block onCreate(). private static final long RUN_TESTS_DELAY_IN_MS = 300; + private String mCommandLineFilePath; + private StringBuilder mCommandLineFlags = new StringBuilder(); + private boolean mRunInSubThread = false; + private boolean mStdoutFifo = false; + private String mStdoutFilePath; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); CommandLine.init(new String[]{}); - // Needed by path_utils_unittest.cc - PathUtils.setPrivateDataDirectorySuffix("chrome", getApplicationContext()); + parseArgumentsFromIntent(getIntent()); + } + + private void parseArgumentsFromIntent(Intent intent) { + mCommandLineFilePath = intent.getStringExtra(EXTRA_COMMAND_LINE_FILE); + if (mCommandLineFilePath == null) { + mCommandLineFilePath = ""; + } else { + File commandLineFile = new File(mCommandLineFilePath); + if (!commandLineFile.isAbsolute()) { + mCommandLineFilePath = Environment.getExternalStorageDirectory() + "/" + + mCommandLineFilePath; + } + Log.i(TAG, "command line file path: %s", mCommandLineFilePath); + } - ResourceExtractor resourceExtractor = ResourceExtractor.get(getApplicationContext()); - resourceExtractor.setExtractAllPaksAndV8SnapshotForTesting(); - resourceExtractor.startExtractingResources(); - resourceExtractor.waitForCompletion(); + String commandLineFlags = intent.getStringExtra(EXTRA_COMMAND_LINE_FLAGS); + if (commandLineFlags != null) mCommandLineFlags.append(commandLineFlags); - // Needed by system_monitor_unittest.cc - PowerMonitor.createForTests(this); + mRunInSubThread = intent.hasExtra(EXTRA_RUN_IN_SUB_THREAD); - loadLibraries(); - Bundle extras = this.getIntent().getExtras(); - if (extras != null && extras.containsKey(EXTRA_RUN_IN_SUB_THREAD)) { + mStdoutFilePath = intent.getStringExtra(EXTRA_STDOUT_FILE); + if (mStdoutFilePath == null) { + mStdoutFilePath = new File(getFilesDir(), "test.fifo").getAbsolutePath(); + mStdoutFifo = true; + } + } + + protected void appendCommandLineFlags(String flags) { + mCommandLineFlags.append(" ").append(flags); + } + + @Override + public void onStart() { + super.onStart(); + + if (mRunInSubThread) { // Create a new thread and run tests on it. new Thread() { @Override @@ -76,31 +104,8 @@ public class NativeTestActivity extends Activity { } private void runTests() { - String commandLineFlags = getIntent().getStringExtra(EXTRA_COMMAND_LINE_FLAGS); - if (commandLineFlags == null) commandLineFlags = ""; - - String commandLineFilePath = getIntent().getStringExtra(EXTRA_COMMAND_LINE_FILE); - if (commandLineFilePath == null) { - commandLineFilePath = ""; - } else { - File commandLineFile = new File(commandLineFilePath); - if (!commandLineFile.isAbsolute()) { - commandLineFilePath = Environment.getExternalStorageDirectory() + "/" - + commandLineFilePath; - } - Log.i(TAG, "command line file path: %s", commandLineFilePath); - } - - String stdoutFilePath = getIntent().getStringExtra(EXTRA_STDOUT_FILE); - boolean stdoutFifo = false; - if (stdoutFilePath == null) { - stdoutFilePath = new File(getFilesDir(), "test.fifo").getAbsolutePath(); - stdoutFifo = true; - } - - // This directory is used by build/android/pylib/test_package_apk.py. - nativeRunTests(commandLineFlags, commandLineFilePath, stdoutFilePath, stdoutFifo, - getApplicationContext()); + nativeRunTests(mCommandLineFlags.toString(), mCommandLineFilePath, mStdoutFilePath, + mStdoutFifo, getApplicationContext()); finish(); } @@ -111,14 +116,6 @@ public class NativeTestActivity extends Activity { Log.e(TAG, "[ RUNNER_FAILED ] could not load native library"); } - private void loadLibraries() { - for (String library : NativeLibraries.LIBRARIES) { - Log.i(TAG, "loading: %s", library); - System.loadLibrary(library); - Log.i(TAG, "loaded: %s", library); - } - } - private native void nativeRunTests(String commandLineFlags, String commandLineFilePath, String stdoutFilePath, boolean stdoutFifo, Context appContext); } diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java index 2f6bdad..4db6286 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java @@ -32,21 +32,31 @@ import java.util.regex.Pattern; */ public class NativeTestInstrumentationTestRunner extends Instrumentation { + public static final String EXTRA_NATIVE_TEST_ACTIVITY = + "org.chromium.native_test.NativeTestInstrumentationTestRunner." + + "NativeTestActivity"; + private static final String TAG = Log.makeTag("native_test"); private static final int ACCEPT_TIMEOUT_MS = 5000; + private static final String DEFAULT_NATIVE_TEST_ACTIVITY = + "org.chromium.native_test.NativeUnitTestActivity"; private static final Pattern RE_TEST_OUTPUT = Pattern.compile("\\[ *([^ ]*) *\\] ?([^ ]+) .*"); + private ResultsBundleGenerator mBundleGenerator = new RobotiumBundleGenerator(); private String mCommandLineFile; private String mCommandLineFlags; + private String mNativeTestActivity; + private Bundle mLogBundle = new Bundle(); private File mStdoutFile; - private Bundle mLogBundle; - private ResultsBundleGenerator mBundleGenerator; @Override public void onCreate(Bundle arguments) { mCommandLineFile = arguments.getString(NativeTestActivity.EXTRA_COMMAND_LINE_FILE); mCommandLineFlags = arguments.getString(NativeTestActivity.EXTRA_COMMAND_LINE_FLAGS); + mNativeTestActivity = arguments.getString(EXTRA_NATIVE_TEST_ACTIVITY); + if (mNativeTestActivity == null) mNativeTestActivity = DEFAULT_NATIVE_TEST_ACTIVITY; + try { mStdoutFile = File.createTempFile( ".temp_stdout_", ".txt", Environment.getExternalStorageDirectory()); @@ -56,8 +66,6 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation { finish(Activity.RESULT_CANCELED, new Bundle()); return; } - mLogBundle = new Bundle(); - mBundleGenerator = new RobotiumBundleGenerator(); start(); } @@ -94,9 +102,7 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation { */ private Activity startNativeTestActivity() { Intent i = new Intent(Intent.ACTION_MAIN); - i.setComponent(new ComponentName( - "org.chromium.native_test", - "org.chromium.native_test.NativeTestActivity")); + 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); diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java new file mode 100644 index 0000000..ae66727 --- /dev/null +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java @@ -0,0 +1,48 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.native_test; + +import android.os.Bundle; + +import org.chromium.base.Log; +import org.chromium.base.PathUtils; +import org.chromium.base.PowerMonitor; +import org.chromium.base.ResourceExtractor; +import org.chromium.base.library_loader.NativeLibraries; + +/** + * An {@link android.app.Activity} for running native unit tests. + * (i.e., not browser tests) + */ +public class NativeUnitTestActivity extends NativeTestActivity { + + private static final String TAG = Log.makeTag("native_test"); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Needed by path_utils_unittest.cc + PathUtils.setPrivateDataDirectorySuffix("chrome", getApplicationContext()); + + ResourceExtractor resourceExtractor = ResourceExtractor.get(getApplicationContext()); + resourceExtractor.setExtractAllPaksAndV8SnapshotForTesting(); + resourceExtractor.startExtractingResources(); + resourceExtractor.waitForCompletion(); + + // Needed by system_monitor_unittest.cc + PowerMonitor.createForTests(this); + + loadLibraries(); + } + + private void loadLibraries() { + for (String library : NativeLibraries.LIBRARIES) { + Log.i(TAG, "loading: %s", library); + System.loadLibrary(library); + Log.i(TAG, "loaded: %s", library); + } + } +} diff --git a/testing/android/native_test/native_test_jni_onload.cc b/testing/android/native_test/native_test_jni_onload.cc index 041aa74..8fecc44 100644 --- a/testing/android/native_test/native_test_jni_onload.cc +++ b/testing/android/native_test/native_test_jni_onload.cc @@ -10,11 +10,11 @@ namespace { bool RegisterJNI(JNIEnv* env) { - return RegisterNativeTestJNI(env); + return testing::android::RegisterNativeTestJNI(env); } bool Init() { - InstallHandlers(); + testing::android::InstallHandlers(); return true; } diff --git a/testing/android/native_test/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc index d49ca11..343f118 100644 --- a/testing/android/native_test/native_test_launcher.cc +++ b/testing/android/native_test/native_test_launcher.cc @@ -28,14 +28,12 @@ #include "jni/NativeTestActivity_jni.h" #include "testing/android/native_test/native_test_util.h" -using testing::native_test_util::ArgsToArgv; -using testing::native_test_util::ParseArgsFromCommandLineFile; -using testing::native_test_util::ParseArgsFromString; -using testing::native_test_util::ScopedMainEntryLogger; - // The main function of the program to be wrapped as a test apk. extern int main(int argc, char** argv); +namespace testing { +namespace android { + namespace { // The test runner script writes the command line file in @@ -123,7 +121,7 @@ static void RunTests(JNIEnv* env, exit(EXIT_FAILURE); } } - if (!base::android::RedirectStream(stdout, stdout_file_path, "w")) { + if (!base::android::RedirectStream(stdout, stdout_file_path, "w+")) { AndroidLog(ANDROID_LOG_ERROR, "Failed to redirect stream to file: %s: %s\n", stdout_file_path.value().c_str(), strerror(errno)); exit(EXIT_FAILURE); @@ -145,7 +143,6 @@ bool RegisterNativeTestJNI(JNIEnv* env) { return RegisterNativesImpl(env); } - // TODO(nileshagrawal): now that we're using FIFO, test scripts can detect EOF. // Remove the signal handlers. void InstallHandlers() { @@ -159,3 +156,6 @@ void InstallHandlers() { sigaction(kExceptionSignals[i], &sa, &g_old_sa[kExceptionSignals[i]]); } } + +} // namespace android +} // namespace testing diff --git a/testing/android/native_test/native_test_launcher.h b/testing/android/native_test/native_test_launcher.h index cdd1e76..ea4dfe8 100644 --- a/testing/android/native_test/native_test_launcher.h +++ b/testing/android/native_test/native_test_launcher.h @@ -7,7 +7,13 @@ #include +namespace testing { +namespace android { + void InstallHandlers(); bool RegisterNativeTestJNI(JNIEnv* env); +} // namespace android +} // namespace testing + #endif // TESTING_ANDROID_NATIVE_TEST_LAUNCHER_H_ diff --git a/testing/android/native_test/native_test_util.cc b/testing/android/native_test/native_test_util.cc index 2eaf971..ffb1b11 100644 --- a/testing/android/native_test/native_test_util.cc +++ b/testing/android/native_test/native_test_util.cc @@ -10,7 +10,7 @@ #include "base/strings/string_util.h" namespace testing { -namespace native_test_util { +namespace android { void ParseArgsFromString(const std::string& command_line, std::vector* args) { @@ -46,5 +46,5 @@ int ArgsToArgv(const std::vector& args, return argc; } -} // namespace native_test_util +} // namespace android } // namespace testing diff --git a/testing/android/native_test/native_test_util.h b/testing/android/native_test/native_test_util.h index ef17e52..e647a92 100644 --- a/testing/android/native_test/native_test_util.h +++ b/testing/android/native_test/native_test_util.h @@ -12,7 +12,7 @@ // Helper methods for setting up environment for running gtest tests // inside an APK. namespace testing { -namespace native_test_util { +namespace android { class ScopedMainEntryLogger { public: @@ -33,7 +33,7 @@ void ParseArgsFromCommandLineFile( const char* path, std::vector* args); int ArgsToArgv(const std::vector& args, std::vector* argv); -} // namespace native_test_util +} // namespace android } // namespace testing #endif // TESTING_ANDROID_NATIVE_TEST_UTIL_ -- cgit v1.1