Skip to content

Fix Evaluate tests for emscripten build #544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

anutosh491
Copy link
Collaborator

@anutosh491 anutosh491 commented Apr 1, 2025

Description

I realized technically this should work. The only reason it might not is if we fail to fetch the -std=c++14 arg which we should !

Creating the interpreter correctly should fix that I suppose

TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
const std::vector<const char*>& GpuArgs /*={}*/) {
std::string MainExecutableName =
sys::fs::getMainExecutable(nullptr, nullptr);
std::string ResourceDir = MakeResourcesPath();
std::vector<const char *> ClingArgv = {"-resource-dir", ResourceDir.c_str(),
"-std=c++14"};

Type of change

Please tick all options which are relevant.

  • Bug fix
  • New feature
  • Requires documentation updates

Testing

Please describe the test(s) that you added and ran to verify your changes.

Checklist

  • I have read the contribution guide recently

Copy link
Contributor

github-actions bot commented Apr 1, 2025

clang-tidy review says "All clean, LGTM! 👍"

Copy link

codecov bot commented Apr 1, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 75.93%. Comparing base (96045bd) to head (37fa886).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #544   +/-   ##
=======================================
  Coverage   75.93%   75.93%           
=======================================
  Files           9        9           
  Lines        3644     3644           
=======================================
  Hits         2767     2767           
  Misses        877      877           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

github-actions bot commented Apr 1, 2025

clang-tidy review says "All clean, LGTM! 👍"

@anutosh491
Copy link
Collaborator Author

Strange, I won't expect the following to fail. Looks simple enough but it fails here

1: /home/runner/work/CppInterOp/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp:80: Failure
1: Expected equality of these values:
1:   Cpp::Evaluate("int i = 11; ++i", &HadError)
1:     Which is: 2
1:   12
1: 
1: [  FAILED  ] InterpreterTest.Evaluate (262 ms)

Tried it locally too

image

Not sure why we get 2 in the first place !

Copy link
Contributor

github-actions bot commented Apr 1, 2025

clang-tidy review says "All clean, LGTM! 👍"

@anutosh491 anutosh491 force-pushed the fix_evaluate_for_emscripten branch from 0210023 to e6bf84a Compare April 10, 2025 09:11
Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@anutosh491
Copy link
Collaborator Author

Okay this might be the weirdest thing I've come across in a while but I would like to bring your attention towards something (cc @vgvassilev @mcbarton )

If you go through the above comment of mine (#544 (comment)) you would realize that it is strange for something like this to fail. Its a simple Evaluate check which we have been doing since quite some time now and I also pasted an image of executing the same thing in xeus-cpp-lite.

Let me explain through a more clearer example on what is happening (cause the error here isn't justifying much)

Conside these 2 tests in FunctionReflectionTest

TEST(FunctionReflectionTest, Construct) {
..........

  Cpp::CreateInterpreter();

  Interp->declare(R"(
    #include <new>
    extern "C" int printf(const char*,...);
    class C {
      int x;
      C() {
        x = 12345;
        printf("Constructor Executed");
      }
    };
    )");

  testing::internal::CaptureStdout();
  Cpp::TCppScope_t scope = Cpp::GetNamed("C");
  Cpp::TCppObject_t object = Cpp::Construct(scope);
  EXPECT_TRUE(object != nullptr);
  std::string output = testing::internal::GetCapturedStdout();
  EXPECT_EQ(output, "Constructor Executed");
  output.clear();
  
TEST(FunctionReflectionTest, Destruct) {
.......

  Cpp::CreateInterpreter();

  Interp->declare(R"(
    #include <new>
    extern "C" int printf(const char*,...);
    class C {
      C() {}
      ~C() {
        printf("Destructor Executed");
      }
    };
    )");

  testing::internal::CaptureStdout();
  Cpp::TCppScope_t scope = Cpp::GetNamed("C");
  Cpp::TCppObject_t object = Cpp::Construct(scope);
  Cpp::Destruct(object, scope);
  std::string output = testing::internal::GetCapturedStdout();

  EXPECT_EQ(output, "Destructor Executed");

Now our emscripten build is good enough to address both these tests. But there is something going wrong with CaptureStdout and/or GetCapturedStdout provided by the emscripten build of gtest. So if Construct works, destruct won't work and would fail with this

1: /Users/anutosh491/work/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp:1593: Failure
1: Expected equality of these values:
1:   output
1:     Which is: "Constructor ExecutedDestructor Executed"
1:   "Destructor Executed"
1: 

So technically both these tests have the capacity to function perfectly on their own (and whichever would be placed first would work for now)

@anutosh491
Copy link
Collaborator Author

anutosh491 commented Apr 10, 2025

So basically what I realize is that its one of the GetCapturedStdout from EnumReflectionTest.cpp or FunctionReflectionTest.cpp that is spoiling this case with Evaluate. In simpler terms a side module loaded previously is spoiling the case here.

As a workaround (cause I am bullish on something like Evaluate to be test, I mean it is one of the basic things we should expect to work) I am just changing this for now

--- a/unittests/CppInterOp/CMakeLists.txt
+++ b/unittests/CppInterOp/CMakeLists.txt
@@ -10,9 +10,9 @@ else()
 endif()
 
 add_cppinterop_unittest(CppInterOpTests
-  EnumReflectionTest.cpp
-  FunctionReflectionTest.cpp
   InterpreterTest.cpp
+  FunctionReflectionTest.cpp
+  EnumReflectionTest.cpp

This ensures no flaky side module from the above affects stuff in InterpreterTest.cpp ( which technically is 3rd in place currently)

I know this might not be the "best" fix or so but i wouldn't have the time to look into what goes wrong in the emscripten build for gtest in the coming week or two. On the same note I think its really important to test something like Evaluate

So yeah changing the order changes nothing . Just gives us 1 more working test. Hope that's fine :)

Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@anutosh491 anutosh491 requested a review from vgvassilev April 14, 2025 06:33
@anutosh491 anutosh491 force-pushed the fix_evaluate_for_emscripten branch from 0615cd3 to 37fa886 Compare April 15, 2025 03:51
Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

InterpreterTest.cpp
FunctionReflectionTest.cpp
EnumReflectionTest.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to order this alphabetically.

@vgvassilev
Copy link
Contributor

So basically what I realize is that its one of the GetCapturedStdout from EnumReflectionTest.cpp or FunctionReflectionTest.cpp that is spoiling this case with Evaluate. In simpler terms a side module loaded previously is spoiling the case here.

As a workaround (cause I am bullish on something like Evaluate to be test, I mean it is one of the basic things we should expect to work) I am just changing this for now

--- a/unittests/CppInterOp/CMakeLists.txt
+++ b/unittests/CppInterOp/CMakeLists.txt
@@ -10,9 +10,9 @@ else()
 endif()
 
 add_cppinterop_unittest(CppInterOpTests
-  EnumReflectionTest.cpp
-  FunctionReflectionTest.cpp
   InterpreterTest.cpp
+  FunctionReflectionTest.cpp
+  EnumReflectionTest.cpp

This ensures no flaky side module from the above affects stuff in InterpreterTest.cpp ( which technically is 3rd in place currently)

I know this might not be the "best" fix or so but i wouldn't have the time to look into what goes wrong in the emscripten build for gtest in the coming week or two. On the same note I think its really important to test something like Evaluate

So yeah changing the order changes nothing . Just gives us 1 more working test. Hope that's fine :)

That means that something is wrong with static initialization of the binary and it is better to get to the bottom of it.

@anutosh491
Copy link
Collaborator Author

That means that something is wrong with static initialization of the binary and it is better to get to the bottom of it.

Hmm, I am not sure that's the case. Check this #544 (comment)

@vgvassilev
Copy link
Contributor

That means that something is wrong with static initialization of the binary and it is better to get to the bottom of it.

Hmm, I am not sure that's the case. Check this #544 (comment)

I did.

@anutosh491
Copy link
Collaborator Author

I did.

So basically we sure can run these tests. Looking as to how we can get round this !

@mcbarton
Copy link
Collaborator

Now our emscripten build is good enough to address both these tests. But there is something going wrong with CaptureStdout and/or GetCapturedStdout provided by the emscripten build of gtest.

@anutosh491 Since this PR went in, we updated the version of GoogleTests we are using here #552 . Have you checked that this bug hasn't been fixed in the latest version?

@anutosh491
Copy link
Collaborator Author

Hi,

As I wrote above I would fall short on time to investigate anything related to the emscripten build for gtest :(

As you introduced these set of tests would you like to take charge of fixing it ?

I think the "Evaluate" function is something that should absolutely be tested and not be skipped! (But yeah as Vassil pointed out my workaround might just be a cheap trick to get this done)

@vgvassilev
Copy link
Contributor

We can move forward with the current approach only if we add a fixme in cmake and open a bug report explaining what we know and what needs to be investigated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants