Skip to content
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

Throwing exception in a mocked method #265

Closed
killkrt opened this issue Aug 9, 2019 · 6 comments
Closed

Throwing exception in a mocked method #265

killkrt opened this issue Aug 9, 2019 · 6 comments

Comments

@killkrt
Copy link

killkrt commented Aug 9, 2019

Description

I am mocking a method in order to raise an exception (using Trompeloeil) and I want to check if its caller protect itself catching the exception correctly.

Steps to reproduce

This is a very simplified version of my code:

struct Foo
{
    virtual void mayThrow() = 0;
    
    virtual bool throwerCaller()
    {
        bool res = false;
        try
        {
            mayThrow();
            res = true;
        }
        catch(...)
        {
            res = false;
        }
        return res;
    }
}

The test should check whether the method mayThrow throws an exception, its caller method (throwerCaller) returns false.

    struct MockedFoo : Foo
    {
         MAKE_MOCK0( mayThrow(), void() );
    };

    TEST_CASE("Foo")
    {
         MockedFoo foo;
         foo.REQUIRE_CALL( foo, mayThrow() ).THROW( std::exception() );
         CHECK_FALSE( foo.throwerCaller() );
         // Even using CHECK_THROWS_AS( foo.throwCaller(), const std::exception& ) works
    }

Running this code it will abort due to a crash:

FATAL ERROR: test case CRASHED: SIGABRT - Abort (abnormal termination) signal

Not sure that this is an issue of Doctest or Trompeloeil.

  • doctest version: 2.3.3
  • Operating System: macOS 10.14.6
  • Compiler+version: clang-1001.0.46.4
@onqtam
Copy link
Member

onqtam commented Aug 11, 2019

well this is printed by the doctest framework - it has intercepted a SIGABRT signal... You could try defining DOCTEST_CONFIG_NO_POSIX_SIGNALS before including doctest in the entire test binary - that will disable signal catching on UNIX and you'll get the original SIGABRT message - virtual functions could be the reason for SIGABRT - here is one example of how you could shoot yourself in the foot with virtual functions and constructors/destructors: https://rextester.com/JVBF97486

I don't know enough about Trompeloeil but I doubt that this issue is related to doctest.

@killkrt
Copy link
Author

killkrt commented Aug 11, 2019

Thank you for the reply.

Anyway, that's strange, since my method throwerCaller is wrapping the call to mayThow with a try{} catch{}, so no exception should be propagated.

Uhm... Maybe it's a Trompeloeil issue?

@onqtam
Copy link
Member

onqtam commented Aug 11, 2019

I don't know... Did you try defining DOCTEST_CONFIG_NO_POSIX_SIGNALS so doctest doesn't capture the signals on its own? Have you tried stepping through the code with a debugger to see on which line the crash happens? Or perhaps even printf-debugging - logging messages between the lines?

@killkrt
Copy link
Author

killkrt commented Aug 11, 2019

I tried and now it's failing with another error:

The output from the failed tests:

1/1 automatictests                          FAIL     0.37 s (killed by signal 6 SIGABRT)

--- command ---
/.../build/tests/automatictests
--- stderr ---
terminate called after throwing an instance of 'std::exception'
  what():  std::exception
-------

I debugged the code and it crash as it calls mayThrow even if it is wrapped by a try-catch.
This is the real code:

        try
        {
            // Stop should not fail!
            stop(); //  <-- Crash here when this mocked method is throwing an exception
            state = CommunicationState::Stop;
        }
        catch ( const std::exception& exc )
        {
            // Logging error here, anyway this code is never executed
        }
        catch ( ... )
        {
            // Logging error here, anyway this code is never executed
        }

@onqtam
Copy link
Member

onqtam commented Aug 12, 2019

I don't think this is related to doctest - you could try to separate this from the doctest stuff and try to reproduce it in a simple main() function. I also don't have experience with mocking frameworks - you could ask this in the issues section of Trompeloeil - and make sure to include the entire code and not separate snippets, so it's easier to understand. Sorry for not being able to help.

@killkrt
Copy link
Author

killkrt commented Aug 12, 2019

@onqtam you have been very supportive and kind.

I've followed your hint and I tried to rewrite the test bypassing Trompeloeil (so implementing manually a mocked class) and it works as expected, so I guess that there is something that I'm missing in Trompeloeil.

Thank your patience and I'm sorry wasted your time.

@killkrt killkrt closed this as completed Aug 12, 2019
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

No branches or pull requests

2 participants