• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/native_library.h"
6 
7 #include "base/check.h"
8 #include "base/files/file_path.h"
9 #include "base/path_service.h"
10 #include "base/test/native_library_test_utils.h"
11 #include "build/build_config.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace base {
15 
16 const FilePath::CharType kDummyLibraryPath[] =
17     FILE_PATH_LITERAL("dummy_library");
18 
TEST(NativeLibraryTest,LoadFailure)19 TEST(NativeLibraryTest, LoadFailure) {
20   NativeLibraryLoadError error;
21   EXPECT_FALSE(LoadNativeLibrary(FilePath(kDummyLibraryPath), &error));
22   EXPECT_FALSE(error.ToString().empty());
23 }
24 
25 // |error| is optional and can be null.
TEST(NativeLibraryTest,LoadFailureWithNullError)26 TEST(NativeLibraryTest, LoadFailureWithNullError) {
27   EXPECT_FALSE(LoadNativeLibrary(FilePath(kDummyLibraryPath), nullptr));
28 }
29 
30 #if BUILDFLAG(IS_FUCHSIA)
TEST(NativeLibraryTest,LoadAbsolutePath)31 TEST(NativeLibraryTest, LoadAbsolutePath) {
32   EXPECT_TRUE(LoadNativeLibrary(FilePath("/pkg/lib/libtest_shared_library.so"),
33                                 nullptr));
34 }
35 
TEST(NativeLibraryTest,LoadAbsolutePath_OutsideLibraryRoot)36 TEST(NativeLibraryTest, LoadAbsolutePath_OutsideLibraryRoot) {
37   NativeLibraryLoadError error;
38   EXPECT_FALSE(LoadNativeLibrary(FilePath("/pkg/tmp/libtest_shared_library.so"),
39                                  &error));
40   std::string expected_error =
41       "Absolute library paths must begin with /pkg/lib";
42   EXPECT_EQ(error.ToString(), expected_error);
43 }
44 #endif
45 
TEST(NativeLibraryTest,GetNativeLibraryName)46 TEST(NativeLibraryTest, GetNativeLibraryName) {
47   const char kExpectedName[] =
48 #if BUILDFLAG(IS_WIN)
49       "mylib.dll";
50 #elif BUILDFLAG(IS_IOS)
51       "mylib.framework/mylib";
52 #elif BUILDFLAG(IS_MAC)
53       "libmylib.dylib";
54 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
55       "libmylib.so";
56 #endif
57   EXPECT_EQ(kExpectedName, GetNativeLibraryName("mylib"));
58 }
59 
TEST(NativeLibraryTest,GetLoadableModuleName)60 TEST(NativeLibraryTest, GetLoadableModuleName) {
61   const char kExpectedName[] =
62 #if BUILDFLAG(IS_WIN)
63       "mylib.dll";
64 #elif BUILDFLAG(IS_IOS)
65       "mylib.framework";
66 #elif BUILDFLAG(IS_MAC)
67       "mylib.so";
68 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
69       "libmylib.so";
70 #endif
71   EXPECT_EQ(kExpectedName, GetLoadableModuleName("mylib"));
72 }
73 
74 // ASAN will complain about our intentional ODR violation because of
75 // |g_native_library_exported_value| being defined globally both here
76 // and in the shared library.
77 #if !defined(ADDRESS_SANITIZER)
78 
79 const char kTestLibraryName[] =
80 #if BUILDFLAG(IS_WIN)
81     "test_shared_library.dll";
82 #elif BUILDFLAG(IS_IOS)
83     "Frameworks/test_shared_library_ios.framework/test_shared_library_ios";
84 #elif BUILDFLAG(IS_MAC)
85     "libtest_shared_library.dylib";
86 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
87     "libtest_shared_library.so";
88 #endif
89 
90 class TestLibrary {
91  public:
TestLibrary()92   TestLibrary() : TestLibrary(NativeLibraryOptions()) {}
93 
TestLibrary(const NativeLibraryOptions & options)94   explicit TestLibrary(const NativeLibraryOptions& options)
95       : library_(nullptr) {
96     base::FilePath exe_path;
97 
98 #if !BUILDFLAG(IS_FUCHSIA)
99     // Libraries do not sit alongside the executable in Fuchsia. NativeLibrary
100     // is aware of this and is able to resolve library paths correctly.
101     CHECK(base::PathService::Get(base::DIR_EXE, &exe_path));
102 #endif
103 
104     library_ = LoadNativeLibraryWithOptions(
105         exe_path.AppendASCII(kTestLibraryName), options, nullptr);
106     CHECK(library_);
107   }
108   TestLibrary(const TestLibrary&) = delete;
109   TestLibrary& operator=(const TestLibrary&) = delete;
~TestLibrary()110   ~TestLibrary() { UnloadNativeLibrary(library_); }
111 
112   template <typename ReturnType, typename... Args>
Call(const char * function_name,Args...args)113   ReturnType Call(const char* function_name, Args... args) {
114     return reinterpret_cast<ReturnType (*)(Args...)>(
115         GetFunctionPointerFromNativeLibrary(library_, function_name))(args...);
116   }
117 
118  private:
119   NativeLibrary library_;
120 };
121 
122 // NativeLibraaryTest.LoadLibrary is failing on M tablets only.
123 // crbug/641309
124 #if !BUILDFLAG(IS_ANDROID)
125 
126 // Verifies that we can load a native library and resolve its exported symbols.
TEST(NativeLibraryTest,LoadLibrary)127 TEST(NativeLibraryTest, LoadLibrary) {
128   TestLibrary library;
129   EXPECT_EQ(5, library.Call<int>("GetSimpleTestValue"));
130 }
131 
132 #endif  // !BUILDFLAG(IS_ANDROID)
133 
134 // Android dlopen() requires further investigation, as it might vary across
135 // versions with respect to symbol resolution scope.
136 // TSan and MSan error out on RTLD_DEEPBIND, https://crbug.com/705255
137 #if !BUILDFLAG(IS_ANDROID) && !defined(THREAD_SANITIZER) && \
138     !defined(MEMORY_SANITIZER)
139 
140 // Verifies that the |prefer_own_symbols| option satisfies its guarantee that
141 // a loaded library will always prefer local symbol resolution before
142 // considering global symbols.
TEST(NativeLibraryTest,LoadLibraryPreferOwnSymbols)143 TEST(NativeLibraryTest, LoadLibraryPreferOwnSymbols) {
144   NativeLibraryOptions options;
145   options.prefer_own_symbols = true;
146   TestLibrary library(options);
147 
148   // Verify that this binary and the DSO use different storage for
149   // |g_native_library_exported_value|.
150   g_native_library_exported_value = 1;
151   library.Call<void>("SetExportedValue", 2);
152   EXPECT_EQ(1, g_native_library_exported_value);
153   g_native_library_exported_value = 3;
154   EXPECT_EQ(2, library.Call<int>("GetExportedValue"));
155 
156   // Both this binary and the library link against the
157   // native_library_test_utils source library, which in turn exports the
158   // NativeLibraryTestIncrement() function whose return value depends on some
159   // static internal state.
160   //
161   // The DSO's GetIncrementValue() forwards to that function inside the DSO.
162   //
163   // Here we verify that direct calls to NativeLibraryTestIncrement() in this
164   // binary return a sequence of values independent from the sequence returned
165   // by GetIncrementValue(), ensuring that the DSO is calling its own local
166   // definition of NativeLibraryTestIncrement().
167 
168   // Ensure that the counter starts at the expected value (0).
169   library.Call<void>("NativeLibraryResetCounter");
170   NativeLibraryResetCounter();
171 
172   EXPECT_EQ(1, library.Call<int>("GetIncrementValue"));
173   EXPECT_EQ(1, NativeLibraryTestIncrement());
174   EXPECT_EQ(2, library.Call<int>("GetIncrementValue"));
175   EXPECT_EQ(3, library.Call<int>("GetIncrementValue"));
176   EXPECT_EQ(4, library.Call<int>("NativeLibraryTestIncrement"));
177   EXPECT_EQ(2, NativeLibraryTestIncrement());
178   EXPECT_EQ(3, NativeLibraryTestIncrement());
179 }
180 
181 #endif  // !BUILDFLAG(IS_ANDROID) && !defined(THREAD_SANITIZER) && \
182         // !defined(MEMORY_SANITIZER)
183 
184 #endif  // !defined(ADDRESS_SANITIZER)
185 
186 }  // namespace base
187