2424#include " gtest/gtest.h"
2525
2626#include < algorithm>
27+ #include < thread>
2728#include < utility>
2829
2930using ::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
262263TEST (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+
367373TEST (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}
0 commit comments