| /* | |
| * Copyright (C) 2021 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include <memory> | |
| #include <string> | |
| #include "gmock/gmock.h" | |
| #include "gtest/gtest.h" | |
| #include "jni.h" | |
| #include "native_loader_test.h" | |
| #include "nativehelper/scoped_utf_chars.h" | |
| #include "nativeloader/native_loader.h" | |
| namespace android { | |
| namespace nativeloader { | |
| using ::testing::Return; | |
| using ::testing::StrEq; | |
| // Test the exported API in libnativeloader and libnativeloader_lazy. The | |
| // testing we can do here outside a full VM is limited, but this is only to | |
| // complement other tests and ensure coverage of the APIs that aren't in the | |
| // common call paths. | |
| class NativeLoaderLazyTest : public ::testing::Test { | |
| protected: | |
| void SetUp() override { | |
| jni_mock = std::make_unique<testing::NiceMock<MockJni>>(); | |
| env = std::make_unique<JNIEnv>(); | |
| env->functions = CreateJNINativeInterface(); | |
| } | |
| void TearDown() override { | |
| // ResetNativeLoader isn't accessible through the lazy library, so we cannot | |
| // reset libnativeloader internal state. Hence be sure to not reuse the same | |
| // class loader/namespace names. | |
| delete env->functions; | |
| jni_mock.reset(); | |
| } | |
| void CallCreateClassLoaderNamespace(const char* class_loader) { | |
| ON_CALL(*jni_mock, JniObject_getParent(StrEq(class_loader))).WillByDefault(Return(nullptr)); | |
| jstring err = CreateClassLoaderNamespace(env.get(), | |
| 17, | |
| env.get()->NewStringUTF(class_loader), | |
| false, | |
| env.get()->NewStringUTF("/data/app/foo/classes.dex"), | |
| env.get()->NewStringUTF("/data/app/foo"), | |
| /*permitted_path=*/nullptr, | |
| /*uses_library_list=*/nullptr); | |
| EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env.get(), err).c_str()); | |
| } | |
| std::unique_ptr<JNIEnv> env; | |
| }; | |
| TEST_F(NativeLoaderLazyTest, CreateClassLoaderNamespace) { | |
| CallCreateClassLoaderNamespace("my_classloader_1"); | |
| EXPECT_NE(FindNamespaceByClassLoader(env.get(), env.get()->NewStringUTF("my_classloader_1")), | |
| nullptr); | |
| } | |
| TEST_F(NativeLoaderLazyTest, OpenNativeLibrary) { | |
| bool needs_native_bridge; | |
| char* errmsg = nullptr; | |
| EXPECT_EQ(nullptr, | |
| OpenNativeLibrary(env.get(), | |
| 17, | |
| "libnotfound.so", | |
| env.get()->NewStringUTF("my_classloader"), | |
| /*caller_location=*/nullptr, | |
| /*library_path=*/nullptr, | |
| &needs_native_bridge, | |
| &errmsg)); | |
| EXPECT_NE(nullptr, errmsg); | |
| NativeLoaderFreeErrorMessage(errmsg); | |
| } | |
| TEST_F(NativeLoaderLazyTest, CloseNativeLibrary) { | |
| char* errmsg = nullptr; | |
| EXPECT_FALSE(CloseNativeLibrary(nullptr, false, &errmsg)); | |
| EXPECT_NE(nullptr, errmsg); | |
| NativeLoaderFreeErrorMessage(errmsg); | |
| } | |
| TEST_F(NativeLoaderLazyTest, OpenNativeLibraryInNamespace) { | |
| CallCreateClassLoaderNamespace("my_classloader_2"); | |
| struct NativeLoaderNamespace* ns = FindNativeLoaderNamespaceByClassLoader( | |
| env.get(), env.get()->NewStringUTF("my_classloader_2")); | |
| ASSERT_NE(nullptr, ns); | |
| bool needs_native_bridge; | |
| char* errmsg = nullptr; | |
| EXPECT_FALSE(OpenNativeLibraryInNamespace(ns, "libnotfound.so", &needs_native_bridge, &errmsg)); | |
| EXPECT_NE(nullptr, errmsg); | |
| NativeLoaderFreeErrorMessage(errmsg); | |
| } | |
| TEST_F(NativeLoaderLazyTest, FindNamespaceByClassLoader) { | |
| EXPECT_EQ(nullptr, FindNamespaceByClassLoader(env.get(), env.get()->NewStringUTF("namespace"))); | |
| } | |
| TEST_F(NativeLoaderLazyTest, FindNativeLoaderNamespaceByClassLoader) { | |
| EXPECT_EQ( | |
| nullptr, | |
| FindNativeLoaderNamespaceByClassLoader(env.get(), env.get()->NewStringUTF("namespace"))); | |
| } | |
| TEST_F(NativeLoaderLazyTest, NativeLoaderFreeErrorMessage) { | |
| NativeLoaderFreeErrorMessage(nullptr); | |
| } | |
| } // namespace nativeloader | |
| } // namespace android |