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