diff --git a/rwgame/GameConfig.cpp b/rwgame/GameConfig.cpp index 89291e24..b781c123 100644 --- a/rwgame/GameConfig.cpp +++ b/rwgame/GameConfig.cpp @@ -1,16 +1,16 @@ #include "GameConfig.hpp" -#include -#include +#include + #include -#include #include +#include namespace pt = boost::property_tree; const std::string kConfigDirectoryName("OpenRW"); -GameConfig::GameConfig(const std::string& configName, - const std::string& configPath) +GameConfig::GameConfig(const std::string &configName, + const std::string &configPath) : m_configName(configName) , m_configPath(configPath) , m_parseResult() @@ -23,7 +23,8 @@ GameConfig::GameConfig(const std::string& configName, auto configFile = getConfigFile(); std::string dummy; - m_parseResult = parseConfig(ParseType::FILE, configFile, ParseType::CONFIG, dummy); + m_parseResult = + parseConfig(ParseType::FILE, configFile, ParseType::CONFIG, dummy); } std::string GameConfig::getConfigFile() const { @@ -41,17 +42,17 @@ const GameConfig::ParseResult &GameConfig::getParseResult() const { std::string GameConfig::getDefaultConfigPath() { #if defined(RW_LINUX) || defined(RW_FREEBSD) || defined(RW_NETBSD) || \ defined(RW_OPENBSD) - char* config_home = getenv("XDG_CONFIG_HOME"); + char *config_home = getenv("XDG_CONFIG_HOME"); if (config_home != nullptr) { return std::string(config_home) + "/" + kConfigDirectoryName; } - char* home = getenv("HOME"); + char *home = getenv("HOME"); if (home != nullptr) { return std::string(home) + "/.config/" + kConfigDirectoryName; } #elif defined(RW_OSX) - char* home = getenv("HOME"); + char *home = getenv("HOME"); if (home) return std::string(home) + "/Library/Preferences/" + kConfigDirectoryName; @@ -67,7 +68,7 @@ std::string GameConfig::getDefaultConfigPath() { std::string stripComments(const std::string &str) { auto s = std::string(str, 0, str.find_first_of(";#")); - return s.erase(s.find_last_not_of(" \n\r\t")+1); + return s.erase(s.find_last_not_of(" \n\r\t") + 1); } struct StringTranslator { @@ -83,7 +84,7 @@ struct StringTranslator { struct BoolTranslator { typedef std::string internal_type; - typedef bool external_type; + typedef bool external_type; boost::optional get_value(const internal_type &str) { boost::optional res; try { @@ -99,7 +100,7 @@ struct BoolTranslator { struct IntTranslator { typedef std::string internal_type; - typedef int external_type; + typedef int external_type; boost::optional get_value(const internal_type &str) { boost::optional res; try { @@ -115,8 +116,7 @@ struct IntTranslator { GameConfig::ParseResult GameConfig::saveConfig() { auto filename = getConfigFile(); - return parseConfig(ParseType::CONFIG, "", - ParseType::FILE, filename); + return parseConfig(ParseType::CONFIG, "", ParseType::FILE, filename); } std::string GameConfig::getDefaultINIString() { @@ -125,10 +125,11 @@ std::string GameConfig::getDefaultINIString() { return result; } -GameConfig::ParseResult GameConfig::parseConfig( - GameConfig::ParseType srcType, const std::string &source, - ParseType destType, std::string &destination) -{ +GameConfig::ParseResult GameConfig::parseConfig(GameConfig::ParseType srcType, + const std::string &source, + ParseType destType, + std::string &destination) { + // srcTree: holds all key/value pairs pt::ptree srcTree; ParseResult parseResult(srcType, source, destType, destination); @@ -152,12 +153,16 @@ GameConfig::ParseResult GameConfig::parseConfig( return parseResult; } + // knownKeys: holds all known keys + std::vector knownKeys; + auto read_config = [&](const std::string &key, auto &target, - const auto &defaultValue, auto &translator, - bool optional=true) { + const auto &defaultValue, auto &translator, + bool optional = true) { typedef typename std::remove_reference::type config_t; config_t sourceValue; + knownKeys.push_back(key); switch (srcType) { case ParseType::DEFAULT: @@ -210,13 +215,50 @@ GameConfig::ParseResult GameConfig::parseConfig( // Additionally, add them to the unit test. // @todo Don't allow path separators and relative directories - read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3", deft, false); + read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3", + deft, false); read_config("game.language", this->m_gameLanguage, "american", deft); read_config("input.invert_y", this->m_inputInvertY, false, boolt); - if (!parseResult.isValid()) - return parseResult; + if (!parseResult.isValid()) return parseResult; + + // Build the unknown key/value map from the correct source + switch (srcType) { + case ParseType::FILE: + case ParseType::STRING: + for (const auto §ion : srcTree) { + for (const auto &subKey : section.second) { + std::string key = section.first + "." + subKey.first; + if (std::find(knownKeys.begin(), knownKeys.end(), key) == + knownKeys.end()) { + RW_MESSAGE("Unknown configuration key: " << key); + parseResult.addUnknownData(key, subKey.second.data()); + } + } + } + break; + case ParseType::CONFIG: + parseResult.setUnknownData(m_parseResult.getUnknownData()); + break; + case ParseType::DEFAULT: + break; + } + + // Store the unknown key/value map to the correct destination + switch (destType) { + case ParseType::CONFIG: + m_parseResult.setUnknownData(parseResult.getUnknownData()); + break; + case ParseType::STRING: + case ParseType::FILE: + for (const auto &keyvalue : parseResult.getUnknownData()) { + srcTree.put(keyvalue.first, keyvalue.second); + } + break; + default: + break; + } try { if (destType == ParseType::STRING) { @@ -234,8 +276,8 @@ GameConfig::ParseResult GameConfig::parseConfig( return parseResult; } -std::string GameConfig::extractFilenameParseTypeData(ParseType type, const std::string &data) -{ +std::string GameConfig::extractFilenameParseTypeData(ParseType type, + const std::string &data) { switch (type) { case ParseType::CONFIG: return ""; @@ -249,16 +291,19 @@ std::string GameConfig::extractFilenameParseTypeData(ParseType type, const std:: } } -GameConfig::ParseResult::ParseResult( - GameConfig::ParseType srcType, const std::string &source, - GameConfig::ParseType destType, const std::string &destination) +GameConfig::ParseResult::ParseResult(GameConfig::ParseType srcType, + const std::string &source, + GameConfig::ParseType destType, + const std::string &destination) : m_result(ErrorType::GOOD) , m_inputfilename(GameConfig::extractFilenameParseTypeData(srcType, source)) - , m_outputfilename(GameConfig::extractFilenameParseTypeData(destType, destination)) + , m_outputfilename( + GameConfig::extractFilenameParseTypeData(destType, destination)) , m_line(0) , m_message() , m_keys_requiredMissing() - , m_keys_invalidData() { + , m_keys_invalidData() + , m_unknownData() { } GameConfig::ParseResult::ParseResult() @@ -280,7 +325,7 @@ bool GameConfig::ParseResult::isValid() const { } void GameConfig::ParseResult::failInputFile(size_t line, - const std::string &message) { + const std::string &message) { this->m_result = ParseResult::ErrorType::INVALIDINPUTFILE; this->m_line = line; this->m_message = message; @@ -301,17 +346,19 @@ void GameConfig::ParseResult::failInvalidData(const std::string &key) { } void GameConfig::ParseResult::failOutputFile(size_t line, - const std::string &message) { + const std::string &message) { this->m_result = ParseResult::ErrorType::INVALIDOUTPUTFILE; this->m_line = line; this->m_message = message; } -const std::vector &GameConfig::ParseResult::getKeysRequiredMissing() const { +const std::vector + &GameConfig::ParseResult::getKeysRequiredMissing() const { return this->m_keys_requiredMissing; } -const std::vector &GameConfig::ParseResult::getKeysInvalidData() const { +const std::vector &GameConfig::ParseResult::getKeysInvalidData() + const { return this->m_keys_invalidData; } @@ -321,27 +368,23 @@ std::string GameConfig::ParseResult::what() const { return "Good"; case ErrorType::INVALIDARGUMENT: return "Invalid argument: destination cannot be the default config"; - case ErrorType::INVALIDINPUTFILE: - { + case ErrorType::INVALIDINPUTFILE: { std::ostringstream oss; - oss << "Error while reading \"" - << this->m_inputfilename << "\":" << this->m_line << ":\n" + oss << "Error while reading \"" << this->m_inputfilename + << "\":" << this->m_line << ":\n" << this->m_message; return oss.str(); } - case ErrorType::INVALIDOUTPUTFILE: - { + case ErrorType::INVALIDOUTPUTFILE: { std::ostringstream oss; - oss << "Error while writing \"" - << this->m_inputfilename << "\":" << this->m_line << ":\n" + oss << "Error while writing \"" << this->m_inputfilename + << "\":" << this->m_line << ":\n" << this->m_message; return oss.str(); } - case ErrorType::INVALIDCONTENT: - { + case ErrorType::INVALIDCONTENT: { std::ostringstream oss; - oss << "Error while parsing \"" - << this->m_inputfilename << "\"."; + oss << "Error while parsing \"" << this->m_inputfilename << "\"."; if (this->m_keys_requiredMissing.size()) { oss << "\nRequired keys that are missing:"; for (auto &key : this->m_keys_requiredMissing) { @@ -360,3 +403,18 @@ std::string GameConfig::ParseResult::what() const { return "Unknown error"; } } + +void GameConfig::ParseResult::addUnknownData(const std::string &key, + const std::string &value) { + this->m_unknownData[key] = value; +} + +const std::map + &GameConfig::ParseResult::getUnknownData() const { + return this->m_unknownData; +} + +void GameConfig::ParseResult::setUnknownData( + const std::map &unknownData) { + this->m_unknownData = unknownData; +} diff --git a/rwgame/GameConfig.hpp b/rwgame/GameConfig.hpp index 51a24522..732101b1 100644 --- a/rwgame/GameConfig.hpp +++ b/rwgame/GameConfig.hpp @@ -1,47 +1,50 @@ #ifndef RWGAME_GAMECONFIG_HPP #define RWGAME_GAMECONFIG_HPP +#include #include #include class GameConfig { private: - enum ParseType { - DEFAULT, - CONFIG, - FILE, - STRING - }; + enum ParseType { DEFAULT, CONFIG, FILE, STRING }; /** * @brief extractFilenameParseTypeData Get a human readable filename string * @return file path or a description of the data type */ - static std::string extractFilenameParseTypeData(ParseType type, const std::string &data); + static std::string extractFilenameParseTypeData(ParseType type, + const std::string &data); + public: class ParseResult { public: enum ErrorType { /// GOOD: Input file/string was good GOOD, - /// INVALIDINPUTFILE: There was some error while reading from a file or string or the input was ambiguous (e.g. duplicate keys) + /// INVALIDINPUTFILE: There was some error while reading from a file + /// or string or the input was ambiguous (e.g. duplicate keys) INVALIDINPUTFILE, /// INVALIDARGUMENT: The parser received impossible arguments INVALIDARGUMENT, - /// INVALIDCONTENT: Some required keys were missing or some values were of incorrect type + /// INVALIDCONTENT: Some required keys were missing or some values + /// were of incorrect type INVALIDCONTENT, - /// INVALIDOUTPUTFILE: There was some error while writing to a file or string + /// INVALIDOUTPUTFILE: There was some error while writing to a file + /// or string INVALIDOUTPUTFILE }; + private: /** - * @brief ParseResult Holds the issues occurred while parsing of a config file. + * @brief ParseResult Holds the issues occurred while parsing of a + * config file. * @param srcType Type of the source * @param source The source of the parser * @param destType Type of the destination * @param destination The destination */ ParseResult(ParseType srcType, const std::string &source, - ParseType destType, const std::string &destination); + ParseType destType, const std::string &destination); /** * @brief ParseResult Create empty ParseResult @@ -93,7 +96,8 @@ public: void failInvalidData(const std::string &key); /** - * @brief failOutputFile Fail because an error occurred while while writing to the output + * @brief failOutputFile Fail because an error occurred while while + * writing to the output * @param line Line number where the error is located * @param message Description of the error */ @@ -110,6 +114,20 @@ public: * @return String with the error description */ std::string what() const; + + /** + * @brief addUnknownData Add unknown key value pairs + * @param key The unknown key + * @param value The associated data + */ + void addUnknownData(const std::string &key, const std::string &value); + + /** + * @brief addUnknownData Get all the unknown key value pairs + * @return Mapping of the unknown keys with associated data + */ + const std::map &getUnknownData() const; + private: /// Type of the failure ErrorType m_result; @@ -120,7 +138,8 @@ public: /// Filename of the output file std::string m_outputfilename; - /// Line number where the failure occurred (on invalid input or output file) + /// Line number where the failure occurred (on invalid input or output + /// file) size_t m_line; /// Description of the failure (on invalid input or output file) @@ -132,6 +151,15 @@ public: /// All keys that contain invalid data std::vector m_keys_invalidData; + // Mapping of unknown keys and associated data + std::map m_unknownData; + + /** + * @brief setUnknownData Replace the the unknown key value pairs + */ + void setUnknownData( + const std::map &unknownData); + friend class GameConfig; }; @@ -140,8 +168,8 @@ public: * @param configName The configuration filename to load * @param configPath Where to look. */ - GameConfig(const std::string& configName, - const std::string& configPath = getDefaultConfigPath()); + GameConfig(const std::string &configName, + const std::string &configPath = getDefaultConfigPath()); /** * @brief getFilePath Returns the system file path for the configuration @@ -166,15 +194,16 @@ public: const ParseResult &getParseResult() const; /** - * @brief getConfigString Returns the content of the default INI configuration. + * @brief getConfigString Returns the content of the default INI + * configuration. * @return INI string */ std::string getDefaultINIString(); - const std::string& getGameDataPath() const { + const std::string &getGameDataPath() const { return m_gamePath; } - const std::string& getGameLanguage() const { + const std::string &getGameLanguage() const { return m_gameLanguage; } bool getInputInvertY() const { @@ -186,6 +215,7 @@ private: /** * @brief parseConfig Load data from source and write it to destination. + * Whitespace will be stripped from unknown data. * @param srcType Can be DEFAULT | CONFIG | FILE | STRING * @param source don't care if srcType == (DEFAULT | CONFIG), * path of INI file if srcType == FILE @@ -197,7 +227,7 @@ private: * @return True if the parsing succeeded */ ParseResult parseConfig(ParseType srcType, const std::string &source, - ParseType destType, std::string &destination); + ParseType destType, std::string &destination); /* Config State */ std::string m_configName; diff --git a/tests/test_config.cpp b/tests/test_config.cpp index d73fce1f..51b636e1 100644 --- a/tests/test_config.cpp +++ b/tests/test_config.cpp @@ -3,12 +3,39 @@ #include #include +#include +#include + #include #include +#include "rw/defines.hpp" + +namespace pt = boost::property_tree; namespace fs = boost::filesystem; -typedef std::map> simpleConfig_t; +typedef std::map> + simpleConfig_t; + +simpleConfig_t readConfig(const std::string &filename) { + simpleConfig_t cfg; + pt::ptree tree; + pt::read_ini(filename, tree); + + for (const auto §ion : tree) { + for (const auto &subKey : section.second) { + cfg[section.first][subKey.first] = subKey.second.data(); + } + } + return cfg; +} + +std::string stripWhitespace(const std::string &in) { + static const std::string whitespace = " \n\r\t"; + auto start = in.find_first_not_of(whitespace); + auto end = in.find_last_not_of(whitespace) + 1; + return std::string(in, start, end - start); +} simpleConfig_t getValidConfig() { simpleConfig_t result; @@ -16,14 +43,17 @@ simpleConfig_t getValidConfig() { // to test the robustness of the INI parser. // Don't change game.path and input.invert_y keys. Tests depend on them. result["game"]["path"] = "\t/dev/test \t \r\n"; - result["game"]["\tlanguage\t "] = " american ;american english french german italian spanish."; - result["input"]["invert_y"] = "1 #values != 0 enable input inversion. Optional."; + result["game"]["\tlanguage\t "] = + " american ;american english french german italian spanish."; + result["input"]["invert_y"] = + "1 #values != 0 enable input inversion. Optional."; return result; } std::ostream &operator<<(std::ostream &os, const simpleConfig_t &config) { for (auto §ion : config) { - os << "[" << section.first << "]" << "\n"; + os << "[" << section.first << "]" + << "\n"; for (auto &keyValue : section.second) { os << keyValue.first << "=" << keyValue.second << "\n"; } @@ -59,10 +89,11 @@ public: return this->m_path.parent_path().string(); } void change_perms_readonly() { - fs::permissions(this->m_path, fs::perms::owner_read - | fs::perms::group_read | fs::perms::others_read); + fs::permissions(this->m_path, fs::perms::owner_read | + fs::perms::group_read | + fs::perms::others_read); } - template + template bool append(T t) { // Append argument at the end of the file. // File is open/closes repeatedly. Not optimal. @@ -71,7 +102,7 @@ public: ofs.close(); return ofs.good(); } - template + template bool write(T t) { // Write the argument to the file, discarding all contents. // File is open/closes repeatedly. Not optimal. @@ -80,15 +111,31 @@ public: ofs.close(); return ofs.good(); } + private: static fs::path getRandomFilePath() { - return fs::unique_path(fs::temp_directory_path() / "openrw_test_%%%%%%%%%%%%%%%%"); + return fs::unique_path(fs::temp_directory_path() / + "openrw_test_%%%%%%%%%%%%%%%%"); } fs::path m_path; }; BOOST_AUTO_TEST_SUITE(ConfigTests) +BOOST_AUTO_TEST_CASE(test_stripWhitespace) { + std::map map; + map["abc"] = "abc"; + map["\tabc"] = "abc"; + map["abc\t"] = "abc"; + map[" abc"] = "abc"; + map["abc "] = "abc"; + map[" abc "] = "abc"; + map[" abc "] = "abc"; + for (const auto &keyValue : map) { + BOOST_CHECK_EQUAL(keyValue.second, stripWhitespace(keyValue.first)); + } +} + BOOST_AUTO_TEST_CASE(test_TempFile) { // Check the behavior of TempFile TempFile tempFile; @@ -126,8 +173,10 @@ BOOST_AUTO_TEST_CASE(test_config_valid) { GameConfig config(tempFile.filename(), tempFile.dirname()); BOOST_CHECK(config.isValid()); - BOOST_CHECK_EQUAL(config.getParseResult().type(), GameConfig::ParseResult::ErrorType::GOOD); - BOOST_CHECK_EQUAL(config.getParseResult().getKeysRequiredMissing().size(), 0); + BOOST_CHECK_EQUAL(config.getParseResult().type(), + GameConfig::ParseResult::ErrorType::GOOD); + BOOST_CHECK_EQUAL(config.getParseResult().getKeysRequiredMissing().size(), + 0); BOOST_CHECK_EQUAL(config.getParseResult().getKeysInvalidData().size(), 0); BOOST_CHECK_EQUAL(config.getGameDataPath(), "/dev/test"); @@ -147,8 +196,10 @@ BOOST_AUTO_TEST_CASE(test_config_valid_modified) { GameConfig config(tempFile.filename(), tempFile.dirname()); BOOST_CHECK(config.isValid()); - BOOST_CHECK_EQUAL(config.getParseResult().type(), GameConfig::ParseResult::ErrorType::GOOD); - BOOST_CHECK_EQUAL(config.getParseResult().getKeysRequiredMissing().size(), 0); + BOOST_CHECK_EQUAL(config.getParseResult().type(), + GameConfig::ParseResult::ErrorType::GOOD); + BOOST_CHECK_EQUAL(config.getParseResult().getKeysRequiredMissing().size(), + 0); BOOST_CHECK_EQUAL(config.getParseResult().getKeysInvalidData().size(), 0); BOOST_CHECK_EQUAL(config.getInputInvertY(), false); @@ -176,6 +227,55 @@ BOOST_AUTO_TEST_CASE(test_config_save) { GameConfig config2(tempFile.filename(), tempFile.dirname()); BOOST_CHECK_EQUAL(config2.getGameDataPath(), "Liberty City"); + + simpleConfig_t cfg2 = readConfig(tempFile.path()); + BOOST_CHECK_EQUAL(cfg2["game"]["path"], "Liberty City"); +} + +BOOST_AUTO_TEST_CASE(test_config_valid_unknown_keys) { + // Test reading a valid modified configuration file with unknown data + auto cfg = getValidConfig(); + cfg["game"]["unknownkey"] = "descartes"; + cfg["dontknow"]["dontcare"] = "\t$%!$8847 %%$ "; + + TempFile tempFile; + tempFile.append(cfg); + + GameConfig config(tempFile.filename(), tempFile.dirname()); + + BOOST_CHECK(config.isValid()); + + const auto &unknownData = config.getParseResult().getUnknownData(); + + BOOST_CHECK_EQUAL(unknownData.size(), 2); + + BOOST_CHECK_EQUAL(unknownData.count("game.unknownkey"), 1); + BOOST_CHECK_EQUAL(unknownData.at("game.unknownkey"), + stripWhitespace(cfg["game"]["unknownkey"])); + + BOOST_CHECK_EQUAL(unknownData.count("dontknow.dontcare"), 1); + BOOST_CHECK_EQUAL(unknownData.at("dontknow.dontcare"), + stripWhitespace(cfg["dontknow"]["dontcare"])); + + BOOST_CHECK_EQUAL(unknownData.count("game.path"), 0); + + tempFile.remove(); + config.saveConfig(); + + GameConfig config2(tempFile.filename(), tempFile.dirname()); + const auto &unknownData2 = config2.getParseResult().getUnknownData(); + + BOOST_CHECK_EQUAL(unknownData2.size(), 2); + + BOOST_CHECK_EQUAL(unknownData2.count("game.unknownkey"), 1); + BOOST_CHECK_EQUAL(unknownData2.at("game.unknownkey"), + stripWhitespace(cfg["game"]["unknownkey"])); + + BOOST_CHECK_EQUAL(unknownData2.count("dontknow.dontcare"), 1); + BOOST_CHECK_EQUAL(unknownData2.at("dontknow.dontcare"), + stripWhitespace(cfg["dontknow"]["dontcare"])); + + BOOST_CHECK_EQUAL(unknownData2.count("game.path"), 0); } BOOST_AUTO_TEST_CASE(test_config_save_readonly) { @@ -191,7 +291,8 @@ BOOST_AUTO_TEST_CASE(test_config_save_readonly) { auto writeResult = config.saveConfig(); BOOST_CHECK(!writeResult.isValid()); - BOOST_CHECK_EQUAL(writeResult.type(), GameConfig::ParseResult::ErrorType::INVALIDOUTPUTFILE); + BOOST_CHECK_EQUAL(writeResult.type(), + GameConfig::ParseResult::ErrorType::INVALIDOUTPUTFILE); } BOOST_AUTO_TEST_CASE(test_config_valid_default) { @@ -209,6 +310,22 @@ BOOST_AUTO_TEST_CASE(test_config_valid_default) { BOOST_CHECK(config.isValid()); } +BOOST_AUTO_TEST_CASE(test_config_invalid_emptykey) { + // Test duplicate keys in invalid configuration file + auto cfg = getValidConfig(); + cfg["game"][""] = "0"; + + TempFile tempFile; + tempFile.append(cfg); + + GameConfig config(tempFile.filename(), tempFile.dirname()); + + BOOST_CHECK(!config.isValid()); + const auto &parseResult = config.getParseResult(); + BOOST_CHECK_EQUAL(parseResult.type(), + GameConfig::ParseResult::ErrorType::INVALIDINPUTFILE); +} + BOOST_AUTO_TEST_CASE(test_config_invalid_duplicate) { // Test duplicate keys in invalid configuration file auto cfg = getValidConfig(); @@ -221,7 +338,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_duplicate) { BOOST_CHECK(!config.isValid()); const auto &parseResult = config.getParseResult(); - BOOST_CHECK_EQUAL(parseResult.type(), GameConfig::ParseResult::ErrorType::INVALIDINPUTFILE); + BOOST_CHECK_EQUAL(parseResult.type(), + GameConfig::ParseResult::ErrorType::INVALIDINPUTFILE); } BOOST_AUTO_TEST_CASE(test_config_invalid_required_missing) { @@ -237,7 +355,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_required_missing) { BOOST_CHECK(!config.isValid()); const auto &parseResult = config.getParseResult(); - BOOST_CHECK_EQUAL(parseResult.type(), GameConfig::ParseResult::ErrorType::INVALIDCONTENT); + BOOST_CHECK_EQUAL(parseResult.type(), + GameConfig::ParseResult::ErrorType::INVALIDCONTENT); BOOST_CHECK_EQUAL(parseResult.getKeysRequiredMissing().size(), 1); BOOST_CHECK_EQUAL(parseResult.getKeysInvalidData().size(), 0); @@ -248,7 +367,7 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_required_missing) { BOOST_AUTO_TEST_CASE(test_config_invalid_wrong_type) { // Test wrong data type auto cfg = getValidConfig(); - cfg["input"]["invert_y"]="d"; + cfg["input"]["invert_y"] = "d"; TempFile tempFile; tempFile.append(cfg); @@ -258,7 +377,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_wrong_type) { BOOST_CHECK(!config.isValid()); const auto &parseResult = config.getParseResult(); - BOOST_CHECK_EQUAL(parseResult.type(), GameConfig::ParseResult::ErrorType::INVALIDCONTENT); + BOOST_CHECK_EQUAL(parseResult.type(), + GameConfig::ParseResult::ErrorType::INVALIDCONTENT); BOOST_CHECK_EQUAL(parseResult.getKeysRequiredMissing().size(), 0); BOOST_CHECK_EQUAL(parseResult.getKeysInvalidData().size(), 1); @@ -268,7 +388,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_wrong_type) { BOOST_AUTO_TEST_CASE(test_config_invalid_empty) { // Test reading empty configuration file - // An empty file has a valid data structure, but has missing keys and is thus invalid. + // An empty file has a valid data structure, but has missing keys and is + // thus invalid. TempFile tempFile; tempFile.touch(); BOOST_CHECK(tempFile.exists()); @@ -278,7 +399,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_empty) { BOOST_CHECK(!config.isValid()); const auto &parseResult = config.getParseResult(); - BOOST_CHECK_EQUAL(parseResult.type(), GameConfig::ParseResult::ErrorType::INVALIDCONTENT); + BOOST_CHECK_EQUAL(parseResult.type(), + GameConfig::ParseResult::ErrorType::INVALIDCONTENT); BOOST_CHECK_GE(parseResult.getKeysRequiredMissing().size(), 1); } @@ -292,7 +414,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_nonexisting) { BOOST_CHECK(!config.isValid()); const auto &parseResult = config.getParseResult(); - BOOST_CHECK_EQUAL(parseResult.type(), GameConfig::ParseResult::ErrorType::INVALIDINPUTFILE); + BOOST_CHECK_EQUAL(parseResult.type(), + GameConfig::ParseResult::ErrorType::INVALIDINPUTFILE); } BOOST_AUTO_TEST_SUITE_END()