Index: base/native_library_unittest.cc |
diff --git a/base/native_library_unittest.cc b/base/native_library_unittest.cc |
index c189f56e995c04598df5bf2d85c1a882dcafd629..1d0683d4c7e6e083da99efcd96acb517e338e128 100644 |
--- a/base/native_library_unittest.cc |
+++ b/base/native_library_unittest.cc |
@@ -3,7 +3,11 @@ |
// found in the LICENSE file. |
#include "base/files/file_path.h" |
+#include "base/macros.h" |
#include "base/native_library.h" |
+#include "base/path_service.h" |
+#include "base/test/native_library_test_utils.h" |
+#include "build/build_config.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace base { |
@@ -36,4 +40,100 @@ TEST(NativeLibraryTest, GetNativeLibraryName) { |
EXPECT_EQ(kExpectedName, GetNativeLibraryName("mylib")); |
} |
+// We don't support dynamic loading on iOS, and ASAN will complain about our |
+// intentional ODR violation because of |g_native_library_exported_value| being |
+// defined globally both here and in the shared library. |
+#if !defined(OS_IOS) && !defined(ADDRESS_SANITIZER) |
+ |
+const char kTestLibraryName[] = |
+#if defined(OS_MACOSX) |
+ "libtest_shared_library.dylib"; |
+#elif defined(OS_ANDROID) && defined(COMPONENT_BUILD) |
+ "libtest_shared_library.cr.so"; |
+#elif defined(OS_POSIX) |
+ "libtest_shared_library.so"; |
+#elif defined(OS_WIN) |
+ "test_shared_library.dll"; |
+#endif |
+ |
+class TestLibrary { |
+ public: |
+ TestLibrary() : TestLibrary(NativeLibraryOptions()) {} |
+ |
+ explicit TestLibrary(const NativeLibraryOptions& options) |
+ : library_(nullptr) { |
+ base::FilePath exe_path; |
+ CHECK(base::PathService::Get(base::DIR_EXE, &exe_path)); |
+ |
+ library_ = LoadNativeLibraryWithOptions( |
+ exe_path.AppendASCII(kTestLibraryName), options, nullptr); |
+ CHECK(library_); |
+ } |
+ |
+ ~TestLibrary() { |
+ UnloadNativeLibrary(library_); |
+ } |
+ |
+ template <typename ReturnType, typename... Args> |
+ ReturnType Call(const char* function_name, Args... args) { |
+ return reinterpret_cast<ReturnType(*)(Args...)>( |
+ GetFunctionPointerFromNativeLibrary(library_, function_name))(args...); |
+ } |
+ |
+ private: |
+ NativeLibrary library_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestLibrary); |
+}; |
+ |
+// Verifies that we can load a native library and resolve its exported symbols. |
+TEST(NativeLibraryTest, LoadLibrary) { |
+ TestLibrary library; |
+ EXPECT_EQ(5, library.Call<int>("GetSimpleTestValue")); |
+} |
+ |
+// Android dlopen() requires further investigation, as it might vary across |
+// versions with respect to symbol resolution scope. |
+#if !defined(OS_ANDROID) |
+ |
+// Verifies that the |prefer_own_symbols| option satisfies its guarantee that |
+// a loaded library will always prefer local symbol resolution before |
+// considering global symbols. |
+TEST(NativeLibraryTest, LoadLibraryPreferOwnSymbols) { |
+ NativeLibraryOptions options; |
+ options.prefer_own_symbols = true; |
+ TestLibrary library(options); |
+ |
+ // Verify that this binary and the DSO use different storage for |
+ // |g_native_library_exported_value|. |
+ g_native_library_exported_value = 1; |
+ library.Call<void>("SetExportedValue", 2); |
+ EXPECT_EQ(1, g_native_library_exported_value); |
+ g_native_library_exported_value = 3; |
+ EXPECT_EQ(2, library.Call<int>("GetExportedValue")); |
+ |
+ // Both this binary and the library link against the |
+ // native_library_test_utils source library, which in turn exports the |
+ // NativeLibraryTestIncrement() function whose return value depends on some |
+ // static internal state. |
+ // |
+ // The DSO's GetIncrementValue() forwards to that function inside the DSO. |
+ // |
+ // Here we verify that direct calls to NativeLibraryTestIncrement() in this |
+ // binary return a sequence of values independent from the sequence returned |
+ // by GetIncrementValue(), ensuring that the DSO is calling its own local |
+ // definition of NativeLibraryTestIncrement(). |
+ EXPECT_EQ(1, library.Call<int>("GetIncrementValue")); |
+ EXPECT_EQ(1, NativeLibraryTestIncrement()); |
+ EXPECT_EQ(2, library.Call<int>("GetIncrementValue")); |
+ EXPECT_EQ(3, library.Call<int>("GetIncrementValue")); |
+ EXPECT_EQ(4, library.Call<int>("NativeLibraryTestIncrement")); |
+ EXPECT_EQ(2, NativeLibraryTestIncrement()); |
+ EXPECT_EQ(3, NativeLibraryTestIncrement()); |
+} |
+ |
+#endif // !defined(OS_ANDROID) |
+ |
+#endif // !defined(OS_IOS) && !defined(ADDRESS_SANITIZER) |
+ |
} // namespace base |