diff --git a/rwgame/GameConfig.cpp b/rwgame/GameConfig.cpp index 8b483eaf..713a9ee6 100644 --- a/rwgame/GameConfig.cpp +++ b/rwgame/GameConfig.cpp @@ -99,6 +99,12 @@ struct IntTranslator { } }; +bool GameConfig::saveConfig() { + auto filename = getConfigFile(); + return parseConfig(ParseType::CONFIG, "", + ParseType::FILE, filename); +} + std::string GameConfig::getDefaultINIString() { std::string result; parseConfig(ParseType::DEFAULT, "", ParseType::STRING, result); diff --git a/rwgame/GameConfig.hpp b/rwgame/GameConfig.hpp index f9a3569b..91199228 100644 --- a/rwgame/GameConfig.hpp +++ b/rwgame/GameConfig.hpp @@ -17,6 +17,11 @@ public: */ std::string getConfigFile() const; + /** + * @brief writeConfig Save the game configuration + */ + bool saveConfig(); + /** * @brief isValid * @return True if the loaded configuration is valid diff --git a/tests/test_config.cpp b/tests/test_config.cpp index 3ec87ebc..2bbfd7c8 100644 --- a/tests/test_config.cpp +++ b/tests/test_config.cpp @@ -8,21 +8,22 @@ namespace fs = boost::filesystem; -typedef std::map> config_t; +typedef std::map> simpleConfig_t; fs::path getRandomFilePath() { return fs::unique_path(fs::temp_directory_path() /= "openrw_test_%%%%%%%%%%%%%%%%"); } -config_t getValidConfig() { - config_t result; - result["game"]["\tpath "] = "\t/dev/test \t \r\n"; - result["game"]["language\t "] = " american ;american english french german italian spanish."; +simpleConfig_t getValidConfig() { + simpleConfig_t result; + // 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."; return result; } -std::ostream &writeConfig(std::ostream &os, const config_t &config) { +std::ostream &writeConfig(std::ostream &os, const simpleConfig_t &config) { for (auto §ion : config) { os << "[" << section.first << "]" << "\n"; for (auto &keyValue : section.second) { @@ -32,11 +33,10 @@ std::ostream &writeConfig(std::ostream &os, const config_t &config) { return os; } -#include - BOOST_AUTO_TEST_SUITE(ConfigTests) BOOST_AUTO_TEST_CASE(test_config_valid) { + // Test reading a valid configuration file auto cfg = getValidConfig(); auto configPath = getRandomFilePath(); @@ -55,7 +55,9 @@ BOOST_AUTO_TEST_CASE(test_config_valid) { } BOOST_AUTO_TEST_CASE(test_config_valid_modified) { + // Test reading a valid modified configuration file auto cfg = getValidConfig(); + cfg["game"]["path"] = "Liberty City"; cfg["input"]["invert_y"] = "0"; auto configPath = getRandomFilePath(); @@ -69,9 +71,38 @@ BOOST_AUTO_TEST_CASE(test_config_valid_modified) { BOOST_CHECK(config.isValid()); BOOST_CHECK_EQUAL(config.getInputInvertY(), false); + BOOST_CHECK_EQUAL(config.getGameDataPath(), "Liberty City"); +} + +BOOST_AUTO_TEST_CASE(test_config_save) { + // Test saving a configuration file + auto cfg = getValidConfig(); + cfg["game"]["path"] = "Liberty City"; + auto configPath = getRandomFilePath(); + + std::ofstream ofs(configPath.string()); + writeConfig(ofs, cfg); + ofs.close(); + + GameConfig config(configPath.filename().string(), + configPath.parent_path().string()); + + BOOST_CHECK(config.isValid()); + + fs::remove(configPath); + + BOOST_CHECK(!fs::exists(configPath)); + BOOST_CHECK(config.saveConfig()); + BOOST_CHECK(fs::exists(configPath)); + + GameConfig config2(configPath.filename().string(), + configPath.parent_path().string()); + + BOOST_CHECK_EQUAL(config2.getGameDataPath(), "Liberty City"); } BOOST_AUTO_TEST_CASE(test_config_invalid_duplicate) { + // Test duplicate keys in invalid configuration file auto cfg = getValidConfig(); cfg["input"]["invert_y "] = "0"; auto configPath = getRandomFilePath(); @@ -86,10 +117,11 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_duplicate) { BOOST_CHECK(!config.isValid()); } -BOOST_AUTO_TEST_CASE(test_config_invalid_empty) { - config_t cfg; +BOOST_AUTO_TEST_CASE(test_config_invalid_required_missing) { + // Test missing required keys in invalid configuration file + auto cfg = getValidConfig(); + cfg["game"].erase("path"); auto configPath = getRandomFilePath(); - std::cout << configPath.string() << "\n"; std::ofstream ofs(configPath.string()); writeConfig(ofs, cfg); @@ -101,4 +133,29 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_empty) { BOOST_CHECK(!config.isValid()); } +BOOST_AUTO_TEST_CASE(test_config_invalid_empty) { + // Test reading empty configuration file + simpleConfig_t cfg; + auto configPath = getRandomFilePath(); + + std::ofstream ofs(configPath.string()); + writeConfig(ofs, cfg); + ofs.close(); + + GameConfig config(configPath.filename().string(), + configPath.parent_path().string()); + + BOOST_CHECK(!config.isValid()); +} + +BOOST_AUTO_TEST_CASE(test_config_invalid_nonexisting) { + // Test reading non-existing configuration file + auto configPath = getRandomFilePath(); + + GameConfig config(configPath.filename().string(), + configPath.parent_path().string()); + + BOOST_CHECK(!config.isValid()); +} + BOOST_AUTO_TEST_SUITE_END()