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