Chromium Code Reviews| Index: base/native_library_unittest.cc |
| diff --git a/base/native_library_unittest.cc b/base/native_library_unittest.cc |
| index c189f56e995c04598df5bf2d85c1a882dcafd629..ad18eb6d6777f21b35d9ff44d8406b47a2ef3146 100644 |
| --- a/base/native_library_unittest.cc |
| +++ b/base/native_library_unittest.cc |
| @@ -4,6 +4,9 @@ |
| #include "base/files/file_path.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 +39,97 @@ 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: |
| + explicit TestLibrary( |
| + const NativeLibraryOptions& options = NativeLibraryOptions()) |
|
Primiano Tucci (use gerrit)
2016/08/25 21:10:53
isn't this a reference to a temporary object? No i
Ken Rockot(use gerrit already)
2016/08/25 21:25:01
Nah, this will default-construct a new value at th
|
| + : 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...); |
|
Primiano Tucci (use gerrit)
2016/08/25 21:10:53
neat :)
|
| + } |
| + |
| + private: |
| + NativeLibrary library_; |
| +}; |
| + |
| +// 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() behavior is not well specified with respect to symbol |
| +// resolution scope and may vary across versions. |
| +#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 |