diff options
Diffstat (limited to 'libnativeloader/native_loader_test.cpp')
-rw-r--r-- | libnativeloader/native_loader_test.cpp | 110 |
1 files changed, 83 insertions, 27 deletions
diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp index 43c3c151c9..e754414f46 100644 --- a/libnativeloader/native_loader_test.cpp +++ b/libnativeloader/native_loader_test.cpp @@ -36,12 +36,13 @@ namespace android { namespace nativeloader { using ::testing::Eq; +using ::testing::NotNull; using ::testing::Return; using ::testing::StrEq; using ::testing::_; using internal::ConfigEntry; -using internal::ParseConfig; using internal::ParseApexLibrariesConfig; +using internal::ParseConfig; #if defined(__LP64__) #define LIB_DIR "lib64" @@ -49,19 +50,15 @@ using internal::ParseApexLibrariesConfig; #define LIB_DIR "lib" #endif -// gmock interface that represents interested platform APIs on libdl and libnativebridge +// gmock interface that represents interested platform APIs on libdl_android and libnativebridge class Platform { public: virtual ~Platform() {} - // libdl APIs - virtual void* dlopen(const char* filename, int flags) = 0; - virtual int dlclose(void* handle) = 0; - virtual char* dlerror(void) = 0; - - // These mock_* are the APIs semantically the same across libdl and libnativebridge. + // These mock_* are the APIs semantically the same across libdl_android and libnativebridge. // Instead of having two set of mock APIs for the two, define only one set with an additional - // argument 'bool bridged' to identify the context (i.e., called for libdl or libnativebridge). + // argument 'bool bridged' to identify the context (i.e., called for libdl_android or + // libnativebridge). typedef char* mock_namespace_handle; virtual bool mock_init_anonymous_namespace(bool bridged, const char* sonames, const char* search_paths) = 0; @@ -74,7 +71,7 @@ class Platform { virtual void* mock_dlopen_ext(bool bridged, const char* filename, int flags, mock_namespace_handle ns) = 0; - // libnativebridge APIs for which libdl has no corresponding APIs + // libnativebridge APIs for which libdl_android has no corresponding APIs virtual bool NativeBridgeInitialized() = 0; virtual const char* NativeBridgeGetError() = 0; virtual bool NativeBridgeIsPathSupported(const char*) = 0; @@ -125,11 +122,6 @@ class MockPlatform : public Platform { })); } - // Mocking libdl APIs - MOCK_METHOD2(dlopen, void*(const char*, int)); - MOCK_METHOD1(dlclose, int(void*)); - MOCK_METHOD0(dlerror, char*()); - // Mocking the common APIs MOCK_METHOD3(mock_init_anonymous_namespace, bool(bool, const char*, const char*)); MOCK_METHOD7(mock_create_namespace, @@ -155,19 +147,11 @@ class MockPlatform : public Platform { static std::unique_ptr<MockPlatform> mock; -// Provide C wrappers for the mock object. +// Provide C wrappers for the mock object. These symbols must be exported by ld +// to be able to override the real symbols in the shared libs. extern "C" { -void* dlopen(const char* file, int flag) { - return mock->dlopen(file, flag); -} -int dlclose(void* handle) { - return mock->dlclose(handle); -} - -char* dlerror(void) { - return mock->dlerror(); -} +// libdl_android APIs bool android_init_anonymous_namespace(const char* sonames, const char* search_path) { return mock->mock_init_anonymous_namespace(false, sonames, search_path); @@ -197,6 +181,7 @@ void* android_dlopen_ext(const char* filename, int flags, const android_dlextinf } // libnativebridge APIs + bool NativeBridgeIsSupported(const char* libpath) { return mock->NativeBridgeIsSupported(libpath); } @@ -313,7 +298,8 @@ class NativeLoaderTest : public ::testing::TestWithParam<bool> { std::vector<std::string> default_public_libs = android::base::Split(preloadable_public_libraries(), ":"); for (auto l : default_public_libs) { - EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE)) + EXPECT_CALL(*mock, + mock_dlopen_ext(false, StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE, NotNull())) .WillOnce(Return(any_nonnull)); } } @@ -336,6 +322,76 @@ TEST_P(NativeLoaderTest, InitializeLoadsDefaultPublicLibraries) { RunTest(); } +TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderInApex) { + const char* test_lib_path = "libfoo.so"; + void* fake_handle = &fake_handle; // Arbitrary non-null value + EXPECT_CALL(*mock, + mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("com_android_art"))) + .WillOnce(Return(fake_handle)); + + bool needs_native_bridge = false; + char* errmsg = nullptr; + EXPECT_EQ(fake_handle, + OpenNativeLibrary(env.get(), + /*target_sdk_version=*/17, + test_lib_path, + /*class_loader=*/nullptr, + /*caller_location=*/"/apex/com.android.art/javalib/myloadinglib.jar", + /*library_path=*/nullptr, + &needs_native_bridge, + &errmsg)); + // OpenNativeLibrary never uses nativebridge when there's no classloader. That + // should maybe change. + EXPECT_EQ(needs_native_bridge, false); + EXPECT_EQ(errmsg, nullptr); +} + +TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderInFramework) { + const char* test_lib_path = "libfoo.so"; + void* fake_handle = &fake_handle; // Arbitrary non-null value + EXPECT_CALL(*mock, mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("system"))) + .WillOnce(Return(fake_handle)); + + bool needs_native_bridge = false; + char* errmsg = nullptr; + EXPECT_EQ(fake_handle, + OpenNativeLibrary(env.get(), + /*target_sdk_version=*/17, + test_lib_path, + /*class_loader=*/nullptr, + /*caller_location=*/"/system/framework/framework.jar!classes1.dex", + /*library_path=*/nullptr, + &needs_native_bridge, + &errmsg)); + // OpenNativeLibrary never uses nativebridge when there's no classloader. That + // should maybe change. + EXPECT_EQ(needs_native_bridge, false); + EXPECT_EQ(errmsg, nullptr); +} + +TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderAndCallerLocation) { + const char* test_lib_path = "libfoo.so"; + void* fake_handle = &fake_handle; // Arbitrary non-null value + EXPECT_CALL(*mock, mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("system"))) + .WillOnce(Return(fake_handle)); + + bool needs_native_bridge = false; + char* errmsg = nullptr; + EXPECT_EQ(fake_handle, + OpenNativeLibrary(env.get(), + /*target_sdk_version=*/17, + test_lib_path, + /*class_loader=*/nullptr, + /*caller_location=*/nullptr, + /*library_path=*/nullptr, + &needs_native_bridge, + &errmsg)); + // OpenNativeLibrary never uses nativebridge when there's no classloader. That + // should maybe change. + EXPECT_EQ(needs_native_bridge, false); + EXPECT_EQ(errmsg, nullptr); +} + INSTANTIATE_TEST_SUITE_P(NativeLoaderTests, NativeLoaderTest, testing::Bool()); ///////////////////////////////////////////////////////////////// |