mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-03 14:09:33 +03:00
Improve Angle Android gtest support
This CL makes angle_test() use an angle-specific gtest launcher - AngleUnitTestActivity.java. This enables building standalone Android angle without //base Chromium-Bug: 1149922 Bug: None Change-Id: Id84f3e2bd84c5017ed1988ca07534f424ebfa596 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2745535 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
committed by
Commit Bot
parent
2ef1e0fc7d
commit
bf0c6ae1ee
@@ -99,8 +99,8 @@ angle_libs_suffix = "_ANGLE_DEV"
|
||||
```
|
||||
|
||||
All
|
||||
[NativeTest](https://chromium.googlesource.com/chromium/src/+/master/testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java)
|
||||
based tests share the same activity name, `org.chromium.native_test.NativeUnitTestNativeActivity`.
|
||||
[AngleNativeTest](https://chromium.googlesource.com/chromium/src/+/master/third_party/angle/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java)
|
||||
based tests share the same activity name, `com.android.angle.test.AngleUnitTestActivity`.
|
||||
Thus, prior to capturing your test trace, the specific test APK must be installed on the device.
|
||||
When you build the test, a test launcher is generated, for example,
|
||||
`./out/Release/bin/run_angle_end2end_tests`. The best way to install the APK is to run this test
|
||||
@@ -109,14 +109,14 @@ launcher once.
|
||||
In GAPID's "Capture Trace" dialog, "Package / Action:" should be:
|
||||
|
||||
```
|
||||
android.intent.action.MAIN:org.chromium.native_test/org.chromium.native_test.NativeUnitTestNativeActivity
|
||||
android.intent.action.MAIN:com.android.angle.test/com.android.angle.test.AngleUnitTestActivity
|
||||
```
|
||||
|
||||
The mandatory [extra intent
|
||||
argument](https://developer.android.com/studio/command-line/adb.html#IntentSpec) for starting the
|
||||
activity is `org.chromium.native_test.NativeTest.StdoutFile`. Without it the test APK crashes. Test
|
||||
filters can be specified via either the `org.chromium.native_test.NativeTest.CommandLineFlags` or
|
||||
the `org.chromium.native_test.NativeTest.Shard` argument. Example "Intent Arguments:" values in
|
||||
the `org.chromium.native_test.NativeTest.GtestFilter` argument. Example "Intent Arguments:" values in
|
||||
GAPID's "Capture Trace" dialog:
|
||||
|
||||
```
|
||||
@@ -126,7 +126,7 @@ GAPID's "Capture Trace" dialog:
|
||||
or
|
||||
|
||||
```
|
||||
-e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt --esal org.chromium.native_test.NativeTest.Shard RendererTest.SimpleOperation/ES2_VULKAN,SimpleOperationTest.DrawWithTexture/ES2_VULKAN
|
||||
-e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt --e org.chromium.native_test.NativeTest.GtestFilter RendererTest.SimpleOperation/ES2_VULKAN:SimpleOperationTest.DrawWithTexture/ES2_VULKAN
|
||||
```
|
||||
|
||||
## Running ANGLE under RenderDoc
|
||||
|
||||
@@ -420,8 +420,13 @@ if (angle_standalone || build_with_chromium) {
|
||||
if (is_android) {
|
||||
public_configs += [ "$angle_root:build_id_config" ]
|
||||
if (build_with_chromium) {
|
||||
use_native_activity = true
|
||||
configs -= [ "//build/config/android:hide_all_but_jni" ]
|
||||
use_default_launcher = false
|
||||
android_manifest_template = "$angle_root/src/tests/test_utils/runner/android/java/AndroidManifest.xml.jinja2"
|
||||
deps += [
|
||||
"$angle_root/src/tests:native_test_java",
|
||||
"$angle_root/src/tests:native_test_support_android",
|
||||
]
|
||||
} else {
|
||||
use_raw_android_executable = true
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "string_utils.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace angle;
|
||||
@@ -92,6 +93,46 @@ TEST(StringUtilsTest, SplitString_WhitespaceAndResultType)
|
||||
ASSERT_TRUE(r.empty());
|
||||
}
|
||||
|
||||
// Tests for SplitStringAlongWhitespace
|
||||
TEST(StringUtilsTest, SplitStringAlongWhitespace)
|
||||
{
|
||||
{
|
||||
// No whitespace.
|
||||
std::vector<std::string> r;
|
||||
SplitStringAlongWhitespace("abcd", &r);
|
||||
ASSERT_THAT(r, testing::ElementsAre("abcd"));
|
||||
}
|
||||
|
||||
{
|
||||
// Just whitespace.
|
||||
std::vector<std::string> r;
|
||||
SplitStringAlongWhitespace(" \t", &r);
|
||||
ASSERT_THAT(r, testing::ElementsAre());
|
||||
}
|
||||
|
||||
{
|
||||
// Consecutive whitespace of same type.
|
||||
std::vector<std::string> r;
|
||||
SplitStringAlongWhitespace("a b", &r);
|
||||
ASSERT_THAT(r, testing::ElementsAre("a", "b"));
|
||||
}
|
||||
|
||||
{
|
||||
// Consecutive whitespace of different types.
|
||||
std::vector<std::string> r;
|
||||
SplitStringAlongWhitespace("ab \tcd", &r);
|
||||
ASSERT_THAT(r, testing::ElementsAre("ab", "cd"));
|
||||
}
|
||||
|
||||
{
|
||||
// Non-empty output std::vector.
|
||||
std::vector<std::string> r;
|
||||
r.push_back("z");
|
||||
SplitStringAlongWhitespace("abc", &r);
|
||||
ASSERT_THAT(r, testing::ElementsAre("z", "abc"));
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for TrimString
|
||||
TEST(StringUtilsTest, TrimString)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,28 @@ declare_args() {
|
||||
is_win || is_linux || is_chromeos || is_android || is_apple || is_fuchsia
|
||||
}
|
||||
|
||||
if (is_android && build_with_chromium) {
|
||||
android_library("native_test_java") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java",
|
||||
"test_utils/runner/android/java/src/com/android/angle/test/AngleUnitTestActivity.java",
|
||||
"test_utils/runner/android/java/src/com/android/angle/test/TestStatusReporter.java",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//build/android:native_libraries_java",
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
]
|
||||
}
|
||||
|
||||
angle_source_set("native_test_support_android") {
|
||||
testonly = true
|
||||
sources = [ "test_utils/runner/android/AngleNativeTest.cpp" ]
|
||||
deps = [ "$angle_root:angle_common" ]
|
||||
}
|
||||
}
|
||||
|
||||
angle_test("test_utils_unittest_helper") {
|
||||
sources = [
|
||||
"../../util/test_utils_unittest_helper.cpp",
|
||||
|
||||
160
src/tests/test_utils/runner/android/AngleNativeTest.cpp
Normal file
160
src/tests/test_utils/runner/android/AngleNativeTest.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// angle_native_test:
|
||||
// Contains native implementation for com.android.angle.test.AngleNativeTest.
|
||||
|
||||
#include <jni.h>
|
||||
#include <vector>
|
||||
|
||||
#include <android/log.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/string_utils.h"
|
||||
|
||||
// The main function of the program to be wrapped as a test apk.
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const char kLogTag[] = "chromium";
|
||||
const char kCrashedMarker[] = "[ CRASHED ]\n";
|
||||
|
||||
// The list of signals which are considered to be crashes.
|
||||
const int kExceptionSignals[] = {SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1};
|
||||
|
||||
struct sigaction g_old_sa[NSIG];
|
||||
|
||||
class ScopedMainEntryLogger
|
||||
{
|
||||
public:
|
||||
ScopedMainEntryLogger() { printf(">>ScopedMainEntryLogger\n"); }
|
||||
|
||||
~ScopedMainEntryLogger()
|
||||
{
|
||||
printf("<<ScopedMainEntryLogger\n");
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
};
|
||||
|
||||
// This function runs in a compromised context. It should not allocate memory.
|
||||
void SignalHandler(int sig, siginfo_t *info, void *reserved)
|
||||
{
|
||||
// Output the crash marker.
|
||||
write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker) - 1);
|
||||
g_old_sa[sig].sa_sigaction(sig, info, reserved);
|
||||
}
|
||||
|
||||
std::string ASCIIJavaStringToUTF8(JNIEnv *env, jstring str)
|
||||
{
|
||||
if (!str)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
const jsize length = env->GetStringLength(str);
|
||||
if (!length)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so
|
||||
// instead get the String in UTF16. As the input is ASCII, drop the higher
|
||||
// bytes.
|
||||
const jchar *jchars = env->GetStringChars(str, NULL);
|
||||
const char16_t *chars = reinterpret_cast<const char16_t *>(jchars);
|
||||
std::string out(chars, chars + length);
|
||||
env->ReleaseStringChars(str, jchars);
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t ArgsToArgv(const std::vector<std::string> &args, std::vector<char *> *argv)
|
||||
{
|
||||
// We need to pass in a non-const char**.
|
||||
size_t argc = args.size();
|
||||
|
||||
argv->resize(argc + 1);
|
||||
for (size_t i = 0; i < argc; ++i)
|
||||
{
|
||||
(*argv)[i] = const_cast<char *>(args[i].c_str());
|
||||
}
|
||||
(*argv)[argc] = NULL; // argv must be NULL terminated.
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
void InstallExceptionHandlers()
|
||||
{
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
sa.sa_sigaction = SignalHandler;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
|
||||
for (unsigned int i = 0; kExceptionSignals[i] != -1; ++i)
|
||||
{
|
||||
sigaction(kExceptionSignals[i], &sa, &g_old_sa[kExceptionSignals[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidLog(int priority, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
__android_log_vprint(priority, kLogTag, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_android_angle_test_AngleNativeTest_nativeRunTests(JNIEnv *env,
|
||||
jclass clazz,
|
||||
jstring jcommandLineFlags,
|
||||
jstring jcommandLineFilePath,
|
||||
jstring jstdoutFilePath)
|
||||
{
|
||||
InstallExceptionHandlers();
|
||||
|
||||
const std::string commandLineFlags(ASCIIJavaStringToUTF8(env, jcommandLineFlags));
|
||||
const std::string commandLineFilePath(ASCIIJavaStringToUTF8(env, jcommandLineFilePath));
|
||||
const std::string stdoutFilePath(ASCIIJavaStringToUTF8(env, jstdoutFilePath));
|
||||
|
||||
std::vector<std::string> args;
|
||||
if (commandLineFilePath.empty())
|
||||
{
|
||||
args.push_back("_");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string commandLineString;
|
||||
if (angle::ReadFileToString(commandLineFilePath, &commandLineString))
|
||||
{
|
||||
angle::SplitStringAlongWhitespace(commandLineString, &args);
|
||||
}
|
||||
}
|
||||
angle::SplitStringAlongWhitespace(commandLineFlags, &args);
|
||||
|
||||
// A few options, such "--gtest_list_tests", will just use printf directly
|
||||
// Always redirect stdout to a known file.
|
||||
if (freopen(stdoutFilePath.c_str(), "a+", stdout) == NULL)
|
||||
{
|
||||
AndroidLog(ANDROID_LOG_ERROR, "Failed to redirect stream to file: %s: %s\n",
|
||||
stdoutFilePath.c_str(), strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dup2(STDOUT_FILENO, STDERR_FILENO);
|
||||
|
||||
std::vector<char *> argv;
|
||||
size_t argc = ArgsToArgv(args, &argv);
|
||||
|
||||
ScopedMainEntryLogger scoped_main_entry_logger;
|
||||
main(static_cast<int>(argc), &argv[0]);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2021 The ANGLE Project Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style license that can be
|
||||
found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.angle.test"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<!-- Explicitly set the attribute requestLegacyExternalStorage to "true"
|
||||
since it is "false" by default on apps targeting Android 10, and that
|
||||
breaks test listing. See
|
||||
https://developer.android.com/training/data-storage#scoped-storage and
|
||||
https://developer.android.com/training/data-storage/compatibility. -->
|
||||
<application android:label="NativeTests"
|
||||
android:requestLegacyExternalStorage="true">
|
||||
<uses-library android:name="android.test.runner"/>
|
||||
<activity android:name=".AngleUnitTestActivity"
|
||||
android:label="NativeTest"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:process=":test_process">
|
||||
{% if is_component_build == 'true' %}
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="{{ native_library_name }}.cr" />
|
||||
{% else %}
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="{{ native_library_name }}" />
|
||||
{% endif %}
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<instrumentation android:name="org.chromium.build.gtest_apk.NativeTestInstrumentationTestRunner"
|
||||
android:targetPackage="com.android.angle.test"
|
||||
android:label="Instrumentation entry point for com.android.angle.test"
|
||||
chromium-junit3="true"/>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,165 @@
|
||||
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// AngleNativeTest:
|
||||
// Helper to run Angle tests inside NativeActivity.
|
||||
|
||||
package com.android.angle.test;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.system.Os;
|
||||
import android.util.Log;
|
||||
|
||||
import org.chromium.build.gtest_apk.NativeTestIntent;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class AngleNativeTest
|
||||
{
|
||||
private static final String TAG = "NativeTest";
|
||||
|
||||
private String mCommandLineFilePath;
|
||||
private StringBuilder mCommandLineFlags = new StringBuilder();
|
||||
private TestStatusReporter mReporter;
|
||||
private String mStdoutFilePath;
|
||||
|
||||
private static class ReportingUncaughtExceptionHandler
|
||||
implements Thread.UncaughtExceptionHandler
|
||||
{
|
||||
|
||||
private TestStatusReporter mReporter;
|
||||
private Thread.UncaughtExceptionHandler mWrappedHandler;
|
||||
|
||||
public ReportingUncaughtExceptionHandler(
|
||||
TestStatusReporter reporter, Thread.UncaughtExceptionHandler wrappedHandler)
|
||||
{
|
||||
mReporter = reporter;
|
||||
mWrappedHandler = wrappedHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable ex)
|
||||
{
|
||||
mReporter.uncaughtException(Process.myPid(), ex);
|
||||
if (mWrappedHandler != null) mWrappedHandler.uncaughtException(thread, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void postCreate(Activity activity)
|
||||
{
|
||||
parseArgumentsFromIntent(activity, activity.getIntent());
|
||||
mReporter = new TestStatusReporter(activity);
|
||||
mReporter.testRunStarted(Process.myPid());
|
||||
Thread.setDefaultUncaughtExceptionHandler(new ReportingUncaughtExceptionHandler(
|
||||
mReporter, Thread.getDefaultUncaughtExceptionHandler()));
|
||||
}
|
||||
|
||||
private void parseArgumentsFromIntent(Activity activity, Intent intent)
|
||||
{
|
||||
Log.i(TAG, "Extras:");
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras != null)
|
||||
{
|
||||
for (String s : extras.keySet())
|
||||
{
|
||||
Log.i(TAG, " " + s);
|
||||
}
|
||||
}
|
||||
|
||||
mCommandLineFilePath = intent.getStringExtra(NativeTestIntent.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: " + mCommandLineFilePath);
|
||||
}
|
||||
|
||||
String commandLineFlags = intent.getStringExtra(NativeTestIntent.EXTRA_COMMAND_LINE_FLAGS);
|
||||
if (commandLineFlags != null) mCommandLineFlags.append(commandLineFlags);
|
||||
|
||||
String gtestFilter = intent.getStringExtra(NativeTestIntent.EXTRA_GTEST_FILTER);
|
||||
if (gtestFilter != null)
|
||||
{
|
||||
appendCommandLineFlags("--gtest_filter=" + gtestFilter);
|
||||
}
|
||||
|
||||
mStdoutFilePath = intent.getStringExtra(NativeTestIntent.EXTRA_STDOUT_FILE);
|
||||
}
|
||||
|
||||
private void appendCommandLineFlags(String flags)
|
||||
{
|
||||
mCommandLineFlags.append(" ").append(flags);
|
||||
}
|
||||
|
||||
public void postStart(final Activity activity)
|
||||
{
|
||||
final Runnable runTestsTask = new Runnable() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
runTests(activity);
|
||||
}
|
||||
};
|
||||
|
||||
// Post a task that posts a task that creates a new thread and runs tests on it.
|
||||
// This is needed because NativeActivity processes Looper messages in native code code,
|
||||
// which makes invoking the test runner Handler problematic.
|
||||
|
||||
// On L and M, the system posts a task to the main thread that prints to stdout
|
||||
// from android::Layout (https://goo.gl/vZA38p). Chaining the subthread creation
|
||||
// through multiple tasks executed on the main thread ensures that this task
|
||||
// runs before we start running tests s.t. its output doesn't interfere with
|
||||
// the test output. See crbug.com/678146 for additional context.
|
||||
|
||||
final Handler handler = new Handler();
|
||||
final Runnable startTestThreadTask = new Runnable() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
new Thread(runTestsTask).start();
|
||||
}
|
||||
};
|
||||
final Runnable postTestStarterTask = new Runnable() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
handler.post(startTestThreadTask);
|
||||
}
|
||||
};
|
||||
handler.post(postTestStarterTask);
|
||||
}
|
||||
|
||||
private void runTests(Activity activity)
|
||||
{
|
||||
nativeRunTests(mCommandLineFlags.toString(), mCommandLineFilePath, mStdoutFilePath);
|
||||
activity.finish();
|
||||
mReporter.testRunFinished(Process.myPid());
|
||||
}
|
||||
|
||||
// Signal a failure of the native test loader to python scripts
|
||||
// which run tests. For example, we look for
|
||||
// RUNNER_FAILED build/android/test_package.py.
|
||||
private void nativeTestFailed()
|
||||
{
|
||||
Log.e(TAG, "[ RUNNER_FAILED ] could not load native library");
|
||||
}
|
||||
|
||||
private native void nativeRunTests(
|
||||
String commandLineFlags, String commandLineFilePath, String stdoutFilePath);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// AngleUnitTestActivity:
|
||||
// A {@link android.app.NativeActivity} for running angle gtests.
|
||||
|
||||
package com.android.angle.test;
|
||||
|
||||
import android.app.NativeActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import org.chromium.build.NativeLibraries;
|
||||
|
||||
public class AngleUnitTestActivity extends NativeActivity
|
||||
{
|
||||
private static final String TAG = "NativeTest";
|
||||
|
||||
private AngleNativeTest mTest = new AngleNativeTest();
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
// For NativeActivity based tests,
|
||||
// dependency libraries must be loaded before NativeActivity::OnCreate,
|
||||
// otherwise loading android.app.lib_name will fail
|
||||
for (String library : NativeLibraries.LIBRARIES)
|
||||
{
|
||||
Log.i(TAG, "loading: " + library);
|
||||
System.loadLibrary(library);
|
||||
Log.i(TAG, "loaded: " + library);
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
mTest.postCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
mTest.postStart(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// TestStatusReporter:
|
||||
// Broadcasts test status to any listening {@link org.chromium.test.reporter.TestStatusReceiver}.
|
||||
|
||||
package com.android.angle.test;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import org.chromium.build.gtest_apk.TestStatusIntent;
|
||||
|
||||
public class TestStatusReporter
|
||||
{
|
||||
private final Context mContext;
|
||||
|
||||
public TestStatusReporter(Context c)
|
||||
{
|
||||
mContext = c;
|
||||
}
|
||||
|
||||
public void testRunStarted(int pid)
|
||||
{
|
||||
sendTestRunBroadcast(TestStatusIntent.ACTION_TEST_RUN_STARTED, pid);
|
||||
}
|
||||
|
||||
public void testRunFinished(int pid)
|
||||
{
|
||||
sendTestRunBroadcast(TestStatusIntent.ACTION_TEST_RUN_FINISHED, pid);
|
||||
}
|
||||
|
||||
private void sendTestRunBroadcast(String action, int pid)
|
||||
{
|
||||
Intent i = new Intent(action);
|
||||
i.setType(TestStatusIntent.DATA_TYPE_RESULT);
|
||||
i.putExtra(TestStatusIntent.EXTRA_PID, pid);
|
||||
mContext.sendBroadcast(i);
|
||||
}
|
||||
|
||||
public void uncaughtException(int pid, Throwable ex)
|
||||
{
|
||||
Intent i = new Intent(TestStatusIntent.ACTION_UNCAUGHT_EXCEPTION);
|
||||
i.setType(TestStatusIntent.DATA_TYPE_RESULT);
|
||||
i.putExtra(TestStatusIntent.EXTRA_PID, pid);
|
||||
i.putExtra(TestStatusIntent.EXTRA_STACK_TRACE, Log.getStackTraceString(ex));
|
||||
mContext.sendBroadcast(i);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user