Improve unit test parser error handling#6933
Conversation
|
jenkins build this please |
There was a problem hiding this comment.
Pull request overview
This PR improves unit-test diagnostics when Eclipse deck parsing fails by avoiding std::exit() (which bypasses Boost.Test) and ensuring parser errors are actually emitted to stderr during tests.
Changes:
- Add an optional
throwOnErrorparameter toOpm::readDeck()andFlowGenericVanguard::readDeck()to throwstd::runtime_errorinstead of callingstd::exit(). - Register an
OpmLogstderr backend in relevant test fixtures so parser diagnostics are visible in unit test output. - Enable
throwOnErrorinSimulatorFixture,test_equil, andtest_RestartSerialization.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_equil.cpp | Enables throwOnError and adds stderr logging backend in the test fixture. |
| tests/test_RestartSerialization.cpp | Enables throwOnError across restart serialization tests and adds stderr logging backend. |
| tests/SimulatorFixture.hpp | Adds stderr logging backend and enables throwOnError for simulator-based tests. |
| opm/simulators/utils/readDeck.hpp | Extends readDeck() API with throwOnError (default false). |
| opm/simulators/utils/readDeck.cpp | Implements throwOnError by throwing instead of finalizing + exiting. |
| opm/simulators/flow/FlowGenericVanguard.hpp | Extends FlowGenericVanguard::readDeck() API with throwOnError (default false). |
| opm/simulators/flow/FlowGenericVanguard.cpp | Plumbs throwOnError through to Opm::readDeck(). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
|
I'll be honest, I think this is a lot of complexity for a very narrow use case. There aren't supposed to be parse errors in the unit tests. |
@bska It has happened to me several times when adding unit tests with new datafiles to PRs, and then it is very confusing to track down what is happening. |
Then don't add them as unit test until you've verified that there are no parse errors. You don't need MPI support for that. |
When readDeck() encounters parse errors in unit tests, it calls std::exit(1) which bypasses Boost.Test entirely, producing a silent failure with no error message (OpmLog has no backend in tests). Add a throwOnError parameter to readDeck() that throws std::runtime_error instead of calling std::exit(1). Register an OpmLog stderr backend in test fixtures so parser diagnostics are visible. Enable both in SimulatorFixture, test_equil, and test_RestartSerialization.
3104e26 to
a9d58b3
Compare
|
jenkins build this please |
|
@bska Thanks for the feedback. A few thoughts:
If you feel |
The number of lines is the only salient point of this. You're adding a conditional, to a function that's already heavily nested, that will never be needed in a real simulation run yet you're asking every simulation run to pay for that complexity.
Checking if the data file is okay amounts to having something like BOOST_AUTO_TEST_CASE(Check_Data_File)
{
const auto deck = Parser{}.parseFile(your_filename_here);
}and if you're developing the test you're already in the context of a set of unit tests it doesn't cost anything to have that. You can even put logging there if needed. |
|
Not judging the merits of this PR here, but it made me wonder: why do we exit() instead of throw from readDeck() in the first place? Normally I would assume that throwing is what we want to do. Edit: ... and would this not be dealt with by the ParseContext and ErrorGuard? |
@atgeirr Good question. I looked into this,
So I agree that throwing is the right thing to do here. I've opened #6935 as a simpler alternative to this PR. It just replaces |
All of this was introduced in #2785 and whatever we do we need to be sure that we don't reintroduce the problems that prompted that change. |
@bska Thanks for the pointer to #2785. I've reviewed it and the underlying issue #2764. The problem #2785 solved was that Both #6933 and the simpler alternative #6935 preserve all of #2785's improvements. #6933 adds an optional |
No, it was not. there was a hard MPI_Abort there before, which caused logging multiple times and with that PR this is done only once via MPI_Finalize and exit. The exit s there to have a proper return code from the program for calling scripts. |
|
I do think that the subject of this PR does not reflect the real problem that this PR reveals: MPI_Finalize needs to be called on all processes and this is not the case anymore for reservoir coupling which parses different decks where only some of them might have errors. Maybe it is time to test coupling with some decks being erroneous now before really fixing and merging this. Hence I think we need to resolve this and this PR might be a good first step. |
As far as this PR is concerned which talks about removing |
We're not merging this. The follow-up alternative in #6935 is a much better approach. |
I disagree. If you know that all the processes get there MPI_Finalize is the correct and clean way. This was the case here. |
@blattms I've created a test case for this scenario in #6951. It runs a reservoir coupling master that spawns a slave whose DATA file has a deliberate parse error (missing INCLUDE file). The slave exits immediately after the parse failure, but the master hangs on The test currently passes by detecting the expected (broken) behavior:
The plan for a follow-up PR is to have the slave send a "parse failed" signal as its first MPI message after spawn (before |
Problem
When
readDeck()encounters parse errors in unit tests, it callsstd::exit(1)which bypassesBoost.Testentirely. This produces a silent failure (exit code 1, no error message) because:OpmLoghas no registered backend in test fixtures, so error messages are discardedstd::exit()skips Boost.Test's exception handling, so no test failure is reportedSolution
throwOnErrorparameter toreadDeck()andFlowGenericVanguard::readDeck()(defaults tofalsefor backward compatibility)std::runtime_errorwith the failure message instead of callingstd::exit(1)OpmLogstderr backend in test fixture constructors so parser diagnostics are printedSimulatorFixture,test_equil, andtest_RestartSerializationBefore / after
std::runtime_errorwith messagethrowOnErrordefaults tofalse)