xref: /llvm-project/llvm/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp (revision 9f40457d61dc8285e454d688e9062c5813299341)
1 //===- llvm/unittest/Support/DynamicLibrary/DynamicLibraryTest.cpp --------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/Config/config.h"
11 #include "llvm/Support/DynamicLibrary.h"
12 #include "llvm/Support/FileSystem.h"
13 #include "llvm/Support/ManagedStatic.h"
14 #include "llvm/Support/Path.h"
15 #include "gtest/gtest.h"
16 
17 #include "PipSqueak.h"
18 #include <string>
19 
20 using namespace llvm;
21 using namespace llvm::sys;
22 
23 extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "ProcessCall"; }
24 
25 std::string LibPath() {
26   std::string Path =
27       fs::getMainExecutable("DynamicLibraryTests", (void *)&TestA);
28   llvm::SmallString<256> Buf(path::parent_path(Path));
29   path::append(Buf, "PipSqueak.so");
30   return Buf.str();
31 }
32 
33 #if defined(_WIN32) || (defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN))
34 
35 typedef void (*SetStrings)(std::string &GStr, std::string &LStr);
36 typedef const char *(*GetString)();
37 
38 template <class T> static T FuncPtr(void *Ptr) {
39   union {
40     T F;
41     void *P;
42   } Tmp;
43   Tmp.P = Ptr;
44   return Tmp.F;
45 }
46 template <class T> static void* PtrFunc(T *Func) {
47   union {
48     T *F;
49     void *P;
50   } Tmp;
51   Tmp.F = Func;
52   return Tmp.P;
53 }
54 
55 static const char *OverloadTestA() { return "OverloadCall"; }
56 
57 std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; }
58 
59 TEST(DynamicLibrary, Overload) {
60   {
61     std::string Err;
62     llvm_shutdown_obj Shutdown;
63     DynamicLibrary DL =
64         DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
65     EXPECT_TRUE(DL.isValid());
66     EXPECT_TRUE(Err.empty());
67 
68     GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
69     EXPECT_TRUE(GS != nullptr && GS != &TestA);
70     EXPECT_EQ(StdString(GS()), "LibCall");
71 
72     GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
73     EXPECT_TRUE(GS != nullptr && GS != &TestA);
74     EXPECT_EQ(StdString(GS()), "LibCall");
75 
76     DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err);
77     EXPECT_TRUE(DL.isValid());
78     EXPECT_TRUE(Err.empty());
79 
80     GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
81     EXPECT_TRUE(GS != nullptr && GS == &TestA);
82     EXPECT_EQ(StdString(GS()), "ProcessCall");
83 
84     GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
85     EXPECT_TRUE(GS != nullptr && GS == &TestA);
86     EXPECT_EQ(StdString(GS()), "ProcessCall");
87 
88     DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA));
89     GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
90     EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA);
91 
92     GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
93     EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA);
94     EXPECT_EQ(StdString(GS()), "OverloadCall");
95   }
96   EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol(
97                   "TestA")) == nullptr);
98 }
99 
100 TEST(DynamicLibrary, Shutdown) {
101   std::string A, B;
102   {
103     std::string Err;
104     llvm_shutdown_obj Shutdown;
105     DynamicLibrary DL =
106         DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
107     EXPECT_TRUE(DL.isValid());
108     EXPECT_TRUE(Err.empty());
109 
110     SetStrings SS = FuncPtr<SetStrings>(
111         DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
112     EXPECT_TRUE(SS != nullptr);
113 
114     SS(A, B);
115     EXPECT_EQ(B, "Local::Local");
116   }
117   EXPECT_EQ(A, "Global::~Global");
118   EXPECT_EQ(B, "Local::~Local");
119   EXPECT_TRUE(FuncPtr<SetStrings>(DynamicLibrary::SearchForAddressOfSymbol(
120                   "SetStrings")) == nullptr);
121 }
122 
123 #else
124 
125 TEST(DynamicLibrary, Unsupported) {
126   std::string Err;
127   DynamicLibrary DL =
128       DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
129   EXPECT_FALSE(DL.isValid());
130   EXPECT_EQ(Err, "dlopen() not supported on this platform");
131 }
132 
133 #endif
134