Create a custom test launcher for android
Set use_default_launcher=false in rtc_test on android Bug: webrtc:42223878 Change-Id: If05da40b420d5da8f9e0f39560eb07380ebada14 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/368921 Owners-Override: Jeremy Leconte <jleconte@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Jeremy Leconte <jleconte@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Jeremy Leconte <jleconte@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43505}
This commit is contained in:
parent
002d00486b
commit
711e1a8beb
14
BUILD.gn
14
BUILD.gn
@ -695,7 +695,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
deps += [
|
||||
"sdk/android:native_unittests",
|
||||
"sdk/android:native_unittests_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
shard_timeout = 900
|
||||
}
|
||||
@ -744,11 +743,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
data = video_engine_tests_resources
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
deps += [ "//build/android/gtest_apk:native_test_instrumentation_test_runner_java" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
if (is_ios) {
|
||||
@ -793,11 +788,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
data = webrtc_perf_tests_resources
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
deps += [ "//build/android/gtest_apk:native_test_instrumentation_test_runner_java" ]
|
||||
shard_timeout = 4500
|
||||
}
|
||||
if (is_ios) {
|
||||
@ -809,7 +800,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
testonly = true
|
||||
deps = [ "rtc_base:rtc_base_nonparallel_tests" ]
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,8 +388,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +219,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
|
||||
data = common_video_resources
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
|
||||
|
||||
@ -1074,7 +1074,6 @@ if (rtc_include_tests) {
|
||||
data = rtc_media_unittests_resources
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
|
||||
|
||||
@ -83,8 +83,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
# rtc_test targets. Therefore we include this target here, instead of
|
||||
# in video_coding_modules_tests, where it is actually used.
|
||||
"../sdk/android:libjingle_peerconnection_java",
|
||||
"//sdk/android:native_test_jni_onload",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
shard_timeout = 900
|
||||
}
|
||||
@ -238,10 +236,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"../sdk/android:libjingle_peerconnection_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
deps += [ "../sdk/android:libjingle_peerconnection_java" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
if (is_ios) {
|
||||
|
||||
@ -1003,11 +1003,7 @@ if (rtc_include_tests) {
|
||||
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
deps += [ "//build/android/gtest_apk:native_test_instrumentation_test_runner_java" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
if (is_ios) {
|
||||
@ -1099,11 +1095,7 @@ if (rtc_include_tests) {
|
||||
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
deps += [ "//build/android/gtest_apk:native_test_instrumentation_test_runner_java" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
|
||||
|
||||
@ -493,7 +493,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
"../../sdk/android:internal_jni",
|
||||
"../../sdk/android:libjingle_peerconnection_java",
|
||||
"../../sdk/android:native_api_jni",
|
||||
"../../sdk/android:native_test_jni_onload",
|
||||
"../utility",
|
||||
]
|
||||
}
|
||||
|
||||
@ -1000,8 +1000,6 @@ if (rtc_include_tests) {
|
||||
deps += [
|
||||
":android_codec_factory_helper",
|
||||
"../../sdk/android:hwcodecs_java",
|
||||
"//sdk/android:native_test_jni_onload",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
shard_timeout = 900
|
||||
}
|
||||
|
||||
@ -11,9 +11,6 @@ include_rules = [
|
||||
]
|
||||
|
||||
specific_include_rules = {
|
||||
"android_codec_factory_helper\.cc": [
|
||||
"+base/android",
|
||||
],
|
||||
"multiplex_encoder_adapter\.cc": [
|
||||
"+media/base",
|
||||
],
|
||||
|
||||
16
pc/BUILD.gn
16
pc/BUILD.gn
@ -2098,11 +2098,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
deps += [ "//build/android/gtest_apk:native_test_instrumentation_test_runner_java" ]
|
||||
}
|
||||
}
|
||||
|
||||
@ -2448,8 +2444,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
|
||||
# We need to depend on this one directly, or classloads will fail for
|
||||
# the voice engine BuildInfo, for instance.
|
||||
"//sdk/android:libjingle_peerconnection_java",
|
||||
"//sdk/android:native_test_jni_onload",
|
||||
"../sdk/android:libjingle_peerconnection_java",
|
||||
]
|
||||
shard_timeout = 900
|
||||
}
|
||||
@ -2519,12 +2514,11 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
"test/android_test_initializer.h",
|
||||
]
|
||||
deps = [
|
||||
"../modules/utility:utility",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:ssl_adapter",
|
||||
"../sdk/android:internal_jni",
|
||||
"../sdk/android:libjingle_peerconnection_jni",
|
||||
"//modules/utility:utility",
|
||||
"//rtc_base:checks",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -2818,7 +2812,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
sources = [ "test/svc_e2e_tests.cc" ]
|
||||
data = svc_tests_resources
|
||||
deps = [
|
||||
"..//test/network:simulated_network",
|
||||
"../api:create_network_emulation_manager",
|
||||
"../api:create_peer_connection_quality_test_frame_generator",
|
||||
"../api:create_peerconnection_quality_test_fixture",
|
||||
@ -2843,6 +2836,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
"../test:fileutils",
|
||||
"../test:test_main",
|
||||
"../test:test_support",
|
||||
"../test/network:simulated_network",
|
||||
"../test/pc/e2e:network_quality_metrics_reporter",
|
||||
"../test/pc/e2e/analyzer/video:default_video_quality_analyzer",
|
||||
]
|
||||
|
||||
3
pc/DEPS
3
pc/DEPS
@ -18,9 +18,6 @@ include_rules = [
|
||||
]
|
||||
|
||||
specific_include_rules = {
|
||||
"androidtestinitializer\.cc": [
|
||||
"+base/android", # Allowed only for Android tests.
|
||||
],
|
||||
"srtpfilter_unittest\.cc": [
|
||||
"+crypto",
|
||||
],
|
||||
|
||||
@ -614,7 +614,6 @@ if (rtc_include_tests) {
|
||||
|
||||
data = tools_unittests_resources
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
if (is_ios) {
|
||||
|
||||
@ -91,7 +91,7 @@ if (is_android) {
|
||||
":surfaceviewrenderer_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -140,6 +140,7 @@ if (is_android) {
|
||||
":native_api_jni",
|
||||
":video_egl_jni",
|
||||
"../../pc:libjingle_peerconnection",
|
||||
"../../rtc_base:logging",
|
||||
"../../rtc_base:ssl_adapter",
|
||||
"//third_party/jni_zero",
|
||||
]
|
||||
@ -169,11 +170,13 @@ if (is_android) {
|
||||
"src/java/org/webrtc/WebRtcClassLoader.java",
|
||||
]
|
||||
|
||||
srcjar_deps = [ "//sdk/android:generated_native_api_jni" ]
|
||||
|
||||
deps = [
|
||||
":generated_base_jni_java",
|
||||
":generated_native_api_jni_java",
|
||||
":generated_rtcerror_jni_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
@ -188,7 +191,7 @@ if (is_android) {
|
||||
|
||||
deps = [
|
||||
":base_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -210,7 +213,7 @@ if (is_android) {
|
||||
deps = [
|
||||
":base_java",
|
||||
":generated_video_jni_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
srcjar_deps = [ "//api/video:video_frame_enums" ]
|
||||
@ -258,7 +261,7 @@ if (is_android) {
|
||||
":generated_video_egl_jni_java",
|
||||
":generated_video_jni_java",
|
||||
":video_api_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
@ -335,7 +338,7 @@ if (is_android) {
|
||||
":swcodecs_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
srcjar_deps = [
|
||||
@ -366,7 +369,7 @@ if (is_android) {
|
||||
":base_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
@ -398,7 +401,7 @@ if (is_android) {
|
||||
":base_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -426,7 +429,7 @@ if (is_android) {
|
||||
":base_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
@ -450,7 +453,7 @@ if (is_android) {
|
||||
":generated_audio_device_module_base_jni_java",
|
||||
":generated_java_audio_device_module_native_jni_java",
|
||||
":generated_java_audio_jni_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
@ -475,7 +478,7 @@ if (is_android) {
|
||||
deps = [
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
@ -491,7 +494,7 @@ if (is_android) {
|
||||
":base_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -506,7 +509,7 @@ if (is_android) {
|
||||
":generated_libvpx_vp8_jni_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -521,7 +524,7 @@ if (is_android) {
|
||||
":generated_libvpx_vp9_jni_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -533,7 +536,7 @@ if (is_android) {
|
||||
":generated_libaom_av1_encoder_jni_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -561,7 +564,7 @@ if (is_android) {
|
||||
":libvpx_vp9_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
@ -970,9 +973,9 @@ if (current_os == "linux" || is_android) {
|
||||
":generated_external_classes_jni",
|
||||
":generated_native_api_jni",
|
||||
":internal_jni",
|
||||
"../../api:array_view",
|
||||
"../../api:sequence_checker",
|
||||
"//api:array_view",
|
||||
"//rtc_base:checks",
|
||||
"../../rtc_base:checks",
|
||||
"//third_party/jni_zero",
|
||||
]
|
||||
}
|
||||
@ -987,7 +990,7 @@ if (current_os == "linux" || is_android) {
|
||||
deps = [
|
||||
":base_jni",
|
||||
":native_api_jni",
|
||||
"//rtc_base:checks",
|
||||
"../../rtc_base:checks",
|
||||
]
|
||||
}
|
||||
|
||||
@ -1035,8 +1038,8 @@ if (current_os == "linux" || is_android) {
|
||||
":base_jni",
|
||||
":native_api_jni",
|
||||
":video_jni",
|
||||
"//api/video_codecs:video_codecs_api",
|
||||
"//rtc_base:checks",
|
||||
"../../api/video_codecs:video_codecs_api",
|
||||
"../../rtc_base:checks",
|
||||
"//third_party/jni_zero",
|
||||
]
|
||||
}
|
||||
@ -1067,9 +1070,9 @@ if (current_os == "linux" || is_android) {
|
||||
deps = [
|
||||
":base_jni",
|
||||
":peerconnection_jni",
|
||||
"../../api:libjingle_peerconnection_api",
|
||||
"../../api/video_codecs:video_codecs_api",
|
||||
"../../rtc_base:threading",
|
||||
"//api:libjingle_peerconnection_api",
|
||||
"//api/video_codecs:video_codecs_api",
|
||||
]
|
||||
}
|
||||
|
||||
@ -1105,12 +1108,12 @@ if (current_os == "linux" || is_android) {
|
||||
":native_api_jni",
|
||||
":video_jni",
|
||||
":videoframe_jni",
|
||||
"../../api:libjingle_peerconnection_api",
|
||||
"../../api:media_stream_interface",
|
||||
"../../api/video:video_frame",
|
||||
"../../api/video:video_rtp_headers",
|
||||
"../../rtc_base:refcount",
|
||||
"../../rtc_base:threading",
|
||||
"//api:libjingle_peerconnection_api",
|
||||
"//api:media_stream_interface",
|
||||
"//api/video:video_frame",
|
||||
"//api/video:video_rtp_headers",
|
||||
"//third_party/jni_zero",
|
||||
]
|
||||
}
|
||||
@ -1125,7 +1128,7 @@ if (current_os == "linux" || is_android) {
|
||||
deps = [
|
||||
":base_java",
|
||||
":generated_logging_jni_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
]
|
||||
}
|
||||
|
||||
@ -1571,7 +1574,7 @@ if (is_android) {
|
||||
":swcodecs_java",
|
||||
":video_api_java",
|
||||
":video_java",
|
||||
"//rtc_base:base_java",
|
||||
"../../rtc_base:base_java",
|
||||
"//third_party/android_deps:guava_android_java",
|
||||
"//third_party/androidx:androidx_annotation_annotation_java",
|
||||
"//third_party/androidx:androidx_test_monitor_java",
|
||||
@ -1603,6 +1606,7 @@ if (is_android) {
|
||||
":libjingle_peerconnection_metrics_default_jni",
|
||||
":native_api_jni",
|
||||
"../../pc:libjingle_peerconnection",
|
||||
"../../rtc_base:logging",
|
||||
"../../rtc_base:ssl_adapter",
|
||||
]
|
||||
output_extension = "so"
|
||||
@ -1631,11 +1635,13 @@ if (is_android) {
|
||||
sources = [ "native_unittests/test_jni_onload.cc" ]
|
||||
|
||||
deps = [
|
||||
":base_java",
|
||||
":base_jni",
|
||||
":internal_jni",
|
||||
":native_api_base",
|
||||
":native_api_jni",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:logging",
|
||||
]
|
||||
}
|
||||
|
||||
@ -1668,7 +1674,6 @@ if (is_android) {
|
||||
":native_api_peerconnection",
|
||||
":native_api_stacktrace",
|
||||
":native_api_video",
|
||||
":native_test_jni_onload",
|
||||
":opensles_audio_device_module",
|
||||
":video_jni",
|
||||
"../../api:enable_media_with_defaults",
|
||||
|
||||
@ -13,11 +13,21 @@
|
||||
#define JNIEXPORT __attribute__((visibility("default")))
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/native_api/base/init.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "test/android/native_test_launcher.h" // nogncheck
|
||||
|
||||
// This is called by the VM when the shared library is first loaded.
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
RTC_LOG(LS_INFO) << "Entering JNI_OnLoad in test_jni_onload.cc";
|
||||
|
||||
jni_zero::InitVM(vm);
|
||||
// TODO(webrtc:42223878): Set exception handler?
|
||||
// jni_zero::SetExceptionHandler(CheckException);
|
||||
// JNIEnv* env = jni_zero::AttachCurrentThread();
|
||||
// TODO(webrtc:42223878): Classloader, OOM error handler?
|
||||
webrtc::InitAndroid(vm);
|
||||
webrtc::test::android::InstallHandlers();
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
include_rules = [
|
||||
"+base/android/jni_android.h",
|
||||
"+modules/audio_device",
|
||||
]
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#undef JNIEXPORT
|
||||
#define JNIEXPORT __attribute__((visibility("default")))
|
||||
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/ssl_adapter.h"
|
||||
#include "sdk/android/native_api/jni/class_loader.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
@ -20,6 +21,7 @@ namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
extern "C" jint JNIEXPORT JNICALL JNI_OnLoad(JavaVM* jvm, void* reserved) {
|
||||
RTC_LOG(LS_INFO) << "Entering JNI_OnLoad in jni_onload.cc";
|
||||
jint ret = InitGlobalJniVariables(jvm);
|
||||
RTC_DCHECK_GE(ret, 0);
|
||||
if (ret < 0)
|
||||
|
||||
@ -68,11 +68,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
deps += [ "//build/android/gtest_apk:native_test_instrumentation_test_runner_java" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,8 +154,6 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import("//build/config/ui.gni")
|
||||
import("../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/rules.gni")
|
||||
import("//third_party/jni_zero/jni_zero.gni")
|
||||
}
|
||||
|
||||
if (!build_with_chromium) {
|
||||
@ -798,7 +799,6 @@ if (rtc_include_tests) {
|
||||
|
||||
data = test_support_unittests_resources
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
|
||||
@ -1301,14 +1301,43 @@ if (!build_with_chromium && is_android) {
|
||||
rtc_android_library("native_test_java") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"android/org/webrtc/native_test/NativeTestWebrtc.java",
|
||||
"android/org/webrtc/native_test/RTCNativeTestApplication.java",
|
||||
"android/org/webrtc/native_test/RTCNativeUnitTest.java",
|
||||
"android/org/webrtc/native_test/RTCNativeUnitTestActivity.java",
|
||||
"android/org/webrtc/native_test/StrictModeContext.java",
|
||||
]
|
||||
srcjar_deps = [ ":native_test_jni" ]
|
||||
deps = [
|
||||
":native_test_support",
|
||||
"../rtc_base:base_java",
|
||||
"//build/android:build_java",
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/reporter:reporter_java",
|
||||
"//third_party/jni_zero:jni_zero_java",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("native_test_support") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"android/native_test_launcher.cc",
|
||||
"android/native_test_launcher.h",
|
||||
"android/native_test_util.cc",
|
||||
"android/native_test_util.h",
|
||||
]
|
||||
deps = [
|
||||
"../rtc_base:base_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
":native_test_jni",
|
||||
"//testing/gtest",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/jni_zero:jni_zero",
|
||||
]
|
||||
}
|
||||
|
||||
generate_jni("native_test_jni") {
|
||||
testonly = true
|
||||
sources = [ "android/org/webrtc/native_test/NativeTestWebrtc.java" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("call_config_utils") {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
include_rules = [
|
||||
"+third_party/libjpeg",
|
||||
"+third_party/libjpeg_turbo",
|
||||
"+third_party/jni_zero",
|
||||
"+absl/strings/str_split.h",
|
||||
"+call",
|
||||
"+common_audio",
|
||||
"+common_video",
|
||||
|
||||
@ -24,13 +24,18 @@ be found in the AUTHORS file in the root of the source tree.
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/> <!-- From Chromium -->
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> <!-- From Chromium -->
|
||||
<uses-permission android:name="android.permission.SET_TIME_ZONE"/> <!-- From Chromium -->
|
||||
|
||||
<application android:label="NativeTests"
|
||||
android:name="org.chromium.native_test.NativeTestApplication">
|
||||
android:name="org.webrtc.native_test.RTCNativeTestApplication">
|
||||
<uses-library android:name="android.test.runner"/>
|
||||
<activity android:name=".RTCNativeUnitTestActivity"
|
||||
android:label="NativeTest"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:memtagMode="sync"
|
||||
android:process=":test_process">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
123
test/android/native_test_launcher.cc
Normal file
123
test/android/native_test_launcher.cc
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The WebRTC 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 in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Based on Chromium's
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:testing/android/native_test/native_test_launcher.cc
|
||||
// and Angle's
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/tests/test_utils/runner/android/AngleNativeTest.cpp
|
||||
|
||||
// This class sets up the environment for running the native tests inside an
|
||||
// android application. It outputs (to a fifo) markers identifying the
|
||||
// START/PASSED/CRASH of the test suite, FAILURE/SUCCESS of individual tests,
|
||||
// etc.
|
||||
// These markers are read by the test runner script to generate test results.
|
||||
// It installs signal handlers to detect crashes.
|
||||
|
||||
#include "test/android/native_test_launcher.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "test/android/native_test_util.h"
|
||||
#include "test/native_test_jni/NativeTestWebrtc_jni.h"
|
||||
#include "third_party/jni_zero/jni_zero.h"
|
||||
|
||||
// The main function of the program to be wrapped as a test apk.
|
||||
extern int main(int argc, char** argv);
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
|
||||
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];
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static void JNI_NativeTestWebrtc_RunTests(JNIEnv* env,
|
||||
std::string& command_line_flags,
|
||||
std::string& command_line_file_path,
|
||||
std::string& stdout_file_path,
|
||||
std::string& test_data_dir) {
|
||||
AndroidLog(
|
||||
ANDROID_LOG_INFO,
|
||||
"Entering JNI_NativeTestWebrtc_RunTests with command_line_flags=%s, "
|
||||
"command_line_file_path=%s, stdout_file_path=%s, test_data_dir=%s\n",
|
||||
command_line_flags.c_str(), command_line_file_path.c_str(),
|
||||
stdout_file_path.c_str(), test_data_dir.c_str());
|
||||
|
||||
// Required for DEATH_TESTS.
|
||||
pthread_atfork(nullptr, nullptr, jni_zero::DisableJvmForTesting);
|
||||
|
||||
std::vector<std::string> args;
|
||||
|
||||
if (command_line_file_path.empty())
|
||||
args.push_back("_");
|
||||
else
|
||||
ParseArgsFromCommandLineFile(command_line_file_path.c_str(), &args);
|
||||
|
||||
ParseArgsFromString(command_line_flags, &args);
|
||||
|
||||
std::vector<char*> argv;
|
||||
int argc = ArgsToArgv(args, &argv);
|
||||
|
||||
// A few options, such "--gtest_list_tests", will just use printf directly
|
||||
// Always redirect stdout to a known file.
|
||||
if (freopen(stdout_file_path.c_str(), "a+", stdout) == NULL) {
|
||||
AndroidLog(ANDROID_LOG_ERROR, "Failed to redirect stream to file: %s: %s\n",
|
||||
stdout_file_path.c_str(), strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// TODO(jbudorick): Remove this after resolving crbug.com/726880
|
||||
AndroidLog(ANDROID_LOG_INFO, "Redirecting stdout to file: %s\n",
|
||||
stdout_file_path.c_str());
|
||||
dup2(STDOUT_FILENO, STDERR_FILENO);
|
||||
|
||||
// TODO(webrtc:42223878): Wait for debugger.
|
||||
|
||||
ScopedMainEntryLogger scoped_main_entry_logger;
|
||||
main(argc, &argv[0]);
|
||||
}
|
||||
|
||||
// TODO(nileshagrawal): now that we're using FIFO, test scripts can detect EOF.
|
||||
// Remove the signal handlers.
|
||||
void InstallHandlers() {
|
||||
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]]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
26
test/android/native_test_launcher.h
Normal file
26
test/android/native_test_launcher.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The WebRTC 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 in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef TEST_ANDROID_NATIVE_TEST_LAUNCHER_H_
|
||||
#define TEST_ANDROID_NATIVE_TEST_LAUNCHER_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace android {
|
||||
|
||||
void InstallHandlers();
|
||||
|
||||
} // namespace android
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // TEST_ANDROID_NATIVE_TEST_LAUNCHER_H_
|
||||
148
test/android/native_test_util.cc
Normal file
148
test/android/native_test_util.cc
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The WebRTC 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 in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Based on Chromium's
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:testing/android/native_test/native_test_util.cc
|
||||
// and Angle's
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/tests/test_utils/runner/android/AngleNativeTest.cpp
|
||||
|
||||
#include "test/android/native_test_util.h"
|
||||
|
||||
#include <android/log.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/str_split.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kLogTag[] = "webrtc";
|
||||
|
||||
std::optional<std::string> ReadFileToString(const char* path) {
|
||||
FILE* file = fopen(path, "rb");
|
||||
if (!file) {
|
||||
AndroidLog(ANDROID_LOG_ERROR, "Failed to open %s\n", path);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (fseek(file, 0, SEEK_END) != 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto size = ftell(file);
|
||||
// Check that `size` fits in a 32-bit int, to avoid any issues with overflow
|
||||
// in the subsequent casts. (For example, consider the case where long is >32
|
||||
// bits while size_t is 32 bits.) We're not expecting the command line to be
|
||||
// larger than 1 GB, anyway.
|
||||
if (size < 0 || size > 1'000'000'000) {
|
||||
AndroidLog(ANDROID_LOG_ERROR,
|
||||
"Expected size of %s between 0 and 1 GB, got %ld bytes\n", path,
|
||||
size);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string contents;
|
||||
contents.resize(size);
|
||||
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
if (fread(contents.data(), 1, size, file) != static_cast<size_t>(size)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (ferror(file)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Writes printf() style string to Android's logger where |priority| is one of
|
||||
// the levels defined in <android/log.h>.
|
||||
void AndroidLog(int priority, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
__android_log_vprint(priority, kLogTag, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ParseArgsFromString(const std::string& command_line,
|
||||
std::vector<std::string>* args) {
|
||||
std::vector<absl::string_view> v =
|
||||
absl::StrSplit(command_line, absl::ByAsciiWhitespace());
|
||||
for (absl::string_view arg : v) {
|
||||
args->push_back(std::string(arg));
|
||||
}
|
||||
|
||||
// TODO(webrtc:42223878): Implement tokenization that handle quotes and
|
||||
// escaped quotes (along the lines of the previous chromium code):
|
||||
//
|
||||
// base::StringTokenizer tokenizer(command_line, base::kWhitespaceASCII);
|
||||
// tokenizer.set_quote_chars("\"");
|
||||
// while (tokenizer.GetNext()) {
|
||||
// std::string token;
|
||||
// base::RemoveChars(tokenizer.token(), "\"", &token);
|
||||
// args->push_back(token);
|
||||
// }
|
||||
}
|
||||
|
||||
void ParseArgsFromCommandLineFile(const char* path,
|
||||
std::vector<std::string>* args) {
|
||||
std::optional<std::string> command_line_string = ReadFileToString(path);
|
||||
if (command_line_string.has_value()) {
|
||||
ParseArgsFromString(*command_line_string, args);
|
||||
}
|
||||
}
|
||||
|
||||
int ArgsToArgv(const std::vector<std::string>& args, std::vector<char*>* argv) {
|
||||
// We need to pass in a non-const char**.
|
||||
int argc = args.size();
|
||||
|
||||
argv->resize(argc + 1);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
(*argv)[i] = const_cast<char*>(args[i].c_str());
|
||||
}
|
||||
(*argv)[argc] = NULL; // argv must be NULL terminated.
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
63
test/android/native_test_util.h
Normal file
63
test/android/native_test_util.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The WebRTC 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 in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef TEST_ANDROID_NATIVE_TEST_UTIL_H_
|
||||
#define TEST_ANDROID_NATIVE_TEST_UTIL_H_
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "third_party/jni_zero/jni_zero.h"
|
||||
|
||||
// Helper methods for setting up environment for running gtest tests
|
||||
// inside an APK.
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace android {
|
||||
|
||||
void AndroidLog(int priority, const char* format, ...);
|
||||
|
||||
std::string ASCIIJavaStringToUTF8(JNIEnv* env, jstring str);
|
||||
|
||||
void ParseArgsFromString(const std::string& command_line,
|
||||
std::vector<std::string>* args);
|
||||
void ParseArgsFromCommandLineFile(const char* path,
|
||||
std::vector<std::string>* args);
|
||||
int ArgsToArgv(const std::vector<std::string>& args, std::vector<char*>* argv);
|
||||
|
||||
class ScopedMainEntryLogger {
|
||||
public:
|
||||
ScopedMainEntryLogger() {
|
||||
AndroidLog(ANDROID_LOG_INFO, ">>ScopedMainEntryLogger\n");
|
||||
}
|
||||
|
||||
~ScopedMainEntryLogger() {
|
||||
AndroidLog(ANDROID_LOG_INFO, "<<ScopedMainEntryLogger\n");
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
namespace jni_zero {
|
||||
template <>
|
||||
inline std::string FromJniType<std::string>(JNIEnv* env,
|
||||
const JavaRef<jobject>& input) {
|
||||
return webrtc::test::android::ASCIIJavaStringToUTF8(
|
||||
env, static_cast<jstring>(input.obj()));
|
||||
}
|
||||
} // namespace jni_zero
|
||||
|
||||
#endif // TEST_ANDROID_NATIVE_TEST_UTIL_H_
|
||||
210
test/android/org/webrtc/native_test/NativeTestWebrtc.java
Normal file
210
test/android/org/webrtc/native_test/NativeTestWebrtc.java
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2024 The WebRTC 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 in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Based on Chromium's https://source.chromium.org/chromium/chromium/src/+/main:testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java
|
||||
// and Angle's https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java
|
||||
|
||||
package org.webrtc.native_test;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.util.Log;
|
||||
|
||||
import org.jni_zero.JNINamespace;
|
||||
import org.jni_zero.JniType;
|
||||
import org.jni_zero.NativeMethods;
|
||||
|
||||
import org.webrtc.native_test.StrictModeContext;
|
||||
import org.chromium.build.gtest_apk.NativeTestIntent;
|
||||
import org.chromium.test.reporter.TestStatusReporter;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/** Helper to run tests inside Activity or NativeActivity. */
|
||||
@JNINamespace("webrtc::test::android")
|
||||
public class NativeTestWebrtc {
|
||||
private static final String TAG = "NativeTestWebrtc";
|
||||
|
||||
private String mCommandLineFilePath;
|
||||
private StringBuilder mCommandLineFlags = new StringBuilder();
|
||||
private TestStatusReporter mReporter;
|
||||
private boolean mRunInSubThread;
|
||||
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 preCreate(Activity activity) {
|
||||
String coverageDeviceFile =
|
||||
activity.getIntent().getStringExtra(NativeTestIntent.EXTRA_COVERAGE_DEVICE_FILE);
|
||||
if (coverageDeviceFile != null) {
|
||||
try {
|
||||
Os.setenv("LLVM_PROFILE_FILE", coverageDeviceFile, true);
|
||||
} catch (ErrnoException e) {
|
||||
Log.w(TAG, "failed to set LLVM_PROFILE_FILE" + e.toString());
|
||||
}
|
||||
}
|
||||
// Set TMPDIR to make perfetto_unittests not to use /data/local/tmp as a tmp directory.
|
||||
try {
|
||||
Os.setenv("TMPDIR", activity.getApplicationContext().getCacheDir().getPath(), false);
|
||||
} catch (ErrnoException e) {
|
||||
Log.w(TAG, "failed to set TMPDIR" + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
mRunInSubThread = intent.hasExtra(NativeTestIntent.EXTRA_RUN_IN_SUB_THREAD);
|
||||
|
||||
String gtestFilter = intent.getStringExtra(NativeTestIntent.EXTRA_GTEST_FILTER);
|
||||
if (gtestFilter != null) {
|
||||
appendCommandLineFlags("--gtest_filter=" + gtestFilter);
|
||||
}
|
||||
|
||||
mStdoutFilePath = intent.getStringExtra(NativeTestIntent.EXTRA_STDOUT_FILE);
|
||||
}
|
||||
|
||||
public void appendCommandLineFlags(String flags) {
|
||||
mCommandLineFlags.append(" ").append(flags);
|
||||
}
|
||||
|
||||
public void postStart(final Activity activity, boolean forceRunInSubThread) {
|
||||
final Runnable runTestsTask =
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runTests(activity);
|
||||
}
|
||||
};
|
||||
|
||||
if (mRunInSubThread || forceRunInSubThread) {
|
||||
// Post a task that posts a task that creates a new thread and runs tests on it.
|
||||
|
||||
// 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);
|
||||
} else {
|
||||
// Post a task to run the tests. This allows us to not block
|
||||
// onCreate and still run tests on the main thread.
|
||||
new Handler().post(runTestsTask);
|
||||
}
|
||||
}
|
||||
|
||||
private void runTests(Activity activity) {
|
||||
Natives jni = NativeTestWebrtcJni.get();
|
||||
String isolated_test_root = NativeTestWebrtc.getIsolatedTestRoot();
|
||||
Log.i(TAG, "Calling into native code");
|
||||
jni.runTests(
|
||||
mCommandLineFlags.toString(),
|
||||
mCommandLineFilePath,
|
||||
mStdoutFilePath,
|
||||
isolated_test_root);
|
||||
Log.i(TAG, "Call into native code returned");
|
||||
activity.finish();
|
||||
mReporter.testRunFinished(Process.myPid());
|
||||
}
|
||||
|
||||
|
||||
// @CalledByNative
|
||||
public static String getIsolatedTestRoot() {
|
||||
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
|
||||
return Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||
+ "/chromium_tests_root";
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
@NativeMethods
|
||||
interface Natives {
|
||||
void runTests(
|
||||
@JniType("std::string") String commandLineFlags,
|
||||
@JniType("std::string") String commandLineFilePath,
|
||||
@JniType("std::string") String stdoutFilePath,
|
||||
@JniType("std::string") String testDataDir);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2024 The WebRTC 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 in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
package org.webrtc.native_test;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
/** Application class to be used by native_test apks. */
|
||||
public class RTCNativeTestApplication extends Application {
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
assert getBaseContext() != null;
|
||||
|
||||
// This is required for Mockito to initialize mocks without running under Instrumentation.
|
||||
System.setProperty("org.mockito.android.target", getCacheDir().getPath());
|
||||
}
|
||||
}
|
||||
@ -11,16 +11,39 @@
|
||||
package org.webrtc.native_test;
|
||||
|
||||
import android.app.Activity;
|
||||
import org.chromium.native_test.NativeUnitTest;
|
||||
import android.util.Log;
|
||||
import org.chromium.build.NativeLibraries;
|
||||
import org.webrtc.native_test.NativeTestWebrtc;
|
||||
import org.webrtc.ContextUtils;
|
||||
|
||||
/**
|
||||
* Native unit test that calls ContextUtils.initialize for WebRTC.
|
||||
*/
|
||||
public class RTCNativeUnitTest extends NativeUnitTest {
|
||||
@Override
|
||||
public void preCreate(Activity activity) {
|
||||
super.preCreate(activity);
|
||||
ContextUtils.initialize(activity.getApplicationContext());
|
||||
}
|
||||
}
|
||||
public class RTCNativeUnitTest extends NativeTestWebrtc {
|
||||
|
||||
private static final String TAG = "RTCNativeUnitTest";
|
||||
|
||||
private static final String LIBRARY_UNDER_TEST_NAME =
|
||||
"org.chromium.native_test.NativeTestInstrumentationTestRunner.LibraryUnderTest";
|
||||
|
||||
@Override
|
||||
public void preCreate(Activity activity) {
|
||||
super.preCreate(activity);
|
||||
|
||||
// For NativeActivity based tests, dependency libraries must be loaded before
|
||||
// NativeActivity::OnCreate, otherwise loading android.app.lib_name will fail
|
||||
String libraryToLoad = activity.getIntent().getStringExtra(LIBRARY_UNDER_TEST_NAME);
|
||||
loadLibraries(
|
||||
libraryToLoad != null ? new String[] {libraryToLoad} : NativeLibraries.LIBRARIES);
|
||||
|
||||
ContextUtils.initialize(activity.getApplicationContext());
|
||||
}
|
||||
|
||||
private void loadLibraries(String[] librariesToLoad) {
|
||||
for (String library : librariesToLoad) {
|
||||
Log.i(TAG, "loading: " + library);
|
||||
System.loadLibrary(library);
|
||||
Log.i(TAG, "loaded: " + library);
|
||||
}
|
||||
}
|
||||
}
|
||||
122
test/android/org/webrtc/native_test/StrictModeContext.java
Normal file
122
test/android/org/webrtc/native_test/StrictModeContext.java
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2024 The WebRTC 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 in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Based on Chromium's https://source.chromium.org/chromium/chromium/src/+/main:base/android/java/src/org/chromium/base/StrictModeContext.java
|
||||
|
||||
package org.webrtc.native_test;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.StrictMode;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
* Enables try-with-resources compatible StrictMode violation allowlisting.
|
||||
*
|
||||
* <p>Prefer "ignored" as the variable name to appease Android Studio's "Unused symbol" inspection.
|
||||
*
|
||||
* <p>Example:
|
||||
*
|
||||
* <pre>
|
||||
* try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
|
||||
* return Example.doThingThatRequiresDiskWrites();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public class StrictModeContext implements Closeable {
|
||||
private static class Impl extends StrictModeContext {
|
||||
private final StrictMode.ThreadPolicy mThreadPolicy;
|
||||
private final StrictMode.VmPolicy mVmPolicy;
|
||||
|
||||
private Impl(StrictMode.ThreadPolicy threadPolicy, StrictMode.VmPolicy vmPolicy) {
|
||||
mThreadPolicy = threadPolicy;
|
||||
mVmPolicy = vmPolicy;
|
||||
}
|
||||
|
||||
private Impl(StrictMode.ThreadPolicy threadPolicy) {
|
||||
this(threadPolicy, null);
|
||||
}
|
||||
|
||||
private Impl(StrictMode.VmPolicy vmPolicy) {
|
||||
this(null, vmPolicy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (mThreadPolicy != null) {
|
||||
StrictMode.setThreadPolicy(mThreadPolicy);
|
||||
}
|
||||
if (mVmPolicy != null) {
|
||||
StrictMode.setVmPolicy(mVmPolicy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for disabling all VM-level StrictMode checks with try-with-resources.
|
||||
* Includes everything listed here:
|
||||
* https://developer.android.com/reference/android/os/StrictMode.VmPolicy.Builder.html
|
||||
*/
|
||||
public static StrictModeContext allowAllVmPolicies() {
|
||||
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
|
||||
StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX);
|
||||
return new Impl(oldPolicy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for disabling all thread-level StrictMode checks with try-with-resources.
|
||||
* Includes everything listed here:
|
||||
* https://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder.html
|
||||
*/
|
||||
public static StrictModeContext allowAllThreadPolicies() {
|
||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);
|
||||
return new Impl(oldPolicy);
|
||||
}
|
||||
|
||||
/** Convenience method for disabling StrictMode for disk-writes with try-with-resources. */
|
||||
public static StrictModeContext allowDiskWrites() {
|
||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
|
||||
return new Impl(oldPolicy);
|
||||
}
|
||||
|
||||
/** Convenience method for disabling StrictMode for disk-reads with try-with-resources. */
|
||||
public static StrictModeContext allowDiskReads() {
|
||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
||||
return new Impl(oldPolicy);
|
||||
}
|
||||
|
||||
/** Convenience method for disabling StrictMode for slow calls with try-with-resources. */
|
||||
public static StrictModeContext allowSlowCalls() {
|
||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
StrictMode.setThreadPolicy(
|
||||
new StrictMode.ThreadPolicy.Builder(oldPolicy).permitCustomSlowCalls().build());
|
||||
return new Impl(oldPolicy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for disabling StrictMode for unbuffered input/output operations with
|
||||
* try-with-resources. For API level 25- this method will do nothing; because
|
||||
* StrictMode.ThreadPolicy.Builder#permitUnbufferedIo is added in API level 26.
|
||||
*/
|
||||
public static StrictModeContext allowUnbufferedIo() {
|
||||
StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
StrictMode.setThreadPolicy(
|
||||
new StrictMode.ThreadPolicy.Builder(oldPolicy)
|
||||
.permitUnbufferedIo()
|
||||
.build());
|
||||
}
|
||||
return new Impl(oldPolicy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
}
|
||||
@ -525,13 +525,17 @@ template("rtc_test") {
|
||||
public_configs += invoker.public_configs
|
||||
}
|
||||
if (!build_with_chromium && is_android) {
|
||||
use_default_launcher = false
|
||||
android_manifest = webrtc_root + "test/android/AndroidManifest.xml"
|
||||
use_raw_android_executable = false
|
||||
min_sdk_version = 21
|
||||
target_sdk_version = 23
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
webrtc_root + "sdk/android:native_test_jni_onload",
|
||||
webrtc_root + "sdk/android:base_java",
|
||||
webrtc_root + "test:native_test_java",
|
||||
webrtc_root + "test:native_test_support",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user