summaryrefslogtreecommitdiff
path: root/libnativeloader/native_loader_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libnativeloader/native_loader_test.cpp')
-rw-r--r--libnativeloader/native_loader_test.cpp110
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());
/////////////////////////////////////////////////////////////////