blob: 5730d610cdfff33f29c03a6e24bbdd65610e7022 [file] [log] [blame]
Frederich Munchc1db8cf2017-04-27 16:55:24 +00001//===- 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
Frederich Munchc1db8cf2017-04-27 16:55:24 +000010#include "llvm/Support/DynamicLibrary.h"
Chandler Carruth9a67b072017-06-06 11:06:56 +000011#include "llvm/Config/config.h"
Frederich Munchc1db8cf2017-04-27 16:55:24 +000012#include "llvm/Support/FileSystem.h"
13#include "llvm/Support/ManagedStatic.h"
14#include "llvm/Support/Path.h"
Frederich Munch4c73b402017-06-13 16:48:41 +000015#include "llvm/Transforms/IPO/PassManagerBuilder.h"
Frederich Munchc1db8cf2017-04-27 16:55:24 +000016#include "gtest/gtest.h"
17
18#include "PipSqueak.h"
Frederich Munchc1db8cf2017-04-27 16:55:24 +000019
20using namespace llvm;
21using namespace llvm::sys;
22
Frederich Munchad125802017-06-05 16:26:58 +000023std::string LibPath(const std::string Name = "PipSqueak") {
Dimitry Andric287a9ea2017-05-17 19:46:49 +000024 const std::vector<testing::internal::string>& Argvs = testing::internal::GetArgvs();
25 const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "DynamicLibraryTests";
Frederich Muncheab432a2017-04-27 22:10:57 +000026 void *Ptr = (void*)(intptr_t)TestA;
Dimitry Andric287a9ea2017-05-17 19:46:49 +000027 std::string Path = fs::getMainExecutable(Argv0, Ptr);
Frederich Munchc1db8cf2017-04-27 16:55:24 +000028 llvm::SmallString<256> Buf(path::parent_path(Path));
Frederich Munchad125802017-06-05 16:26:58 +000029 path::append(Buf, (Name+".so").c_str());
Frederich Munchc1db8cf2017-04-27 16:55:24 +000030 return Buf.str();
31}
32
33#if defined(_WIN32) || (defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN))
34
35typedef void (*SetStrings)(std::string &GStr, std::string &LStr);
Frederich Munchad125802017-06-05 16:26:58 +000036typedef void (*TestOrder)(std::vector<std::string> &V);
Frederich Munchc1db8cf2017-04-27 16:55:24 +000037typedef const char *(*GetString)();
38
39template <class T> static T FuncPtr(void *Ptr) {
40 union {
41 T F;
42 void *P;
43 } Tmp;
44 Tmp.P = Ptr;
45 return Tmp.F;
46}
47template <class T> static void* PtrFunc(T *Func) {
48 union {
49 T *F;
50 void *P;
51 } Tmp;
52 Tmp.F = Func;
53 return Tmp.P;
54}
55
Frederich Munch4c73b402017-06-13 16:48:41 +000056static void
57NoPassRegistration(const PassManagerBuilder &, legacy::PassManagerBase &) {
58}
59
60static RegisterStandardPasses LocalPass(PassManagerBuilder::EP_LoopOptimizerEnd,
61 NoPassRegistration);
62
63typedef void (*TestPassReg)(void (*)(PassManagerBuilder::ExtensionPointTy,
64 PassManagerBuilder::ExtensionProc));
65
66TEST(DynamicLibrary, PassRegistration) {
67 std::string Err;
68 llvm_shutdown_obj Shutdown;
69 DynamicLibrary DL =
70 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
71 EXPECT_TRUE(DL.isValid());
72 EXPECT_TRUE(Err.empty());
73
74 TestPassReg RP = FuncPtr<TestPassReg>(DL.getAddressOfSymbol("TestPassReg"));
75 RP(&PassManagerBuilder::addGlobalExtension);
76}
77
Frederich Munchc1db8cf2017-04-27 16:55:24 +000078static const char *OverloadTestA() { return "OverloadCall"; }
79
80std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; }
81
82TEST(DynamicLibrary, Overload) {
83 {
84 std::string Err;
85 llvm_shutdown_obj Shutdown;
86 DynamicLibrary DL =
87 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
88 EXPECT_TRUE(DL.isValid());
89 EXPECT_TRUE(Err.empty());
90
91 GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
92 EXPECT_TRUE(GS != nullptr && GS != &TestA);
93 EXPECT_EQ(StdString(GS()), "LibCall");
94
95 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
96 EXPECT_TRUE(GS != nullptr && GS != &TestA);
97 EXPECT_EQ(StdString(GS()), "LibCall");
98
99 DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err);
100 EXPECT_TRUE(DL.isValid());
101 EXPECT_TRUE(Err.empty());
102
103 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
104 EXPECT_TRUE(GS != nullptr && GS == &TestA);
105 EXPECT_EQ(StdString(GS()), "ProcessCall");
106
107 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
108 EXPECT_TRUE(GS != nullptr && GS == &TestA);
109 EXPECT_EQ(StdString(GS()), "ProcessCall");
110
111 DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA));
112 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
113 EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA);
114
115 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
116 EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA);
117 EXPECT_EQ(StdString(GS()), "OverloadCall");
118 }
119 EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol(
120 "TestA")) == nullptr);
121}
122
123TEST(DynamicLibrary, Shutdown) {
Frederich Munchad125802017-06-05 16:26:58 +0000124 std::string A("PipSqueak"), B, C("SecondLib");
125 std::vector<std::string> Order;
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000126 {
127 std::string Err;
128 llvm_shutdown_obj Shutdown;
129 DynamicLibrary DL =
Frederich Munchad125802017-06-05 16:26:58 +0000130 DynamicLibrary::getPermanentLibrary(LibPath(A).c_str(), &Err);
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000131 EXPECT_TRUE(DL.isValid());
132 EXPECT_TRUE(Err.empty());
133
Frederich Munchad125802017-06-05 16:26:58 +0000134 SetStrings SS_0 = FuncPtr<SetStrings>(
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000135 DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
Frederich Munchad125802017-06-05 16:26:58 +0000136 EXPECT_TRUE(SS_0 != nullptr);
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000137
Frederich Munchad125802017-06-05 16:26:58 +0000138 SS_0(A, B);
139 EXPECT_EQ(B, "Local::Local(PipSqueak)");
140
141 TestOrder TO_0 = FuncPtr<TestOrder>(
142 DynamicLibrary::SearchForAddressOfSymbol("TestOrder"));
143 EXPECT_TRUE(TO_0 != nullptr);
144
145 DynamicLibrary DL2 =
146 DynamicLibrary::getPermanentLibrary(LibPath(C).c_str(), &Err);
147 EXPECT_TRUE(DL2.isValid());
148 EXPECT_TRUE(Err.empty());
149
150 // Should find latest version of symbols in SecondLib
151 SetStrings SS_1 = FuncPtr<SetStrings>(
152 DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
153 EXPECT_TRUE(SS_1 != nullptr);
154 EXPECT_TRUE(SS_0 != SS_1);
155
156 TestOrder TO_1 = FuncPtr<TestOrder>(
157 DynamicLibrary::SearchForAddressOfSymbol("TestOrder"));
158 EXPECT_TRUE(TO_1 != nullptr);
159 EXPECT_TRUE(TO_0 != TO_1);
160
161 B.clear();
162 SS_1(C, B);
163 EXPECT_EQ(B, "Local::Local(SecondLib)");
164
165 TO_0(Order);
166 TO_1(Order);
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000167 }
168 EXPECT_EQ(A, "Global::~Global");
169 EXPECT_EQ(B, "Local::~Local");
170 EXPECT_TRUE(FuncPtr<SetStrings>(DynamicLibrary::SearchForAddressOfSymbol(
171 "SetStrings")) == nullptr);
Frederich Munchad125802017-06-05 16:26:58 +0000172
173 // Test unload/destruction ordering
174 EXPECT_EQ(Order.size(), 2UL);
175 EXPECT_EQ(Order.front(), "SecondLib");
176 EXPECT_EQ(Order.back(), "PipSqueak");
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000177}
178
179#else
180
181TEST(DynamicLibrary, Unsupported) {
182 std::string Err;
183 DynamicLibrary DL =
184 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
185 EXPECT_FALSE(DL.isValid());
186 EXPECT_EQ(Err, "dlopen() not supported on this platform");
187}
188
189#endif