Catch2 icon indicating copy to clipboard operation
Catch2 copied to clipboard

Misleading error reporting when a CHECK calls a REQUIRE

Open brevzin opened this issue 6 years ago • 9 comments

Description

If a CHECK() assertion internally calls a function that does a REQUIRE() assertion that fails, we get a very misleading message.

Steps to reproduce

Here is the complete test:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

int foo(int i) {
    REQUIRE(i > 10);
    return 42;
}

TEST_CASE("a", "[a]") {
    CHECK(foo(2) == 2);
}

Compiled with -std=c++11 and no other flags, run with no arguments. This emits:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a is a Catch v2.2.2 host application.
Run with -? for options

-------------------------------------------------------------------------------
a
-------------------------------------------------------------------------------
test.cxx:9
...............................................................................

test.cxx:5: FAILED:
  REQUIRE( i > 10 )
with expansion:
  2 > 10

test.cxx:10: FAILED:
  CHECK( foo(2) == 2 )
due to unexpected exception with message:
  Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE

===============================================================================
test cases: 1 | 1 failed
assertions: 2 | 2 failed

Note the message about CATCH_CONFIG_FAST_COMPILE - which isn't actually defined here. This is super confusing.

Extra information

  • Catch version: v2.2.2, Generated: 2018-04-06 12:05:03.186665
  • Operating System: Cygwin on Windows
  • Compiler+version: gcc 6.4.0

brevzin avatar May 19 '18 21:05 brevzin

what an interesting find! the doctest testing framework has the same issue - thanks for reporting!

onqtam avatar May 20 '18 09:05 onqtam

Yeah, I can see how that output would be very confusing.

horenmar avatar Jun 11 '18 20:06 horenmar

I ran in the same problem. CATCH_CONFIG_DISABLE_EXCEPTIONS is not set and I get the same error message. I have 2.8.0 at the moment.

AlexisWilke avatar Jun 22 '19 02:06 AlexisWilke

Hi,

I've found a very similar case, that result in exactly the same misleading error report. I'm using Catch2 together with Trompeloeil for unit testing. When I set an expectation that some method is forbidden to call as (shown in the example below) and then I check whether some expression (that should throw), calls the method, I get the aforementioned misleading error:

  CHECK_THROWS_AS( TestObject(d, true), std::runtime_error )
due to unexpected exception with message:
  Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE

The root cause is the same, my test runner calls CHECK inside CHECK_THROWS ( Use Trompeloeil with Catch2 )

Example test to reproduce

struct Dependency
{
    MAKE_MOCK0(Method, void());
};

struct TestObject
{
    TestObject(Dependency& d, bool condition)
    {
        if (condition)
        {
            // Should throw, but there's a bug...
            // throw std::invalid_argument{"invalid condition"};
        }
        d.Method();
    }
};

TEST_CASE("exception")
{
    Dependency d{};
    FORBID_CALL(d, Method());

    CHECK_THROWS_AS(TestObject(d, true), std::runtime_error);
}

Tested with Catch v2.13.0

slci avatar Jul 22 '20 11:07 slci

I'm also getting this, in my case a REQUIRE() that calls a FAIL() - I configured my logger to fail the test if anything unexpected is outputted to the error stream, so the REQUIRE() assertion calls some code that logs to the error stream which then calls FAIL(). Using v2.7.0 though.

CelticMinstrel avatar Feb 23 '21 20:02 CelticMinstrel

Is there any workaround for this? Other than disabling exceptions...

It keeps randomly popping up in my codebase... sometimes on Linux builds, sometimes on Windows builds only. Happens only on the build server (azure devops).

I have a custom assertion handler that can be configured to throw. REQUIRE_THROWS(MY_ASSERT(false));

So don't even have a nested CHECK/REQUIRE...

Sidelobe avatar Jun 29 '21 09:06 Sidelobe

reproduced today with Catch v2.13.7. CATCH_CONFIG_FAST_COMPILE is not defined

..\tests\src\hardware_cputemp_perf.cpp(281): FAILED:
  REQUIRE( std::get<bool>(targetDevice) )
with expansion:
  false
with message:
  <INFO stuff>

..\tests\src\hardware_cputemp_perf.cpp(281): FAILED:
  REQUIRE_NOTHROW( [&]() { const auto targetDevice = getAvailableDevice(std::chrono::seconds(protocol == X_LINK_TCP_IP ? 60 : 15), protocol); do { ; Catch::AssertionHandler catchAssertionHandler( "REQUIRE"_catch_sr, ::Catch::SourceLineInfo( "..\\tests\\src\\hardware_cputemp_perf.cpp", static_cast<std::size_t>( 281 ) ), "std::get<bool>(targetDevice)", Catch::ResultDisposition::Normal ); try { __pragma( warning(push) ) catchAssertionHandler.handleExpr( Catch::Decomposer() <= std::get<bool>(targetDevice) ); __pragma( warning(pop) ) } catch(...) { catchAssertionHandler.handleUnexpectedInflightException(); } catchAssertionHandler.complete(); } while( (void)0, (false) && static_cast<bool>( !!(std::get<bool>(targetDevice)) ) ); device = std::make_unique<dai::Device>(p, std::get<dai::DeviceInfo>(targetDevice)); }() )
due to unexpected exception with messages:
  <INFO stuff>
  Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE

with code

INFO("<INFO stuff>");
REQUIRE_NOTHROW([&]() {
    const auto targetDevice = getAvailableDevice(std::chrono::seconds(protocol == X_LINK_TCP_IP ? 60 : 15), protocol);
    REQUIRE(std::get<bool>(targetDevice));
    device = std::make_unique<dai::Device>(p, std::get<dai::DeviceInfo>(targetDevice));
}());

diablodale avatar Mar 06 '22 18:03 diablodale

Any update on the issue? Today I ran into the same problem as @slci with trompeloeil mocking framework and was scratching my head what is going on. Tested on 2.13.10.

PKua007 avatar Dec 29 '22 18:12 PKua007

Is there any workaround for this? Other than disabling exceptions...

It keeps randomly popping up in my codebase... sometimes on Linux builds, sometimes on Windows builds only. Happens only on the build server (azure devops).

I have a custom assertion handler that can be configured to throw. REQUIRE_THROWS(MY_ASSERT(false));

So don't even have a nested CHECK/REQUIRE...

Any update or workaround for this? It keeps randomly re-appearing in my CI builds .. this time on Windows builds (x64 & arm64) , but only in Release

Sidelobe avatar Dec 18 '23 15:12 Sidelobe