diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index b588c327a..a48e525d4 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -179,15 +179,8 @@ namespace Opm { if (unsupportedModifiers.find( keyword->name() ) != unsupportedModifiers.end()) { - auto action = parseMode.unsupportedScheduleGeoModifiers; - - if (action != InputError::IGNORE) { - std::string msg = "OPM does not support grid property modifier " + keyword->name() + " in the Schedule section. Error at report: " + std::to_string( currentStep ); - if (action == InputError::THROW_EXCEPTION) - throw std::invalid_argument( msg ); - else if (action == InputError::WARN) - OpmLog::addMessage(Log::MessageType::Warning , msg ); - } + std::string msg = "OPM does not support grid property modifier " + keyword->name() + " in the Schedule section. Error at report: " + std::to_string( currentStep ); + parseMode.handleError( ParseMode::UNSUPPORTED_SCHEDULE_GEO_MODIFIER , msg ); } } @@ -243,16 +236,8 @@ namespace Opm { for (const auto record : (*compordKeyword)) { auto methodItem = record->getItem(); if (methodItem->getString(0) != "TRACK") { - auto action = parseMode.unsupportedCOMPORDType; - if (action != InputError::IGNORE) { - std::string msg = "The COMPORD keyword only handles 'TRACK' order. [ParseMode::unsupportedCOMPORDType]"; - - if (action == InputError::THROW_EXCEPTION) - throw std::invalid_argument(msg); - else - OpmLog::addMessage(Log::MessageType::Warning , msg ); - - } + std::string msg = "The COMPORD keyword only handles 'TRACK' order."; + parseMode.handleError( ParseMode::UNSUPPORTED_COMPORD_TYPE , msg ); } } } diff --git a/opm/parser/eclipse/EclipseState/SimulationConfig/ThresholdPressure.cpp b/opm/parser/eclipse/EclipseState/SimulationConfig/ThresholdPressure.cpp index f5a6ee9d4..2cfbd3215 100644 --- a/opm/parser/eclipse/EclipseState/SimulationConfig/ThresholdPressure.cpp +++ b/opm/parser/eclipse/EclipseState/SimulationConfig/ThresholdPressure.cpp @@ -104,14 +104,8 @@ namespace Opm { m_thresholdPressureTable[r1 + maxEqlnum*r2] = p; m_thresholdPressureTable[r2 + maxEqlnum*r1] = p; } else { - auto action = parseMode.unsupportedInitialTHPRES; - if (action != InputError::IGNORE) { - std::string msg = "Inferring threshold pressure from the initial state is not supported. [ParseMode::unsupportedInitialTHPRES]"; - if (action == InputError::THROW_EXCEPTION) - throw std::invalid_argument( msg ); - else - OpmLog::addMessage(Log::MessageType::Warning , msg ); - } + std::string msg = "Inferring threshold pressure from the initial state is not supported."; + parseMode.handleError( ParseMode::UNSUPPORTED_INITIAL_THPRES , msg ); } } else throw std::runtime_error("Missing region data for use of the THPRES keyword"); diff --git a/opm/parser/eclipse/EclipseState/SimulationConfig/tests/ThresholdPressureTest.cpp b/opm/parser/eclipse/EclipseState/SimulationConfig/tests/ThresholdPressureTest.cpp index 3dd435650..c9d8f56ad 100644 --- a/opm/parser/eclipse/EclipseState/SimulationConfig/tests/ThresholdPressureTest.cpp +++ b/opm/parser/eclipse/EclipseState/SimulationConfig/tests/ThresholdPressureTest.cpp @@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(ThresholdPressureThrowTest) { BOOST_CHECK_THROW(std::make_shared(parseMode , deck, gridPropertiesEQLNUMall0), std::runtime_error); } - parseMode.unsupportedInitialTHPRES = InputError::IGNORE; + parseMode.update( ParseMode::UNSUPPORTED_INITIAL_THPRES , InputError::IGNORE ); BOOST_CHECK_NO_THROW(ThresholdPressure(parseMode,deck_missingPressure, gridProperties)); } diff --git a/opm/parser/eclipse/IntegrationTests/ParseEQUIL.cpp b/opm/parser/eclipse/IntegrationTests/ParseEQUIL.cpp index d31693abc..0b183f462 100644 --- a/opm/parser/eclipse/IntegrationTests/ParseEQUIL.cpp +++ b/opm/parser/eclipse/IntegrationTests/ParseEQUIL.cpp @@ -39,7 +39,7 @@ using namespace Opm; BOOST_AUTO_TEST_CASE( parse_EQUIL_MISSING_DIMS ) { Parser parser; ParseMode parseMode; - parseMode.missingDIMSKeyword = InputError::IGNORE; + parseMode.update(ParseMode::PARSE_MISSING_DIMS_KEYWORD, InputError::IGNORE); const std::string equil = "EQUIL\n" "2469 382.4 1705.0 0.0 500 0.0 1 1 20 /"; std::shared_ptr deck = parser.parseString(equil, parseMode); diff --git a/opm/parser/eclipse/IntegrationTests/ResinsightTest.cpp b/opm/parser/eclipse/IntegrationTests/ResinsightTest.cpp index 851441e61..2be639deb 100644 --- a/opm/parser/eclipse/IntegrationTests/ResinsightTest.cpp +++ b/opm/parser/eclipse/IntegrationTests/ResinsightTest.cpp @@ -33,9 +33,10 @@ using namespace Opm; BOOST_AUTO_TEST_CASE( test_parse ) { Parser parser(false); ParseMode parseMode; - parseMode.unknownKeyword = InputError::IGNORE; - parseMode.randomText = InputError::IGNORE; - parseMode.randomSlash = InputError::IGNORE; + + parseMode.update( ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::IGNORE ); + parseMode.update( ParseMode::PARSE_RANDOM_TEXT , InputError::IGNORE ); + parseMode.update( ParseMode::PARSE_RANDOM_SLASH , InputError::IGNORE ); parser.addKeyword(); parser.addKeyword(); @@ -50,9 +51,10 @@ BOOST_AUTO_TEST_CASE( test_parse ) { BOOST_AUTO_TEST_CASE( test_state ) { Parser parser(false); ParseMode parseMode; - parseMode.unknownKeyword = InputError::IGNORE; - parseMode.randomText = InputError::IGNORE; - parseMode.randomSlash = InputError::IGNORE; + + parseMode.update( ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::IGNORE ); + parseMode.update( ParseMode::PARSE_RANDOM_TEXT , InputError::IGNORE ); + parseMode.update( ParseMode::PARSE_RANDOM_SLASH , InputError::IGNORE ); parser.addKeyword(); parser.addKeyword(); diff --git a/opm/parser/eclipse/Parser/ParseMode.cpp b/opm/parser/eclipse/Parser/ParseMode.cpp index 65c6c8ed5..34fcb5c64 100644 --- a/opm/parser/eclipse/Parser/ParseMode.cpp +++ b/opm/parser/eclipse/Parser/ParseMode.cpp @@ -17,22 +17,198 @@ along with OPM. If not, see . */ +#include +#include +#include +#include + +#include #include #include namespace Opm { - ParseMode::ParseMode() { - unknownKeyword = InputError::THROW_EXCEPTION; - randomText = InputError::THROW_EXCEPTION; - randomSlash = InputError::THROW_EXCEPTION; - missingDIMSKeyword = InputError::THROW_EXCEPTION; - unsupportedScheduleGeoModifiers = InputError::THROW_EXCEPTION; - unsupportedCOMPORDType = InputError::THROW_EXCEPTION; - unsupportedInitialTHPRES = InputError::THROW_EXCEPTION; + /* + A set of predefined error modes are added, with the default + setting 'InputError::IGNORE, then afterwards the environment + variables 'OPM_ERRORS_EXCEPTION', 'OPM_ERRORS_WARN' and + 'OPM_ERRORS_IGNORE' are consulted + */ + + ParseMode::ParseMode() { + initDefault(); + initEnv(); } + + /* + If you intend to hardwire settings you should use this + constructor, as that way the environment variables are applied + after the hawrdwired settings. + */ + + ParseMode::ParseMode(const std::vector> initial) { + initDefault(); + + for (const auto& pair : initial) + update( pair.first , pair.second ); + + initEnv(); + } + + + void ParseMode::initDefault() { + addKey(PARSE_UNKNOWN_KEYWORD); + addKey(PARSE_RANDOM_TEXT); + addKey(PARSE_RANDOM_SLASH); + addKey(PARSE_MISSING_DIMS_KEYWORD); + addKey(UNSUPPORTED_SCHEDULE_GEO_MODIFIER); + addKey(UNSUPPORTED_COMPORD_TYPE); + addKey(UNSUPPORTED_INITIAL_THPRES); + } + + void ParseMode::initEnv() { + envUpdate( "OPM_ERRORS_EXCEPTION" , InputError::THROW_EXCEPTION ); + envUpdate( "OPM_ERRORS_WARN" , InputError::WARN ); + envUpdate( "OPM_ERRORS_IGNORE" , InputError::IGNORE ); + } + + + void ParseMode::handleError( const std::string& errorKey , const std::string& msg) const { + InputError::Action action = get( errorKey ); + + if (action == InputError::WARN) + OpmLog::addMessage(Log::MessageType::Warning , msg); + else if (action == InputError::THROW_EXCEPTION) + throw std::invalid_argument(errorKey + ": " + msg); + + } + + std::map::const_iterator ParseMode::begin() const { + return m_errorModes.begin(); + } + + + std::map::const_iterator ParseMode::end() const { + return m_errorModes.end(); + } + + + bool ParseMode::hasKey(const std::string& key) const { + if (m_errorModes.find( key ) == m_errorModes.end()) + return false; + else + return true; + } + + + void ParseMode::addKey(const std::string& key) { + if (key.find_first_of("|:*") != std::string::npos) + throw std::invalid_argument("The ParseMode keys can not contain '|', '*' or ':'"); + + if (!hasKey(key)) + m_errorModes.insert( std::pair( key , InputError::THROW_EXCEPTION )); + } + + + InputError::Action ParseMode::get(const std::string& key) const { + if (hasKey( key )) + return m_errorModes.find( key )->second; + else + throw std::invalid_argument("The errormode key: " + key + " has not been registered"); + } + + /*****************************************************************/ + + /* + This is the 'strict' update function, it will throw an exception + if the input string is not a defined error mode. This should + typically be used in a downstream module where the policy + regarding an error mode is hardcoded. When using this method the + static string constanst for the different error modes should be + used as arguments: + + parseMode.updateKey( ParseMode::PARSE_RANDOM_SLASH , InputError::IGNORE ) + + */ + + void ParseMode::updateKey(const std::string& key , InputError::Action action) { + if (hasKey(key)) + m_errorModes[key] = action; + else + throw std::invalid_argument("The errormode key: " + key + " has not been registered"); + } + + + void ParseMode::envUpdate( const std::string& envVariable , InputError::Action action ) { + const char * userSetting = getenv(envVariable.c_str()); + if (userSetting ) + update( userSetting , action); + } + + + void ParseMode::update(InputError::Action action) { + for (const auto& pair : m_errorModes) { + const std::string& key = pair.first; + updateKey( key , action ); + } + } + + + void ParseMode::patternUpdate( const std::string& pattern , InputError::Action action) { + const char * c_pattern = pattern.c_str(); + for (const auto& pair : m_errorModes) { + const std::string& key = pair.first; + if (util_fnmatch( c_pattern , key.c_str()) == 0) + updateKey( key , action ); + } + } + + + /* + This is the most general update function. The input keyString is + "selector string", and all matching error modes will be set to + @action. The algorithm for decoding the @keyString is: + + 1. The input string is split into several tokens on occurences + of ':' or ':' - and then each element is treated + seperately. + + 2. For each element in the list from 1): + + a) If it contains at least one '*' - update all error modes + matching the input string. + + b) If it is exactly equal to recognized error mode - update + that. + + c) Otherwise - silently ignore. + */ + + void ParseMode::update(const std::string& keyString , InputError::Action action) { + std::vector keys; + boost::split( keys , keyString , boost::is_any_of(":|")); + for (const auto& input_key : keys) { + std::vector matching_keys; + size_t wildcard_pos = input_key.find("*"); + + if (wildcard_pos == std::string::npos) { + if (hasKey( input_key )) + updateKey( input_key , action ); + } else + patternUpdate( input_key , action ); + + } + } + + const std::string ParseMode::PARSE_UNKNOWN_KEYWORD = "PARSE_UNKNOWN_KEYWORD"; + const std::string ParseMode::PARSE_RANDOM_TEXT = "PARSE_RANDOM_TEXT"; + const std::string ParseMode::PARSE_RANDOM_SLASH = "PARSE_RANDOM_SLASH"; + const std::string ParseMode::PARSE_MISSING_DIMS_KEYWORD = "PARSE_MISSING_DIMS_KEYWORD"; + const std::string ParseMode::UNSUPPORTED_SCHEDULE_GEO_MODIFIER = "UNSUPPORTED_SCHEDULE_GEO_MODIFIER"; + const std::string ParseMode::UNSUPPORTED_COMPORD_TYPE = "UNSUPPORTED_COMPORD_TYPE"; + const std::string ParseMode::UNSUPPORTED_INITIAL_THPRES = "UNSUPPORTED_INITIAL_THPRES"; } diff --git a/opm/parser/eclipse/Parser/ParseMode.hpp b/opm/parser/eclipse/Parser/ParseMode.hpp index 63d28bf15..d20008434 100644 --- a/opm/parser/eclipse/Parser/ParseMode.hpp +++ b/opm/parser/eclipse/Parser/ParseMode.hpp @@ -21,22 +21,20 @@ #ifndef OPM_PARSE_MODE_HPP #define OPM_PARSE_MODE_HPP +#include +#include +#include + #include namespace Opm { /* - The ParseMode struct is meant to control the behavior of the + The ParseMode class is meant to control the behavior of the parsing and EclipseState construction phase when errors/inconsistencies/... are encountered in the input. - The ParseMode struct should be used as a simple value object, - i.e. apart from the constructor there are no methods - the - object can not 'do anything'. It is perfectly legitimate for - calling scope to manipulate the fields of a parsemode instance - directly. - For each of the possible problems encountered the possible actions are goverened by the InputError::Action enum: @@ -44,11 +42,59 @@ namespace Opm { InputError::WARN InputError::IGNORE + The internal datastructure is a map between string keys and + enum InputError::Action values. The string keys are meant to be + descriptive like: + + "PARSE_RANDOMTEXT" + + + The constructor will consult the env variable + OPM_ERRORS_IGNORE, OPM_ERRORS_WARN and OPM_ERRORS_EXCEPTION + when initializing. The variables should be set as strings of + update syntax. + + update_syntax: The main function for updating the policy of a + parseMode instance is the update() method. That takes a string + as input, and updates the matching flags. The string can + contain wildcards ('* and '?' mathced with fnmatch()) and is + split on ':' or '|' to allow multiple settings to be applied in + one go: + + Just set one variable: + update("PARSE_RANDOM_SLASH" , InputError::IGNORE) + + Ignore all unsupported features: + update("UNSUPPORTED_*" , InputError::IGNORE) + + Set two variables: + update("UNSUPPORTED_INIITIAL_THPRES:PARSE_RANDOM_SLASH" , InputError::IGNORE) + + The update function itself is quite tolerant, and will silently + ignore unknown keys. If you use the updateKey() function only + recognizd keys will be allowed. */ - struct ParseMode { + class ParseMode { + public: ParseMode(); + ParseMode(const std::vector> initial); + void handleError( const std::string& errorKey , const std::string& msg) const; + bool hasKey(const std::string& key) const; + void updateKey(const std::string& key , InputError::Action action); + void update(InputError::Action action); + void update(const std::string& keyString , InputError::Action action); + InputError::Action get(const std::string& key) const; + std::map::const_iterator begin() const; + std::map::const_iterator end() const; + /* + When the key is added it is inserted in 'strict mode', + i.e. with the value 'InputError::THROW_EXCEPTION. If you + want a different value you must subsequently call the update + method. + */ + void addKey(const std::string& key); /* The unknownKeyword field regulates how the parser should react when it encounters an unknwon keyword. Observe that @@ -72,21 +118,20 @@ namespace Opm { subsequent piece of 'random text' might not be identified correctly as such. */ - InputError::Action unknownKeyword; - + const static std::string PARSE_UNKNOWN_KEYWORD; /* With random text we mean a string in the input deck is not correctly formatted as a keyword heading. */ - InputError::Action randomText; + const static std::string PARSE_RANDOM_TEXT; /* It turns out that random '/' - i.e. typically an extra slash which is not needed - is quite common. This is therefor a special case treatment of the 'randomText' behaviour. */ - InputError::Action randomSlash; + const static std::string PARSE_RANDOM_SLASH; /* @@ -101,7 +146,7 @@ namespace Opm { Observe that a fully defaulted XXXDIMS keyword does not trigger this behavior. */ - InputError::Action missingDIMSKeyword; + const static std::string PARSE_MISSING_DIMS_KEYWORD; /* Some property modfiers can be modified in the Schedule @@ -112,22 +157,26 @@ namespace Opm { encountered in the Schedule section the behavior is regulated by this setting. */ - InputError::Action unsupportedScheduleGeoModifiers; - + const static std::string UNSUPPORTED_SCHEDULE_GEO_MODIFIER; /* In the COMPORD implementation only the 'TRACK' input mode is supported. */ - InputError::Action unsupportedCOMPORDType; - + const static std::string UNSUPPORTED_COMPORD_TYPE; /* If the third item in the THPRES keyword is defaulted the threshold pressure is inferred from the initial pressure; this currently not supported. */ - InputError::Action unsupportedInitialTHPRES; + const static std::string UNSUPPORTED_INITIAL_THPRES; + private: + void initDefault(); + void initEnv(); + void envUpdate( const std::string& envVariable , InputError::Action action ); + void patternUpdate( const std::string& pattern , InputError::Action action); + std::map m_errorModes; }; } diff --git a/opm/parser/eclipse/Parser/Parser.cpp b/opm/parser/eclipse/Parser/Parser.cpp index 7da829e1a..6de977657 100644 --- a/opm/parser/eclipse/Parser/Parser.cpp +++ b/opm/parser/eclipse/Parser/Parser.cpp @@ -108,24 +108,19 @@ namespace Opm { */ void handleRandomText(const std::string& keywordString ) const { + std::string errorKey; std::stringstream msg; - InputError::Action action; std::string trimmedCopy = boost::algorithm::trim_copy( keywordString ); if (trimmedCopy == "/") { - action = parseMode.randomSlash; + errorKey = ParseMode::PARSE_RANDOM_SLASH; msg << "Extra '/' detected at: " << dataFile << ":" << lineNR; } else { - action = parseMode.randomText; + errorKey = ParseMode::PARSE_RANDOM_TEXT; msg << "String \'" << keywordString << "\' not formatted/recognized as valid keyword at: " << dataFile << ":" << lineNR; } - if (action == InputError::THROW_EXCEPTION) - throw std::invalid_argument( msg.str() ); - else { - if (action == InputError::WARN) - OpmLog::addMessage(Log::MessageType::Warning , msg.str()); - } + parseMode.handleError( errorKey , msg.str() ); } }; @@ -405,17 +400,15 @@ namespace Opm { } targetSize = sizeDefinitionItem->getInt(0); } else { - InputError::Action action = parserState->parseMode.missingDIMSKeyword; - if (action == InputError::THROW_EXCEPTION) - throw std::invalid_argument("Excpeted the kewyord: " + sizeKeyword.first + " to infer the number of records in: " + keywordString); - else { + std::string msg = "Expected the kewyord: " + sizeKeyword.first + " to infer the number of records in: " + keywordString; + parserState->parseMode.handleError(ParseMode::PARSE_MISSING_DIMS_KEYWORD , msg ); + + { auto keyword = getKeyword( sizeKeyword.first ); auto record = keyword->getRecord(0); auto int_item = std::dynamic_pointer_cast( record->get( sizeKeyword.second ) ); targetSize = int_item->getDefault( ); - if (action == InputError::WARN) - OpmLog::addMessage(Log::MessageType::Warning , "Excpeted the kewyord: " + sizeKeyword.first + " to infer the number of records in: " + keywordString + " using default"); } } } @@ -423,14 +416,9 @@ namespace Opm { } } else { if (ParserKeyword::validDeckName(keywordString)) { - InputError::Action action = parserState->parseMode.unknownKeyword; - if (action == InputError::THROW_EXCEPTION) - throw std::invalid_argument("Keyword " + keywordString + " not recognized "); - else { - if (action == InputError::WARN) - OpmLog::addMessage(Log::MessageType::Warning , "Keyword " + keywordString + " not recognized"); - return std::shared_ptr( ); - } + std::string msg = "Keyword " + keywordString + " not recognized "; + parserState->parseMode.handleError( ParseMode::PARSE_UNKNOWN_KEYWORD , msg ); + return std::shared_ptr( ); } else { parserState->handleRandomText( keywordString ); return std::shared_ptr( ); diff --git a/opm/parser/eclipse/Parser/tests/ParseModeTests.cpp b/opm/parser/eclipse/Parser/tests/ParseModeTests.cpp index 8b7ba5a48..44bb79556 100644 --- a/opm/parser/eclipse/Parser/tests/ParseModeTests.cpp +++ b/opm/parser/eclipse/Parser/tests/ParseModeTests.cpp @@ -56,26 +56,26 @@ BOOST_AUTO_TEST_CASE(TestUnkownKeyword) { parser.addKeyword(); - parseMode.unknownKeyword = InputError::THROW_EXCEPTION; + parseMode.update(ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::THROW_EXCEPTION ); BOOST_CHECK_THROW( parser.parseString( deck1 , parseMode ) , std::invalid_argument); - parseMode.unknownKeyword = InputError::IGNORE; + parseMode.update(ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::IGNORE ); BOOST_CHECK_NO_THROW( parser.parseString( deck1 , parseMode ) ); - parseMode.randomText = InputError::IGNORE; - parseMode.unknownKeyword = InputError::THROW_EXCEPTION; + parseMode.update(ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::THROW_EXCEPTION ); + parseMode.update(ParseMode::PARSE_RANDOM_TEXT , InputError::IGNORE ); BOOST_CHECK_THROW( parser.parseString( deck2 , parseMode ) , std::invalid_argument); - parseMode.randomText = InputError::IGNORE; - parseMode.unknownKeyword = InputError::IGNORE; + parseMode.update(ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::IGNORE ); + parseMode.update(ParseMode::PARSE_RANDOM_TEXT , InputError::IGNORE ); BOOST_CHECK_NO_THROW( parser.parseString( deck2 , parseMode ) ); - parseMode.randomText = InputError::THROW_EXCEPTION; - parseMode.unknownKeyword = InputError::IGNORE; + parseMode.update(ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::IGNORE ); + parseMode.update(ParseMode::PARSE_RANDOM_TEXT , InputError::THROW_EXCEPTION ); BOOST_CHECK_THROW( parser.parseString( deck2 , parseMode ) , std::invalid_argument); - parseMode.randomText = InputError::IGNORE; - parseMode.unknownKeyword = InputError::IGNORE; + parseMode.update(ParseMode::PARSE_UNKNOWN_KEYWORD , InputError::IGNORE ); + parseMode.update(ParseMode::PARSE_RANDOM_TEXT , InputError::IGNORE ); BOOST_CHECK_NO_THROW( parser.parseString( deck2 , parseMode ) ); } @@ -95,10 +95,10 @@ BOOST_AUTO_TEST_CASE( CheckMissingSizeKeyword) { parser.addKeyword(); parser.addKeyword(); - parseMode.missingDIMSKeyword = InputError::THROW_EXCEPTION; + parseMode.update( ParseMode::PARSE_MISSING_DIMS_KEYWORD , InputError::THROW_EXCEPTION ); BOOST_CHECK_THROW( parser.parseString( deck , parseMode ) , std::invalid_argument); - parseMode.missingDIMSKeyword = InputError::IGNORE; + parseMode.update( ParseMode::PARSE_MISSING_DIMS_KEYWORD , InputError::IGNORE ); BOOST_CHECK_NO_THROW( parser.parseString( deck , parseMode ) ); } @@ -123,10 +123,10 @@ BOOST_AUTO_TEST_CASE( CheckUnsoppertedInSCHEDULE ) { std::shared_ptr grid = std::make_shared( deck ); std::shared_ptr ioconfig = std::make_shared( "path" ); - parseMode.unsupportedScheduleGeoModifiers = InputError::IGNORE; + parseMode.update( ParseMode::UNSUPPORTED_SCHEDULE_GEO_MODIFIER , InputError::IGNORE ); BOOST_CHECK_NO_THROW( Schedule( parseMode , grid , deck , ioconfig )); - parseMode.unsupportedScheduleGeoModifiers = InputError::THROW_EXCEPTION; + parseMode.update( ParseMode::UNSUPPORTED_SCHEDULE_GEO_MODIFIER , InputError::THROW_EXCEPTION ); BOOST_CHECK_THROW( Schedule( parseMode , grid , deck , ioconfig ), std::invalid_argument ); } @@ -153,14 +153,15 @@ BOOST_AUTO_TEST_CASE(TestRandomSlash) { parser.addKeyword(); parser.addKeyword(); - parseMode.randomSlash = InputError::THROW_EXCEPTION; - parseMode.randomText = InputError::IGNORE; + + parseMode.update(ParseMode::PARSE_RANDOM_SLASH , InputError::THROW_EXCEPTION); + parseMode.update(ParseMode::PARSE_RANDOM_TEXT , InputError::IGNORE); BOOST_CHECK_THROW( parser.parseString( deck1 , parseMode ) , std::invalid_argument); BOOST_CHECK_THROW( parser.parseString( deck2 , parseMode ) , std::invalid_argument); - parseMode.randomSlash = InputError::IGNORE; - parseMode.randomText = InputError::THROW_EXCEPTION; + parseMode.update(ParseMode::PARSE_RANDOM_SLASH , InputError::IGNORE); + parseMode.update(ParseMode::PARSE_RANDOM_TEXT , InputError::THROW_EXCEPTION); BOOST_CHECK_NO_THROW( parser.parseString( deck1 , parseMode ) ); BOOST_CHECK_NO_THROW( parser.parseString( deck2 , parseMode ) ); } @@ -186,9 +187,65 @@ BOOST_AUTO_TEST_CASE(TestCOMPORD) { std::shared_ptr grid = std::make_shared( deck ); std::shared_ptr ioconfig = std::make_shared( "path" ); - parseMode.unsupportedCOMPORDType = InputError::IGNORE; + parseMode.update( ParseMode::UNSUPPORTED_COMPORD_TYPE , InputError::IGNORE); BOOST_CHECK_NO_THROW( Schedule( parseMode , grid , deck , ioconfig )); - parseMode.unsupportedCOMPORDType = InputError::THROW_EXCEPTION; + parseMode.update( ParseMode::UNSUPPORTED_COMPORD_TYPE , InputError::THROW_EXCEPTION); BOOST_CHECK_THROW( Schedule( parseMode , grid , deck , ioconfig ), std::invalid_argument ); } + + +BOOST_AUTO_TEST_CASE(TestInvalidKey) { + ParseMode parseMode; + BOOST_CHECK_THROW( parseMode.addKey("KEY*") , std::invalid_argument ); + BOOST_CHECK_THROW( parseMode.addKey("KEY:") , std::invalid_argument ); +} + + +BOOST_AUTO_TEST_CASE(TestNew) { + ParseMode parseMode; + + BOOST_CHECK_EQUAL( false , parseMode.hasKey("NO")); + parseMode.addKey("NEW_KEY"); + BOOST_CHECK_EQUAL( true , parseMode.hasKey("NEW_KEY")); + BOOST_CHECK_THROW( parseMode.get("NO") , std::invalid_argument ); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY") , InputError::THROW_EXCEPTION ); + parseMode.addKey("KEY2"); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY") , InputError::THROW_EXCEPTION ); + + BOOST_CHECK_THROW( parseMode.updateKey("NO" , InputError::IGNORE) , std::invalid_argument); + + parseMode.updateKey("NEW_KEY" , InputError::WARN); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY") , InputError::WARN ); + + BOOST_CHECK_NO_THROW( parseMode.update("KEY2:NEW_KEY" , InputError::IGNORE)); + BOOST_CHECK_NO_THROW( parseMode.update("UnknownKey" , InputError::IGNORE)); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY") , InputError::IGNORE ); + BOOST_CHECK_EQUAL( parseMode.get("KEY2") , InputError::IGNORE ); + + parseMode.addKey("SECRET_KEY"); + parseMode.addKey("NEW_KEY2"); + parseMode.addKey("NEW_KEY3"); + parseMode.update("NEW_KEY*" , InputError::WARN); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY") , InputError::WARN ); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY2") , InputError::WARN ); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY3") , InputError::WARN ); + + parseMode.update( InputError::IGNORE ); + BOOST_CHECK_EQUAL( parseMode.get("NEW_KEY3") , InputError::IGNORE ); + BOOST_CHECK_EQUAL( parseMode.get("SECRET_KEY") , InputError::IGNORE ); + + +} + + +BOOST_AUTO_TEST_CASE( test_constructor_with_values) { + ParseMode parseMode( {{ParseMode::PARSE_RANDOM_SLASH , InputError::IGNORE}, + {"UNSUPPORTED_*" , InputError::WARN}, + {"UNKNWON-IGNORED" , InputError::WARN}}); + + BOOST_CHECK_EQUAL( parseMode.get(ParseMode::PARSE_RANDOM_SLASH) , InputError::IGNORE ); + BOOST_CHECK_EQUAL( parseMode.get(ParseMode::PARSE_RANDOM_TEXT) , InputError::THROW_EXCEPTION ); + BOOST_CHECK_EQUAL( parseMode.get(ParseMode::UNSUPPORTED_INITIAL_THPRES) , InputError::WARN ); + BOOST_CHECK_EQUAL( parseMode.get(ParseMode::UNSUPPORTED_COMPORD_TYPE) , InputError::WARN ); +}