Skip to content

Commit 9140587

Browse files
Add test to run things in parallel
1 parent 271c592 commit 9140587

File tree

9 files changed

+167
-20
lines changed

9 files changed

+167
-20
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3459,6 +3459,8 @@ static inline auto find_interpreter_in_map(InterpreterInfo* I) {
34593459
bool DeleteInterpreter(TInterp_t I /*=nullptr*/) {
34603460
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
34613461
assert(sInterpreters->size() == sInterpreterASTMap->size());
3462+
if (sInterpreters->empty())
3463+
return false;
34623464

34633465
if (!I) {
34643466
auto foundAST = find_interpreter_in_map(sInterpreters->back().get());

unittests/CppInterOp/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ set_output_directory(DynamicLibraryManagerTests
128128
)
129129

130130
add_dependencies(DynamicLibraryManagerTests TestSharedLib)
131+
add_dependencies(DynamicLibraryManagerTests TestSharedLib2)
131132

132133
#export_executable_symbols_for_plugins(TestSharedLib)
133134
add_subdirectory(TestSharedLib)
135+
add_subdirectory(TestSharedLib2)

unittests/CppInterOp/DynamicLibraryManagerTest.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ std::string GetExecutablePath(const char* Argv0) {
1919
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
2020
}
2121

22-
TEST(DynamicLibraryManagerTest, Sanity) {
22+
TEST(DynamicLibraryManagerTest, Sanity1) {
2323
#ifdef EMSCRIPTEN
2424
GTEST_SKIP() << "Test fails for Emscipten builds";
2525
#endif
@@ -66,6 +66,55 @@ TEST(DynamicLibraryManagerTest, Sanity) {
6666
// EXPECT_FALSE(Cpp::GetFunctionAddress("ret_zero"));
6767
}
6868

69+
TEST(DynamicLibraryManagerTest, Sanity2) {
70+
#ifdef EMSCRIPTEN
71+
GTEST_SKIP() << "Test fails for Emscipten builds";
72+
#endif
73+
74+
#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \
75+
defined(_WIN32)
76+
GTEST_SKIP() << "Test fails with Cling on Windows";
77+
#endif
78+
79+
auto* I = Cpp::CreateInterpreter();
80+
EXPECT_TRUE(I);
81+
EXPECT_FALSE(Cpp::GetFunctionAddress("ret_one", I));
82+
83+
std::string BinaryPath = GetExecutablePath(/*Argv0=*/nullptr);
84+
llvm::StringRef Dir = llvm::sys::path::parent_path(BinaryPath);
85+
Cpp::AddSearchPath(Dir.str().c_str(), true, false, I);
86+
87+
// FIXME: dlsym on mach-o takes the C-level name, however, the macho-o format
88+
// adds an additional underscore (_) prefix to the lowered names. Figure out
89+
// how to harmonize that API.
90+
#ifdef __APPLE__
91+
std::string PathToTestSharedLib =
92+
Cpp::SearchLibrariesForSymbol("_ret_one", /*system_search=*/false, I);
93+
#else
94+
std::string PathToTestSharedLib =
95+
Cpp::SearchLibrariesForSymbol("ret_one", /*system_search=*/false, I);
96+
#endif // __APPLE__
97+
98+
EXPECT_STRNE("", PathToTestSharedLib.c_str())
99+
<< "Cannot find: '" << PathToTestSharedLib << "' in '" << Dir.str()
100+
<< "'";
101+
102+
EXPECT_TRUE(Cpp::LoadLibrary(PathToTestSharedLib.c_str(), true, I));
103+
// Force ExecutionEngine to be created.
104+
Cpp::Process("", I);
105+
Cpp::Declare("", I);
106+
// FIXME: Conda returns false to run this code on osx.
107+
#ifndef __APPLE__
108+
EXPECT_TRUE(Cpp::GetFunctionAddress("ret_one", I));
109+
#endif //__APPLE__
110+
111+
Cpp::UnloadLibrary("TestSharedLib2", I);
112+
// We have no reliable way to check if it was unloaded because posix does not
113+
// require the library to be actually unloaded but just the handle to be
114+
// invalidated...
115+
// EXPECT_FALSE(Cpp::GetFunctionAddress("ret_zero"));
116+
}
117+
69118
TEST(DynamicLibraryManagerTest, BasicSymbolLookup) {
70119
#ifndef EMSCRIPTEN
71120
GTEST_SKIP() << "This test is only intended for Emscripten builds.";

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,8 @@ TEST(FunctionReflectionTest, BestOverloadFunctionMatch1) {
10141014
GetAllTopLevelDecls(code, Decls);
10151015
std::vector<Cpp::TCppFunction_t> candidates;
10161016

1017+
EXPECT_FALSE(Cpp::BestOverloadFunctionMatch({}, {}, {}));
1018+
10171019
for (auto decl : Decls)
10181020
if (Cpp::IsTemplatedFunction(decl)) candidates.push_back((Cpp::TCppFunction_t)decl);
10191021

unittests/CppInterOp/InterpreterTest.cpp

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "gtest/gtest.h"
2525

2626
#include <algorithm>
27+
#include <thread>
2728
#include <utility>
2829

2930
using ::testing::StartsWith;
@@ -247,7 +248,7 @@ TEST(InterpreterTest, DISABLED_DetectResourceDir) {
247248
#ifdef _WIN32
248249
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
249250
#endif
250-
Cpp::CreateInterpreter();
251+
auto* I = Cpp::CreateInterpreter();
251252
EXPECT_STRNE(Cpp::DetectResourceDir().c_str(), Cpp::GetResourceDir());
252253
llvm::SmallString<256> Clang(LLVM_BINARY_DIR);
253254
llvm::sys::path::append(Clang, "bin", "clang");
@@ -256,7 +257,7 @@ TEST(InterpreterTest, DISABLED_DetectResourceDir) {
256257
GTEST_SKIP() << "Test not run (Clang binary does not exist)";
257258

258259
std::string DetectedPath = Cpp::DetectResourceDir(Clang.str().str().c_str());
259-
EXPECT_STREQ(DetectedPath.c_str(), Cpp::GetResourceDir());
260+
EXPECT_STREQ(DetectedPath.c_str(), Cpp::GetResourceDir(I));
260261
}
261262

262263
TEST(InterpreterTest, DetectSystemCompilerIncludePaths) {
@@ -364,26 +365,78 @@ if (llvm::sys::RunningOnValgrind())
364365
#endif
365366
}
366367

368+
static int printf_jit(const char* format, ...) {
369+
llvm::errs() << "printf_jit called!\n";
370+
return 0;
371+
}
372+
367373
TEST(InterpreterTest, MultipleInterpreter) {
368-
#if CLANG_VERSION_MAJOR < 20 && defined(EMSCRIPTEN)
369-
GTEST_SKIP() << "Test fails for Emscipten LLVM 20 builds";
374+
#ifdef EMSCRIPTEN
375+
GTEST_SKIP() << "Test fails for Emscipten builds";
370376
#endif
371-
auto* I = Cpp::CreateInterpreter();
372-
EXPECT_TRUE(I);
373-
Cpp::Declare(R"(
374-
void f() {}
375-
)");
376-
Cpp::TCppScope_t f = Cpp::GetNamed("f");
377+
// delete all old interpreters
378+
while (Cpp::DeleteInterpreter())
379+
;
380+
auto* I1 = Cpp::CreateInterpreter();
381+
EXPECT_TRUE(I1);
382+
383+
auto F = [](Cpp::TInterp_t I) {
384+
bool hasError = true;
385+
EXPECT_TRUE(Cpp::Evaluate("__cplusplus", &hasError, I) == 201402);
386+
EXPECT_FALSE(hasError);
387+
388+
Cpp::Declare(R"(
389+
extern "C" int printf(const char*,...);
390+
class MyKlass {};
391+
)",
392+
false, I);
393+
Cpp::TCppScope_t f = Cpp::GetNamed("printf", Cpp::GetGlobalScope(I));
394+
EXPECT_TRUE(f);
395+
EXPECT_TRUE(Cpp::GetComplexType(Cpp::GetType("int", I)));
396+
Cpp::TCppType_t MyKlass = Cpp::GetType("MyKlass", I);
397+
EXPECT_EQ(Cpp::GetTypeAsString(MyKlass), "MyKlass");
398+
EXPECT_EQ(Cpp::GetNumBases(MyKlass), 0);
399+
EXPECT_FALSE(Cpp::GetBaseClass(MyKlass, 3));
400+
std::vector<Cpp::TCppScope_t> members;
401+
Cpp::GetEnumConstantDatamembers(Cpp::GetScopeFromType(MyKlass), members);
402+
EXPECT_EQ(members.size(), 0);
403+
404+
EXPECT_FALSE(
405+
Cpp::InsertOrReplaceJitSymbol("printf", (uint64_t)&printf_jit, I));
406+
407+
auto f_callable = Cpp::MakeFunctionCallable(f);
408+
EXPECT_EQ(f_callable.getKind(), Cpp::JitCall::Kind::kGenericCall);
409+
410+
EXPECT_FALSE(
411+
Cpp::TakeInterpreter((TInterp_t)1)); // try to take ownership of an
412+
// interpreter that does not exist
413+
414+
std::vector<std::string> includes;
415+
Cpp::AddIncludePath("/non/existent/", I);
416+
Cpp::GetIncludePaths(includes, false, false, I);
417+
EXPECT_NE(std::find(includes.begin(), includes.end(), "/non/existent/"),
418+
std::end(includes));
419+
420+
EXPECT_TRUE(Cpp::InsertOrReplaceJitSymbol("non_existent", (uint64_t)&f, I));
421+
};
422+
F(I1);
377423

378424
auto* I2 = Cpp::CreateInterpreter();
425+
auto* I3 = Cpp::CreateInterpreter();
426+
auto* I4 = Cpp::CreateInterpreter();
379427
EXPECT_TRUE(I2);
380-
Cpp::Declare(R"(
381-
void ff() {}
382-
)");
383-
Cpp::TCppScope_t ff = Cpp::GetNamed("ff");
384-
385-
auto f_callable = Cpp::MakeFunctionCallable(f);
386-
EXPECT_EQ(f_callable.getKind(), Cpp::JitCall::Kind::kGenericCall);
387-
auto ff_callable = Cpp::MakeFunctionCallable(ff);
388-
EXPECT_EQ(ff_callable.getKind(), Cpp::JitCall::Kind::kGenericCall);
428+
EXPECT_TRUE(I3);
429+
EXPECT_TRUE(I4);
430+
431+
std::thread t2(F, I2);
432+
std::thread t3(F, I3);
433+
std::thread t4(F, I4);
434+
t2.join();
435+
t3.join();
436+
t4.join();
437+
438+
testing::internal::CaptureStderr();
439+
Cpp::Process("printf(\"Blah\");", I2);
440+
std::string cerrs = testing::internal::GetCapturedStderr();
441+
EXPECT_STREQ(cerrs.c_str(), "printf_jit called!\n");
389442
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
add_llvm_library(TestSharedLib2
2+
SHARED
3+
DISABLE_LLVM_LINK_LLVM_DYLIB
4+
BUILDTREE_ONLY
5+
TestSharedLib.cpp)
6+
# Put TestSharedLib2 next to the unit test executable.
7+
set_output_directory(TestSharedLib2
8+
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../TestSharedLib/unittests/bin/$<CONFIG>/
9+
LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../TestSharedLib/unittests/bin/$<CONFIG>/
10+
)
11+
12+
13+
if (EMSCRIPTEN)
14+
set_target_properties(TestSharedLib2
15+
PROPERTIES NO_SONAME 1
16+
)
17+
target_link_options(TestSharedLib2
18+
PRIVATE "SHELL: -s WASM_BIGINT"
19+
PRIVATE "SHELL: -s SIDE_MODULE=1"
20+
)
21+
endif()
22+
23+
set_target_properties(TestSharedLib2 PROPERTIES FOLDER "Tests")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include "TestSharedLib.h"
2+
3+
int ret_one() { return 1; }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef UNITTESTS_CPPINTEROP_TESTSHAREDLIB_TESTSHAREDLIB_H
2+
#define UNITTESTS_CPPINTEROP_TESTSHAREDLIB_TESTSHAREDLIB_H
3+
4+
// Avoid having to mangle/demangle the symbol name in tests
5+
#ifdef _WIN32
6+
extern "C" __declspec(dllexport) int ret_one();
7+
#else
8+
extern "C" int __attribute__((visibility("default"))) ret_one();
9+
#endif
10+
11+
#endif // UNITTESTS_CPPINTEROP_TESTSHAREDLIB_TESTSHAREDLIB_H

unittests/CppInterOp/VariableReflectionTest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ TEST(VariableReflectionTest, GetVariableOffset) {
287287
std::vector<Cpp::TCppScope_t> datamembers;
288288
Cpp::GetDatamembers(Decls[4], datamembers);
289289

290+
EXPECT_FALSE((bool)Cpp::GetVariableOffset(nullptr));
291+
290292
EXPECT_TRUE((bool) Cpp::GetVariableOffset(Decls[0])); // a
291293
EXPECT_TRUE((bool) Cpp::GetVariableOffset(Decls[1])); // N
292294
EXPECT_TRUE((bool)Cpp::GetVariableOffset(Decls[2])); // S

0 commit comments

Comments
 (0)