-
Notifications
You must be signed in to change notification settings - Fork 536
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
assert(false) not failing in tests but it should #3102
Comments
Ah I think this explains what I'm seeing in #3103. After looking at the code I concluded the same thing -- the latter part of that test should be consistently failing, but only does so on the pipeline and not locally. I've fixed that test by updating the transforms, but that is concerning. I'm glad I wasn't going insane 😅 |
It appears to be a macro variable defined by cmake depending on the CMAKE_BUILD_TYPE argument. I'll try building with these options and check the test results |
The tests pass after building with the former, and fail (expectedly) after building with the latter. It feels like very unintuitive behavior (though I suppose these are the kinds of issues that crop up when using three build systems stacked together in a trench coat 😛 ) Maybe -DBUILD_TESTING=ON should set -DCMAKE_BUILD_TYPE=Debug by default? |
I don't think we want to default to Debug - that will likely slow things down considerably since you don't get optimizations with that (for some things it can be catastrophic - I remember at one point we determined that the sensor_msgs::PointCloudIterator is about 300x slower in Debug than in Release/RelWithDebInfo) |
The alternative is that failing tests pass, which also feels catastrophic. In your example, are you wanting to set |
@sea-bass I'm thinking of addressing this by replacing all asserts with exceptions, such that they can't be accidentally disabled by build type. What's the general policy on using std::runtime_error vs custom exception types? |
Actually, to avoid breaking behaviour it might make more sense to print an error, and let the tests use ASSERT_TRUE. That way, users making use of assert-based functions won't be presented with a bunch of new exceptions to catch |
It looks like there are 106 usages of assert across 31 files. It also seems that assert calls It might be nicest to define a macro which provides identical behaviour, minus the turn-off with NDEBUG, and simply do a find and replace. something like: // We avoid calling `assert` directly, as some tests rely on these calls.
// `assert` is disabled automatically by CMake when the build type is
// Release, which can cause failing tests to pass. See #3102
#define ALWAYS_ASSERT(condition) \
if (!condition) { \
std::err << "Assertion '" << #condition << "' failed." << std::endl; \
std::abort(); \
} My preprocessor knowledge is a little rusty 😅 I believe this preserves
@sea-bass what do you think? Edit: I think there are a few cases where the code does |
I might let @henningkayser chime in on this one... it may be beyond my knowledge of computers :) |
So, I can see changing asserts in tests - but we should be very careful about doing this sort of change outside the tests. Typically, the "it goes away in release mode" is actually a feature that someone intended when they use an assert - especially in high performance code. For the particular assert() you called out in RobotState - developers would want to verify they never have dirty transforms when they are creating a new feature, but at run time these RobotState functions get called many times during each plan generation and the overhead of always checking transforms can significantly slow down planning. Remember, you aren't just adding in the assert boolean check here - you're also adding the whole call to checkLinkTransforms() - because in release mode that function call is currently being removed entirely. Actionable thoughts:
|
Does building with |
For the CI, we could do something like start with |
Would it be possible to use macros to determine if a build-type-dependent call is being made as part of a test, and produce a warning if this is the case? I feel like this would help developers understand these effects when writing tests, and prompt them to design the tests to use functionality that is globally available? (this is unrelated to the CI jobs, but based on the responses I think I agree that using Debug is the best option if possible) |
Regarding point 2, I've been wanting to create a Getting Started guide for new developers (see https://github.com/orgs/moveit/discussions/3096). Feedback would be appreciated! |
I fully agree with #3102 (comment):
To evaluate those tests in CI we have moveit2/.github/workflows/ci.yaml Line 56 in 2490e51
|
@rhaschke This is causing failing tests slip through the cracks between PR CI and main CI though, due to a difference in the build type. See for example this CI job on main and the corresponding jobs on the associated PR. I agree that To me, this is more of an issue of incorrect test design, and I think in these situations we should print a warning to make it clear that the test will have unreliable behavior (though I'm unsure quite how this would be implemented). |
The problem is that ccov-testing was disabled in #2866, which is why there is no Debug build run on PRs anymore. There is no need to change code, but just re-enable ccov/debug testing for PRs. |
Ahh I see, and thank you for looking into those issues 👍 Would you agree that it's a bad testing practice to be using Debug dependent code indirectly in tests? My assumption was that it's valid to want to run tests with a Release build (and reasonable to expect them to behave identically), I'd still argue the latter point -- provided the former -- but I suppose Release does imply post-development (and testing), so maybe this assumption is incorrect. |
Description
Public service announcement: I tried building from source to make some slight changes. I determined by running the tests that
assert(false)
was not failing though it should. One test in particular [0] callsstate.getRigidlyConnectedParentLinkModel(...)
successfully though it should fail since there are dirty link transforms and that method internally callsassert(checkLinkTransforms())
[1]. Since that second method should return false, the test should fail, but it is currently passing.Looking further I found that
assert()
relies on theNDEBUG
macro being undefined to work correctly. IfNDEBUG
is defined, the assertion is disabled, andassert()
does nothing [2]. I wrote some test code to determine ifNDEBUG
is defined, and it is -- though I cannot determine where.This is causing the CI tests to run in such a way that
assert(false)
statements are silently passing, which is not good. Probably there are not many of these, but the one I linked to should fail.[0] https://github.com/moveit/moveit2/blob/main/moveit_core/robot_state/test/robot_state_test.cpp#L785
[1] https://github.com/moveit/moveit2/blob/main/moveit_core/robot_state/src/robot_state.cpp#L1309
[2] https://en.cppreference.com/w/cpp/error/assert
ROS Distro
Rolling
OS and version
Ubuntu 24.04
Source or binary build?
Source
If binary, which release version?
No response
If source, which branch?
main
Which RMW are you using?
None
Steps to Reproduce
Run the test I mentioned.
Expected behavior
The test should fail.
You can force it to fail by putting this at the top of the test I mentioned [0], put this at the top to make
NDEBUG
undefined. Then run the test and it will fail.[0] https://github.com/moveit/moveit2/blob/main/moveit_core/robot_state/test/robot_state_test.cpp#L785
If you want to fix that particular test so it doesn't fail when NDEBUG is undefined, call this just before the line that is failing:
Actual behavior
The test does not currently fail.
Backtrace or Console output
No response
The text was updated successfully, but these errors were encountered: