From 581d25e509e4a2b1e8927c6d8accc0c90ea86090 Mon Sep 17 00:00:00 2001 From: jbudorick Date: Tue, 19 May 2015 10:09:11 -0700 Subject: [Android] Refactor the native test wrappers. BUG=476410 Review URL: https://codereview.chromium.org/1126543009 Cr-Commit-Position: refs/heads/master@{#330531} --- 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 | 22 +++-- .../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 +- 12 files changed, 226 insertions(+), 106 deletions(-) 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 (limited to 'testing/android') 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 c5a4443..e1f6f14c 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 @@ -31,6 +31,9 @@ import java.util.regex.Pattern; * An Instrumentation that runs tests based on NativeTestActivity. */ public class NativeTestInstrumentationTestRunner extends Instrumentation { + public static final String EXTRA_NATIVE_TEST_ACTIVITY = + "org.chromium.native_test.NativeTestInstrumentationTestRunner." + + "NativeTestActivity"; // TODO(jbudorick): Remove this extra when b/18981674 is fixed. public static final String EXTRA_ONLY_OUTPUT_FAILURES = "org.chromium.native_test.NativeTestInstrumentationTestRunner." @@ -39,19 +42,25 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation { 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 File mStdoutFile; - private Bundle mLogBundle; - private ResultsBundleGenerator mBundleGenerator; + private String mNativeTestActivity; + private Bundle mLogBundle = new Bundle(); private boolean mOnlyOutputFailures; + private File mStdoutFile; @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()); @@ -61,8 +70,7 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation { finish(Activity.RESULT_CANCELED, new Bundle()); return; } - mLogBundle = new Bundle(); - mBundleGenerator = new RobotiumBundleGenerator(); + mOnlyOutputFailures = arguments.containsKey(EXTRA_ONLY_OUTPUT_FAILURES); start(); } @@ -100,9 +108,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