Comments (4)
I think the issue may be that the REQUIRE macro ends up evaluating the expression twice. One of the calls is failing, and one of the calls is successful.
I made a simple test to check this, and I get the same behavior:
#include "catch_with_main.hpp"
TEST_CASE("catch/require", "Test if require evaluates expressions twice")
{
int i = 1;
REQUIRE(--i == 0);
}
from catch2.
Looked into this a little more, the two times the expression is evaluated appears to be (the first time) at the call to
template<typename T> ResultBuilder& ResultBuilder::operator->*(const T & operand)
The second time would be the call to
virtual ResultAction::Value Runner::acceptResult(bool Result)
A fix for this isn't immediately obvious to me. I would consider the 'acceptResult' call to be extraneous if it would be possible to evaluate the result solely in the ResultBuilder. This would require a few changes to how the ResultBuilder parses expressions though, it would have to save the result data as well as the stringized version of each operand, then evaluate it once the expression is complete.
I noticed that at the moment ResultBuilder doesn't parse past a binary operator such as && or ||, and I think the fix to both of these things could be combined together.
from catch2.
Hi Tryneus.
It is indeed the double evaluation issue.
It's been on my list for a while to come back and look at.
You're the second person to hit this within a week - so I'll take that as a prompt to work on it next ;-)
As for how it can be worked around I have two ideas:
- The first is along the lines you suggested too. The ResultBuilder can capture the native values as well as the stringised ones - then recombined into the original comparison once it has both sides. There were a few reasons why I didn't do it this way in the first place - but I think the repeated evaluation side-effect is more pernicious.
- An alternative I have toyed with the idea of is to run the whole test case for a second pass in the event of failure. The first pass would evaluate the expressions and the second pass would capture the decomposed parts. I'm not sure if this will introduce non-trivial overhead in some cases, have other side-effects or problems of its own.
Either way, looking at what you're doing suggests you're testing multi-threaded code. Is that the case? I don't currently support multiple-threads explicitly - although if the test code is confined to the calling thread there shouldn't be any issues.
from catch2.
I am indeed working with multi-threaded stuff, but when I was using CppUnit on a previous project, I learned to leave test framework calls out of the children threads. If there is a problem in the thread, it will throw an exception which is captured into a string that can be checked later in the main thread.
I've been investigating a fix for the multiple evaluation behavior, I'll try uploading it on a fork if I get it working. It's basically your alternative 1. Also to correct what I said earlier, I now realize that due to operator precedence, it isn't really possible to parse past && or ||.
I suppose it's too early to describe the changes I'm making because I'm not entirely sure if it will work, but I'll update this once I know.
from catch2.
Related Issues (20)
- Update documentation for v3 HOT 2
- Provide Catch2's StringMaker specialization behind extra level of indirection
- Handle ANSI escape sequences during text wrapping
- Bring back Single-Header capability HOT 2
- AddressSanitizer reports container overflow during benchmarking HOT 3
- Latest macOS system header causes compilation failures on GCC HOT 4
- Compilation fails with `error: arithmetic on a pointer to an incomplete type` HOT 1
- Combine test filters with filenames HOT 2
- Section filter command line option only works for sections without whitespace in name HOT 1
- Separate headers for "extra" std types
- Catch2 does not appear to work with C++23
- version 3.5.4 does not compile
- JUnit and console reporter discrepency.
- Provide means to obtain current test case name and current section name HOT 1
- GENERATOR doesn't allow use constants HOT 1
- Memory leak when using exit()
- Compile Error While using Catch::Clara::Parser HOT 1
- Allow the Catch2 library to be compiled with address sanitizer enabled
- Fixture's destructor called before retrieving uncaught exception's message
- How does (can) auto-registration work?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from catch2.