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