Home | History | Annotate | Download | only in DynamicLibrary
      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/Support/DynamicLibrary.h"
     11 #include "llvm/Config/config.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 
     19 using namespace llvm;
     20 using namespace llvm::sys;
     21 
     22 std::string LibPath(const std::string Name = "PipSqueak") {
     23   const std::vector<testing::internal::string> &Argvs =
     24       testing::internal::GetArgvs();
     25   const char *Argv0 =
     26       Argvs.size() > 0 ? Argvs[0].c_str() : "DynamicLibraryTests";
     27   void *Ptr = (void*)(intptr_t)TestA;
     28   std::string Path = fs::getMainExecutable(Argv0, Ptr);
     29   llvm::SmallString<256> Buf(path::parent_path(Path));
     30   path::append(Buf, (Name + LTDL_SHLIB_EXT).c_str());
     31   return Buf.str();
     32 }
     33 
     34 #if defined(_WIN32) || (defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN))
     35 
     36 typedef void (*SetStrings)(std::string &GStr, std::string &LStr);
     37 typedef void (*TestOrder)(std::vector<std::string> &V);
     38 typedef const char *(*GetString)();
     39 
     40 template <class T> static T FuncPtr(void *Ptr) {
     41   union {
     42     T F;
     43     void *P;
     44   } Tmp;
     45   Tmp.P = Ptr;
     46   return Tmp.F;
     47 }
     48 template <class T> static void* PtrFunc(T *Func) {
     49   union {
     50     T *F;
     51     void *P;
     52   } Tmp;
     53   Tmp.F = Func;
     54   return Tmp.P;
     55 }
     56 
     57 static const char *OverloadTestA() { return "OverloadCall"; }
     58 
     59 std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; }
     60 
     61 TEST(DynamicLibrary, Overload) {
     62   {
     63     std::string Err;
     64     llvm_shutdown_obj Shutdown;
     65     DynamicLibrary DL =
     66         DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
     67     EXPECT_TRUE(DL.isValid());
     68     EXPECT_TRUE(Err.empty());
     69 
     70     GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
     71     EXPECT_TRUE(GS != nullptr && GS != &TestA);
     72     EXPECT_EQ(StdString(GS()), "LibCall");
     73 
     74     GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
     75     EXPECT_TRUE(GS != nullptr && GS != &TestA);
     76     EXPECT_EQ(StdString(GS()), "LibCall");
     77 
     78     DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err);
     79     EXPECT_TRUE(DL.isValid());
     80     EXPECT_TRUE(Err.empty());
     81 
     82     // Test overloading local symbols does not occur by default
     83     GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
     84     EXPECT_TRUE(GS != nullptr && GS == &TestA);
     85     EXPECT_EQ(StdString(GS()), "ProcessCall");
     86 
     87     GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
     88     EXPECT_TRUE(GS != nullptr && GS == &TestA);
     89     EXPECT_EQ(StdString(GS()), "ProcessCall");
     90 
     91     // Test overloading by forcing library priority when searching for a symbol
     92     DynamicLibrary::SearchOrder = DynamicLibrary::SO_LoadedFirst;
     93     GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
     94     EXPECT_TRUE(GS != nullptr && GS != &TestA);
     95     EXPECT_EQ(StdString(GS()), "LibCall");
     96 
     97     DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA));
     98     GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
     99     EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA);
    100 
    101     GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
    102     EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA);
    103     EXPECT_EQ(StdString(GS()), "OverloadCall");
    104   }
    105   EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol(
    106                   "TestA")) == nullptr);
    107 
    108   // Check serach ordering is reset to default after call to llvm_shutdown
    109   EXPECT_TRUE(DynamicLibrary::SearchOrder == DynamicLibrary::SO_Linker);
    110 }
    111 
    112 TEST(DynamicLibrary, Shutdown) {
    113   std::string A("PipSqueak"), B, C("SecondLib");
    114   std::vector<std::string> Order;
    115   {
    116     std::string Err;
    117     llvm_shutdown_obj Shutdown;
    118     DynamicLibrary DL =
    119         DynamicLibrary::getPermanentLibrary(LibPath(A).c_str(), &Err);
    120     EXPECT_TRUE(DL.isValid());
    121     EXPECT_TRUE(Err.empty());
    122 
    123     SetStrings SS_0 = FuncPtr<SetStrings>(
    124         DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
    125     EXPECT_TRUE(SS_0 != nullptr);
    126 
    127     SS_0(A, B);
    128     EXPECT_EQ(B, "Local::Local(PipSqueak)");
    129 
    130     TestOrder TO_0 = FuncPtr<TestOrder>(
    131         DynamicLibrary::SearchForAddressOfSymbol("TestOrder"));
    132     EXPECT_TRUE(TO_0 != nullptr);
    133 
    134     DynamicLibrary DL2 =
    135         DynamicLibrary::getPermanentLibrary(LibPath(C).c_str(), &Err);
    136     EXPECT_TRUE(DL2.isValid());
    137     EXPECT_TRUE(Err.empty());
    138 
    139     // Should find latest version of symbols in SecondLib
    140     SetStrings SS_1 = FuncPtr<SetStrings>(
    141         DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
    142     EXPECT_TRUE(SS_1 != nullptr);
    143     EXPECT_TRUE(SS_0 != SS_1);
    144 
    145     TestOrder TO_1 = FuncPtr<TestOrder>(
    146         DynamicLibrary::SearchForAddressOfSymbol("TestOrder"));
    147     EXPECT_TRUE(TO_1 != nullptr);
    148     EXPECT_TRUE(TO_0 != TO_1);
    149 
    150     B.clear();
    151     SS_1(C, B);
    152     EXPECT_EQ(B, "Local::Local(SecondLib)");
    153 
    154     TO_0(Order);
    155     TO_1(Order);
    156   }
    157   EXPECT_EQ(A, "Global::~Global");
    158   EXPECT_EQ(B, "Local::~Local");
    159   EXPECT_TRUE(FuncPtr<SetStrings>(DynamicLibrary::SearchForAddressOfSymbol(
    160                   "SetStrings")) == nullptr);
    161 
    162   // Test unload/destruction ordering
    163   EXPECT_EQ(Order.size(), 2UL);
    164   EXPECT_EQ(Order.front(), "SecondLib");
    165   EXPECT_EQ(Order.back(), "PipSqueak");
    166 }
    167 
    168 #else
    169 
    170 TEST(DynamicLibrary, Unsupported) {
    171   std::string Err;
    172   DynamicLibrary DL =
    173       DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
    174   EXPECT_FALSE(DL.isValid());
    175   EXPECT_EQ(Err, "dlopen() not supported on this platform");
    176 }
    177 
    178 #endif
    179