diff --git a/GenerateKeywords.cmake b/GenerateKeywords.cmake index c45abd8c6..b53b29a85 100644 --- a/GenerateKeywords.cmake +++ b/GenerateKeywords.cmake @@ -7,6 +7,7 @@ set(genkw_SOURCES src/opm/json/JsonObject.cpp src/opm/parser/eclipse/Deck/DeckOutput.cpp src/opm/parser/eclipse/Generator/KeywordGenerator.cpp src/opm/parser/eclipse/Generator/KeywordLoader.cpp + src/opm/parser/eclipse/Parser/ErrorGuard.cpp src/opm/parser/eclipse/Parser/ParseContext.cpp src/opm/parser/eclipse/Parser/ParserEnums.cpp src/opm/parser/eclipse/Parser/ParserItem.cpp diff --git a/opm/parser/eclipse/Parser/ErrorGuard.hpp b/opm/parser/eclipse/Parser/ErrorGuard.hpp index 49e2e635f..053f5d156 100644 --- a/opm/parser/eclipse/Parser/ErrorGuard.hpp +++ b/opm/parser/eclipse/Parser/ErrorGuard.hpp @@ -41,9 +41,9 @@ public: */ ~ErrorGuard(); void terminate() const; + void dump() const; private: - void dump() const; std::vector> error_list; std::vector> warning_list; diff --git a/opm/parser/eclipse/Parser/InputErrorAction.hpp b/opm/parser/eclipse/Parser/InputErrorAction.hpp index ead1f9888..ae07efaa7 100644 --- a/opm/parser/eclipse/Parser/InputErrorAction.hpp +++ b/opm/parser/eclipse/Parser/InputErrorAction.hpp @@ -37,7 +37,8 @@ namespace Opm { THROW_EXCEPTION = 0, WARN = 1, IGNORE = 2, - EXIT1 = 3 + EXIT1 = 3, + DELAYED_EXIT1 = 4 }; } } diff --git a/src/opm/parser/eclipse/Parser/ErrorGuard.cpp b/src/opm/parser/eclipse/Parser/ErrorGuard.cpp index fbc14f529..57395d617 100644 --- a/src/opm/parser/eclipse/Parser/ErrorGuard.cpp +++ b/src/opm/parser/eclipse/Parser/ErrorGuard.cpp @@ -55,7 +55,7 @@ namespace Opm { void ErrorGuard::terminate() const { this->dump(); - std::terminate(); + std::exit(1); } diff --git a/src/opm/parser/eclipse/Parser/ParseContext.cpp b/src/opm/parser/eclipse/Parser/ParseContext.cpp index 0643444df..5a6f4ef34 100644 --- a/src/opm/parser/eclipse/Parser/ParseContext.cpp +++ b/src/opm/parser/eclipse/Parser/ParseContext.cpp @@ -102,6 +102,8 @@ namespace Opm { envUpdate( "OPM_ERRORS_IGNORE" , InputError::IGNORE ); envUpdate( "OPM_ERRORS_EXIT1", InputError::EXIT1); envUpdate( "OPM_ERRORS_EXIT", InputError::EXIT1); + envUpdate( "OPM_ERRORS_DELAYED_EXIT1", InputError::DELAYED_EXIT1); + envUpdate( "OPM_ERRORS_DELAYED_EXIT", InputError::DELAYED_EXIT1); } @@ -117,22 +119,38 @@ namespace Opm { InputError::Action action = get( errorKey ); - if (action == InputError::WARN) { - OpmLog::warning(msg); + if (action == InputError::IGNORE) { + errors.addWarning(errorKey, msg); return; } - else if (action == InputError::THROW_EXCEPTION) { + if (action == InputError::WARN) { + OpmLog::warning(msg); + errors.addWarning(errorKey, msg); + return; + } + + if (action == InputError::THROW_EXCEPTION) { OpmLog::error(msg); + // If we decide to throw immediately - we clear the error stack to + // make sure the error object does not terminate the application + // when it goes out of scope. + errors.clear(); throw std::invalid_argument(errorKey + ": " + msg); } - else if (action == InputError::EXIT1) { + if (action == InputError::EXIT1) { OpmLog::error(msg); std::cerr << "A fatal error has occured and the application will stop." << std::endl; std::cerr << msg << std::endl; std::exit(1); } + + if (action == InputError::DELAYED_EXIT1) { + OpmLog::error(msg); + errors.addError(errorKey, msg); + return; + } } void ParseContext::handleUnknownKeyword(const std::string& keyword, ErrorGuard& errors) const { diff --git a/tests/parser/ParseContext_EXIT1.cpp b/tests/parser/ParseContext_EXIT1.cpp index 0e08247ae..2186320ad 100644 --- a/tests/parser/ParseContext_EXIT1.cpp +++ b/tests/parser/ParseContext_EXIT1.cpp @@ -7,19 +7,19 @@ #include -void exit1() { - const char * deckString = - "RUNSPEC\n" - "DIMENS\n" - " 10 10 10 10 /n" - "\n"; +void exit1(Opm::InputError::Action action) { + const char * deckString = + "RUNSPEC\n" + "DIMENS\n" + " 10 10 10 10 /n" + "\n"; - Opm::ParseContext parseContext; - Opm::Parser parser; - Opm::ErrorGuard errors; + Opm::ParseContext parseContext; + Opm::Parser parser; + Opm::ErrorGuard errors; - parseContext.update(Opm::ParseContext::PARSE_EXTRA_DATA , Opm::InputError::EXIT1 ); - parser.parseString( deckString , parseContext, errors ); + parseContext.update(Opm::ParseContext::PARSE_EXTRA_DATA , action); + parser.parseString( deckString , parseContext, errors ); } @@ -31,21 +31,26 @@ void exit1() { this test is implemented without the BOOST testing framework. */ -int main() { +void test_exit(Opm::InputError::Action action) { pid_t pid = fork(); if (pid == 0) - exit1(); + exit1(action); int wait_status; waitpid(pid, &wait_status, 0); - if (WIFEXITED(wait_status)) + if (WIFEXITED(wait_status)) { /* - We *want* the child process to terminate with status exit(1), here we - capture the exit status of the child process, and then we invert that - and return the inverted status as the status of the complete test. + We *want* the child process to terminate with status exit(1), i.e. if + the exit status is 0 we fail the complete test with exit(1). */ - std::exit( !WEXITSTATUS(wait_status) ); - else + if (WEXITSTATUS(wait_status) == 0) + std::exit(EXIT_FAILURE); + } else std::exit(EXIT_FAILURE); } + +int main(int argc, char ** argv) { + test_exit(Opm::InputError::Action::EXIT1); + test_exit(Opm::InputError::Action::DELAYED_EXIT1); +} diff --git a/tests/parser/integration/EDITNNCTests.cpp b/tests/parser/integration/EDITNNCTests.cpp index a1478640d..4dec620ad 100644 --- a/tests/parser/integration/EDITNNCTests.cpp +++ b/tests/parser/integration/EDITNNCTests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(noNNC) BOOST_AUTO_TEST_CASE(readDeck) { Parser parser; - auto deck = parser.parseFile(pathprefix() + "NNC/noNNC.DATA"); + auto deck = parser.parseFile(pathprefix() + "EDITNNC/EDITNNC.DATA"); EclipseState eclipseState(deck); const auto& editnnc = eclipseState.getInputEDITNNC(); BOOST_CHECK(!editnnc.empty());