1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-15 06:52:34 +02:00

rwgame: allow configuration files from all places (not only config path)

- add it as an argument to the rwgame executable
- update the tests
This commit is contained in:
Anonymous Maarten 2017-11-02 03:36:13 +01:00 committed by Daniel Evans
parent 6dffed543a
commit 55dd0beea0
6 changed files with 192 additions and 123 deletions

View File

@ -1,4 +1,8 @@
#include "GameBase.hpp" #include "GameBase.hpp"
#include <rw/defines.hpp>
#include <rw/filesystem.hpp>
#include "GitSHA1.h" #include "GitSHA1.h"
#include "SDL.h" #include "SDL.h"
@ -6,21 +10,19 @@
// Use first 8 chars of git hash as the build string // Use first 8 chars of git hash as the build string
const std::string kBuildStr(kGitSHA1Hash, 8); const std::string kBuildStr(kGitSHA1Hash, 8);
const std::string kWindowTitle = "RWGame"; const std::string kWindowTitle = "RWGame";
const std::string kDefaultConfigFileName = "openrw.ini";
constexpr int kWindowWidth = 800; constexpr int kWindowWidth = 800;
constexpr int kWindowHeight = 600; constexpr int kWindowHeight = 600;
GameBase::GameBase(Logger &inlog, int argc, char *argv[]) : log(inlog) { GameBase::GameBase(Logger &inlog, int argc, char *argv[]) :
log(inlog),
config(),
window(),
options() {
log.info("Game", "Build: " + kBuildStr); log.info("Game", "Build: " + kBuildStr);
if (!config.isValid()) {
log.error("Config", "Invalid INI file at \""
+ config.getConfigFile() + "\".\n"
+ "Adapt the following default INI to your configuration.\n"
+ config.getDefaultINIString());
throw std::runtime_error(config.getParseResult().what());
}
size_t w = kWindowWidth, h = kWindowHeight; size_t w = kWindowWidth, h = kWindowHeight;
rwfs::path configPath;
bool fullscreen = false; bool fullscreen = false;
bool help = false; bool help = false;
@ -29,6 +31,7 @@ GameBase::GameBase(Logger &inlog, int argc, char *argv[]) : log(inlog) {
po::options_description desc("Available options"); po::options_description desc("Available options");
desc.add_options()( desc.add_options()(
"help", "Show this help message")( "help", "Show this help message")(
"config,c", po::value<rwfs::path>(), "Path of configuration file")(
"width,w", po::value<size_t>(), "Game resolution width in pixel")( "width,w", po::value<size_t>(), "Game resolution width in pixel")(
"height,h", po::value<size_t>(), "Game resolution height in pixel")( "height,h", po::value<size_t>(), "Game resolution height in pixel")(
"fullscreen,f", "Enable fullscreen mode")( "fullscreen,f", "Enable fullscreen mode")(
@ -59,6 +62,20 @@ GameBase::GameBase(Logger &inlog, int argc, char *argv[]) : log(inlog) {
if (vm.count("fullscreen")) { if (vm.count("fullscreen")) {
fullscreen = true; fullscreen = true;
} }
if (vm.count("config")) {
configPath = vm["config"].as<rwfs::path>();
} else {
configPath = GameConfig::getDefaultConfigPath() / kDefaultConfigFileName;
}
config.loadFile(configPath);
if (!config.isValid()) {
log.error("Config", "Invalid INI file at \""
+ config.getConfigPath().string() + "\".\n"
+ "Adapt the following default INI to your configuration.\n"
+ config.getDefaultINIString());
throw std::runtime_error(config.getParseResult().what());
}
if (SDL_Init(SDL_INIT_VIDEO) < 0) if (SDL_Init(SDL_INIT_VIDEO) < 0)
throw std::runtime_error("Failed to initialize SDL2!"); throw std::runtime_error("Failed to initialize SDL2!");

View File

@ -25,7 +25,7 @@ public:
protected: protected:
Logger& log; Logger& log;
GameConfig config{"openrw.ini"}; GameConfig config;
GameWindow window; GameWindow window;
boost::program_options::variables_map options; boost::program_options::variables_map options;
}; };

View File

@ -2,6 +2,7 @@
#include <algorithm> #include <algorithm>
#include <rw/defines.hpp> #include <rw/defines.hpp>
#include <rw/filesystem.hpp>
#include <boost/property_tree/ini_parser.hpp> #include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
@ -9,26 +10,21 @@ namespace pt = boost::property_tree;
const std::string kConfigDirectoryName("OpenRW"); const std::string kConfigDirectoryName("OpenRW");
GameConfig::GameConfig(const std::string &configName, GameConfig::GameConfig()
const std::string &configPath) : m_configPath()
: m_configName(configName)
, m_configPath(configPath)
, m_parseResult() , m_parseResult()
, m_inputInvertY(false) { , m_inputInvertY(false) {
if (m_configPath.empty()) {
m_configPath = getDefaultConfigPath();
}
// Look up the path to use
auto configFile = getConfigFile();
std::string dummy;
m_parseResult =
parseConfig(ParseType::FILE, configFile, ParseType::CONFIG, dummy);
} }
std::string GameConfig::getConfigFile() const { void GameConfig::loadFile(const rwfs::path &path) {
return m_configPath + "/" + m_configName; m_configPath = path;
std::string dummy;
m_parseResult =
parseConfig(ParseType::FILE, path.string(), ParseType::CONFIG, dummy);
}
rwfs::path GameConfig::getConfigPath() const {
return m_configPath;
} }
bool GameConfig::isValid() const { bool GameConfig::isValid() const {
@ -39,31 +35,31 @@ const GameConfig::ParseResult &GameConfig::getParseResult() const {
return m_parseResult; return m_parseResult;
} }
std::string GameConfig::getDefaultConfigPath() { rwfs::path GameConfig::getDefaultConfigPath() {
#if defined(RW_LINUX) || defined(RW_FREEBSD) || defined(RW_NETBSD) || \ #if defined(RW_LINUX) || defined(RW_FREEBSD) || defined(RW_NETBSD) || \
defined(RW_OPENBSD) defined(RW_OPENBSD)
char *config_home = getenv("XDG_CONFIG_HOME"); char *config_home = getenv("XDG_CONFIG_HOME");
if (config_home != nullptr) { if (config_home != nullptr) {
return std::string(config_home) + "/" + kConfigDirectoryName; return rwfs::path(config_home) / kConfigDirectoryName;
} }
char *home = getenv("HOME"); char *home = getenv("HOME");
if (home != nullptr) { if (home != nullptr) {
return std::string(home) + "/.config/" + kConfigDirectoryName; return rwfs::path(home) / ".config/" / kConfigDirectoryName;
} }
#elif defined(RW_OSX) #elif defined(RW_OSX)
char *home = getenv("HOME"); char *home = getenv("HOME");
if (home) if (home)
return std::string(home) + "/Library/Preferences/" + return rwfs::path(home) / "Library/Preferences/" /
kConfigDirectoryName; kConfigDirectoryName;
#else #else
return "."; return rwfs::path();
#endif #endif
// Well now we're stuck. // Well now we're stuck.
RW_ERROR("No default config path found."); RW_ERROR("No default config path found.");
return "."; return rwfs::path();
} }
std::string stripComments(const std::string &str) { std::string stripComments(const std::string &str) {
@ -71,6 +67,17 @@ std::string stripComments(const std::string &str) {
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 PathTranslator {
typedef std::string internal_type;
typedef rwfs::path external_type;
boost::optional<external_type> get_value(const internal_type &str) {
return rwfs::path(str);
}
boost::optional<internal_type> put_value(const external_type &path) {
return path.string();
}
};
struct StringTranslator { struct StringTranslator {
typedef std::string internal_type; typedef std::string internal_type;
typedef std::string external_type; typedef std::string external_type;
@ -115,8 +122,8 @@ struct IntTranslator {
}; };
GameConfig::ParseResult GameConfig::saveConfig() { GameConfig::ParseResult GameConfig::saveConfig() {
auto filename = getConfigFile(); auto configPath = getConfigPath().string();
return parseConfig(ParseType::CONFIG, "", ParseType::FILE, filename); return parseConfig(ParseType::CONFIG, "", ParseType::FILE, configPath);
} }
std::string GameConfig::getDefaultINIString() { std::string GameConfig::getDefaultINIString() {
@ -210,13 +217,14 @@ GameConfig::ParseResult GameConfig::parseConfig(GameConfig::ParseType srcType,
auto deft = StringTranslator(); auto deft = StringTranslator();
auto boolt = BoolTranslator(); auto boolt = BoolTranslator();
auto patht = PathTranslator();
// Add new configuration parameters here. // Add new configuration parameters here.
// Additionally, add them to the unit test. // Additionally, add them to the unit test.
// @todo Don't allow path separators and relative directories // @todo Don't allow path separators and relative directories
read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3", read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3",
deft, false); patht, false);
read_config("game.language", this->m_gameLanguage, "american", deft); read_config("game.language", this->m_gameLanguage, "american", deft);
read_config("input.invert_y", this->m_inputInvertY, false, boolt); read_config("input.invert_y", this->m_inputInvertY, false, boolt);
@ -273,6 +281,10 @@ GameConfig::ParseResult GameConfig::parseConfig(GameConfig::ParseType srcType,
RW_MESSAGE(e.what()); RW_MESSAGE(e.what());
} }
if (parseResult.type() == ParseResult::ErrorType::UNINITIALIZED) {
parseResult.markGood();
}
return parseResult; return parseResult;
} }
@ -307,7 +319,7 @@ GameConfig::ParseResult::ParseResult(GameConfig::ParseType srcType,
} }
GameConfig::ParseResult::ParseResult() GameConfig::ParseResult::ParseResult()
: m_result(ErrorType::GOOD) : m_result(ErrorType::UNINITIALIZED)
, m_inputfilename() , m_inputfilename()
, m_outputfilename() , m_outputfilename()
, m_line(0) , m_line(0)
@ -331,6 +343,10 @@ void GameConfig::ParseResult::failInputFile(size_t line,
this->m_message = message; this->m_message = message;
} }
void GameConfig::ParseResult::markGood() {
this-> m_result = ParseResult::ErrorType::GOOD;
}
void GameConfig::ParseResult::failArgument() { void GameConfig::ParseResult::failArgument() {
this->m_result = ParseResult::ErrorType::INVALIDARGUMENT; this->m_result = ParseResult::ErrorType::INVALIDARGUMENT;
} }
@ -365,6 +381,9 @@ const std::vector<std::string> &GameConfig::ParseResult::getKeysInvalidData()
std::string GameConfig::ParseResult::what() const { std::string GameConfig::ParseResult::what() const {
std::ostringstream oss; std::ostringstream oss;
switch (this->m_result) { switch (this->m_result) {
case ErrorType::UNINITIALIZED:
oss << "Parsing was skipped or did not finish.";
break;
case ErrorType::GOOD: case ErrorType::GOOD:
oss << "Parsing completed without errors."; oss << "Parsing completed without errors.";
break; break;

View File

@ -4,6 +4,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <rw/filesystem.hpp>
class GameConfig { class GameConfig {
private: private:
enum ParseType { DEFAULT, CONFIG, FILE, STRING }; enum ParseType { DEFAULT, CONFIG, FILE, STRING };
@ -19,6 +21,8 @@ public:
class ParseResult { class ParseResult {
public: public:
enum ErrorType { enum ErrorType {
/// UNINITIALIZED: The config was not initialized
UNINITIALIZED,
/// GOOD: Input file/string was good /// GOOD: Input file/string was good
GOOD, GOOD,
/// INVALIDINPUTFILE: There was some error while reading from a file /// INVALIDINPUTFILE: There was some error while reading from a file
@ -69,6 +73,12 @@ public:
* @return A vector with all the keys * @return A vector with all the keys
*/ */
const std::vector<std::string> &getKeysInvalidData() const; const std::vector<std::string> &getKeysInvalidData() const;
/**
* @brief Mark this result as valid
*/
void markGood();
/** /**
* @brief failInputFile Fail because the input file was invalid * @brief failInputFile Fail because the input file was invalid
* @param line Line number where the error is located * @param line Line number where the error is located
@ -164,17 +174,20 @@ public:
}; };
/** /**
* @brief GameConfig Loads a game configuration * @brief GameConfig Create a game configuration (initially invalid)
* @param configName The configuration filename to load
* @param configPath Where to look.
*/ */
GameConfig(const std::string &configName, GameConfig();
const std::string &configPath = getDefaultConfigPath());
/** /**
* @brief getFilePath Returns the system file path for the configuration * @brief Initialize this object using the config file at path
* @param path Path of the configuration file
*/ */
std::string getConfigFile() const; void loadFile(const rwfs::path &path);
/**
* @brief getConfigPath Returns the path for the configuration
*/
rwfs::path getConfigPath() const;
/** /**
* @brief writeConfig Save the game configuration * @brief writeConfig Save the game configuration
@ -201,7 +214,7 @@ public:
std::string getDefaultINIString(); std::string getDefaultINIString();
const std::string &getGameDataPath() const { const std::string &getGameDataPath() const {
return m_gamePath; return m_gamePath.string(); //FIXME: change to path
} }
const std::string &getGameLanguage() const { const std::string &getGameLanguage() const {
return m_gameLanguage; return m_gameLanguage;
@ -210,8 +223,8 @@ public:
return m_inputInvertY; return m_inputInvertY;
} }
static rwfs::path getDefaultConfigPath();
private: private:
static std::string getDefaultConfigPath();
/** /**
* @brief parseConfig Load data from source and write it to destination. * @brief parseConfig Load data from source and write it to destination.
@ -230,14 +243,13 @@ private:
ParseType destType, std::string &destination); ParseType destType, std::string &destination);
/* Config State */ /* Config State */
std::string m_configName; rwfs::path m_configPath;
std::string m_configPath;
ParseResult m_parseResult; ParseResult m_parseResult;
/* Actual Configuration */ /* Actual Configuration */
/// Path to the game data /// Path to the game data
std::string m_gamePath; rwfs::path m_gamePath;
/// Language for game /// Language for game
std::string m_gameLanguage = "american"; std::string m_gameLanguage = "american";

View File

@ -12,15 +12,14 @@
#include <rw/filesystem.hpp> #include <rw/filesystem.hpp>
namespace pt = boost::property_tree; namespace pt = boost::property_tree;
namespace fs = rwfs;
typedef std::map<std::string, std::map<std::string, std::string>> typedef std::map<std::string, std::map<std::string, std::string>>
simpleConfig_t; simpleConfig_t;
simpleConfig_t readConfig(const std::string &filename) { simpleConfig_t readConfig(const rwfs::path &path) {
simpleConfig_t cfg; simpleConfig_t cfg;
pt::ptree tree; pt::ptree tree;
pt::read_ini(filename, tree); pt::read_ini(path.string(), tree);
for (const auto &section : tree) { for (const auto &section : tree) {
for (const auto &subKey : section.second) { for (const auto &subKey : section.second) {
@ -67,10 +66,10 @@ public:
virtual ~Temp() { virtual ~Temp() {
} }
bool exists() const { bool exists() const {
return fs::exists(this->m_path); return rwfs::exists(this->m_path);
} }
std::string path() const { const rwfs::path &path() const {
return this->m_path.string(); return this->m_path;
} }
std::string filename() const { std::string filename() const {
return this->m_path.filename().string(); return this->m_path.filename().string();
@ -86,20 +85,17 @@ protected:
Temp(const Temp &) = delete; Temp(const Temp &) = delete;
Temp() : m_path(getRandomFilePath()) { Temp() : m_path(getRandomFilePath()) {
} }
Temp(const fs::path &dirname) : m_path(getRandomFilePath(dirname)) { Temp(const rwfs::path &dirname) : m_path(getRandomFilePath(dirname)) {
}
const fs::path &get_path_internal() const {
return this->m_path;
} }
private: private:
static fs::path getRandomFilePath(const fs::path &dirname) { static rwfs::path getRandomFilePath(const rwfs::path &dirname) {
return fs::unique_path(dirname / "openrw_test_%%%%%%%%%%%%%%%%"); return rwfs::unique_path(dirname / "openrw_test_%%%%%%%%%%%%%%%%");
} }
static fs::path getRandomFilePath() { static rwfs::path getRandomFilePath() {
return getRandomFilePath(fs::temp_directory_path()); return getRandomFilePath(rwfs::temp_directory_path());
} }
fs::path m_path; rwfs::path m_path;
}; };
class TempFile; class TempFile;
@ -108,22 +104,22 @@ class TempDir : public Temp {
public: public:
TempDir() : Temp() { TempDir() : Temp() {
} }
TempDir(const TempDir &dirname) : Temp(dirname.get_path_internal()) { TempDir(const TempDir &dirname) : Temp(dirname.path()) {
} }
virtual ~TempDir() { virtual ~TempDir() {
this->remove(); this->remove();
} }
virtual void change_perms_readonly() const override { virtual void change_perms_readonly() const override {
fs::permissions(this->get_path_internal(), rwfs::permissions(this->path(),
fs::perms::owner_read | fs::perms::owner_exe | rwfs::perms::owner_read | rwfs::perms::owner_exe |
fs::perms::group_read | fs::perms::group_exe | rwfs::perms::group_read | rwfs::perms::group_exe |
fs::perms::others_read | fs::perms::others_exe); rwfs::perms::others_read | rwfs::perms::others_exe);
} }
virtual void remove() const override { virtual void remove() const override {
fs::remove_all(this->get_path_internal()); rwfs::remove_all(this->path());
} }
void touch() const override { void touch() const override {
fs::create_directories(this->get_path_internal()); rwfs::create_directories(this->path());
} }
friend class TempFile; friend class TempFile;
}; };
@ -132,28 +128,28 @@ class TempFile : public Temp {
public: public:
TempFile() : Temp() { TempFile() : Temp() {
} }
TempFile(const TempDir &dirname) : Temp(dirname.get_path_internal()) { TempFile(const TempDir &dirname) : Temp(dirname.path()) {
} }
virtual ~TempFile() { virtual ~TempFile() {
this->remove(); this->remove();
} }
virtual void change_perms_readonly() const override { virtual void change_perms_readonly() const override {
fs::permissions(this->get_path_internal(), fs::perms::owner_read | rwfs::permissions(this->path(), rwfs::perms::owner_read |
fs::perms::group_read | rwfs::perms::group_read |
fs::perms::others_read); rwfs::perms::others_read);
} }
virtual void remove() const override { virtual void remove() const override {
fs::remove_all(this->get_path_internal()); rwfs::remove_all(this->path());
} }
virtual void touch() const override { virtual void touch() const override {
std::ofstream ofs(this->path(), std::ios::out | std::ios::app); std::ofstream ofs(this->path().string(), std::ios::out | std::ios::app);
ofs.close(); ofs.close();
} }
template <typename T> template <typename T>
bool append(T t) const { bool append(T t) const {
// Append argument at the end of the file. // Append argument at the end of the file.
// File is open/closes repeatedly. Not optimal. // File is open/closes repeatedly. Not optimal.
std::ofstream ofs(this->path(), std::ios::out | std::ios::app); std::ofstream ofs(this->path().string(), std::ios::out | std::ios::app);
ofs << t; ofs << t;
ofs.close(); ofs.close();
return ofs.good(); return ofs.good();
@ -162,7 +158,7 @@ public:
bool write(T t) const { bool write(T t) const {
// Write the argument to the file, discarding all contents. // Write the argument to the file, discarding all contents.
// File is open/closes repeatedly. Not optimal. // File is open/closes repeatedly. Not optimal.
std::ofstream ofs(this->path(), std::ios::out | std::ios::trunc); std::ofstream ofs(this->path().string(), std::ios::out | std::ios::trunc);
ofs << t; ofs << t;
ofs.close(); ofs.close();
return ofs.good(); return ofs.good();
@ -188,72 +184,78 @@ BOOST_AUTO_TEST_CASE(test_stripWhitespace) {
BOOST_AUTO_TEST_CASE(test_TempDir) { BOOST_AUTO_TEST_CASE(test_TempDir) {
// Check the behavior of TempFile // Check the behavior of TempFile
TempDir tempDir; TempDir tempDir;
BOOST_CHECK_EQUAL(tempDir.exists(), false); BOOST_CHECK(!tempDir.exists());
tempDir.touch(); tempDir.touch();
BOOST_CHECK_EQUAL(tempDir.exists(), true); BOOST_CHECK(tempDir.exists());
tempDir.remove(); tempDir.remove();
BOOST_CHECK_EQUAL(tempDir.exists(), false); BOOST_CHECK(!tempDir.exists());
tempDir.touch(); tempDir.touch();
BOOST_CHECK_EQUAL(tempDir.exists(), true); BOOST_CHECK(tempDir.exists());
TempDir tempChildDir(tempDir); TempDir tempChildDir(tempDir);
BOOST_CHECK_EQUAL(tempChildDir.exists(), false); BOOST_CHECK(!tempChildDir.exists());
tempChildDir.touch(); tempChildDir.touch();
BOOST_CHECK_EQUAL(tempChildDir.exists(), true); BOOST_CHECK(tempChildDir.exists());
tempDir.remove(); tempDir.remove();
BOOST_CHECK_EQUAL(tempChildDir.exists(), false); BOOST_CHECK(!tempChildDir.exists());
BOOST_CHECK_EQUAL(tempDir.exists(), false); BOOST_CHECK(!tempDir.exists());
tempChildDir.touch(); tempChildDir.touch();
BOOST_CHECK_EQUAL(tempChildDir.exists(), true); BOOST_CHECK(tempChildDir.exists());
std::string path; rwfs::path path;
{ {
TempDir tempLocal; TempDir tempLocal;
tempLocal.touch(); tempLocal.touch();
BOOST_CHECK_EQUAL(tempLocal.exists(), true); BOOST_CHECK(tempLocal.exists());
path = tempLocal.path(); path = tempLocal.path();
} }
BOOST_CHECK_EQUAL(fs::exists(path), false); BOOST_CHECK(!rwfs::exists(path));
} }
BOOST_AUTO_TEST_CASE(test_TempFile) { BOOST_AUTO_TEST_CASE(test_TempFile) {
// Check the behavior of TempFile // Check the behavior of TempFile
TempFile tempFile; TempFile tempFile;
BOOST_CHECK_EQUAL(tempFile.exists(), false); BOOST_CHECK(!tempFile.exists());
tempFile.touch(); tempFile.touch();
BOOST_CHECK_EQUAL(tempFile.exists(), true); BOOST_CHECK(tempFile.exists());
tempFile.remove(); tempFile.remove();
BOOST_CHECK_EQUAL(tempFile.exists(), false); BOOST_CHECK(!tempFile.exists());
tempFile.touch(); tempFile.touch();
BOOST_CHECK_EQUAL(tempFile.exists(), true); BOOST_CHECK(tempFile.exists());
tempFile.remove(); tempFile.remove();
BOOST_CHECK_EQUAL(tempFile.append("abc"), true); BOOST_CHECK(tempFile.append("abc"));
BOOST_CHECK_EQUAL(tempFile.append("def"), true); BOOST_CHECK(tempFile.append("def"));
BOOST_CHECK_EQUAL(tempFile.exists(), true); BOOST_CHECK(tempFile.exists());
tempFile.touch(); tempFile.touch();
std::ifstream ifs(tempFile.path()); std::ifstream ifs(tempFile.path().string());
std::string line; std::string line;
std::getline(ifs, line); std::getline(ifs, line);
BOOST_CHECK_EQUAL(line, "abcdef"); BOOST_CHECK_EQUAL(line, "abcdef");
tempFile.change_perms_readonly(); tempFile.change_perms_readonly();
BOOST_CHECK_EQUAL(tempFile.write("abc"), false); BOOST_CHECK(!tempFile.write("abc"));
BOOST_CHECK_EQUAL(tempFile.append("def"), false); BOOST_CHECK(!tempFile.append("def"));
std::string path; rwfs::path path;
{ {
TempFile tempLocal; TempFile tempLocal;
tempLocal.touch(); tempLocal.touch();
BOOST_CHECK_EQUAL(tempLocal.exists(), true); BOOST_CHECK(tempLocal.exists());
path = tempLocal.path(); path = tempLocal.path();
} }
BOOST_CHECK_EQUAL(fs::exists(path), false); BOOST_CHECK(!rwfs::exists(path));
}
BOOST_AUTO_TEST_CASE(test_config_initial) {
// Test an initial config
GameConfig cfg;
BOOST_CHECK(!cfg.isValid());
} }
BOOST_AUTO_TEST_CASE(test_config_valid) { BOOST_AUTO_TEST_CASE(test_config_valid) {
@ -263,7 +265,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(config.isValid()); BOOST_CHECK(config.isValid());
BOOST_CHECK_EQUAL(config.getParseResult().type(), BOOST_CHECK_EQUAL(config.getParseResult().type(),
@ -274,7 +277,7 @@ BOOST_AUTO_TEST_CASE(test_config_valid) {
BOOST_CHECK_EQUAL(config.getGameDataPath(), "/dev/test"); BOOST_CHECK_EQUAL(config.getGameDataPath(), "/dev/test");
BOOST_CHECK_EQUAL(config.getGameLanguage(), "american"); BOOST_CHECK_EQUAL(config.getGameLanguage(), "american");
BOOST_CHECK_EQUAL(config.getInputInvertY(), true); BOOST_CHECK(config.getInputInvertY());
} }
BOOST_AUTO_TEST_CASE(test_config_valid_modified) { BOOST_AUTO_TEST_CASE(test_config_valid_modified) {
@ -286,7 +289,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid_modified) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(config.isValid()); BOOST_CHECK(config.isValid());
BOOST_CHECK_EQUAL(config.getParseResult().type(), BOOST_CHECK_EQUAL(config.getParseResult().type(),
@ -295,7 +299,7 @@ BOOST_AUTO_TEST_CASE(test_config_valid_modified) {
0); 0);
BOOST_CHECK_EQUAL(config.getParseResult().getKeysInvalidData().size(), 0); BOOST_CHECK_EQUAL(config.getParseResult().getKeysInvalidData().size(), 0);
BOOST_CHECK_EQUAL(config.getInputInvertY(), false); BOOST_CHECK(!config.getInputInvertY());
BOOST_CHECK_EQUAL(config.getGameDataPath(), "Liberty City"); BOOST_CHECK_EQUAL(config.getGameDataPath(), "Liberty City");
} }
@ -307,7 +311,8 @@ BOOST_AUTO_TEST_CASE(test_config_save) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(config.isValid()); BOOST_CHECK(config.isValid());
@ -318,7 +323,8 @@ BOOST_AUTO_TEST_CASE(test_config_save) {
BOOST_CHECK(writeResult.isValid()); BOOST_CHECK(writeResult.isValid());
BOOST_CHECK(tempFile.exists()); BOOST_CHECK(tempFile.exists());
GameConfig config2(tempFile.filename(), tempFile.dirname()); GameConfig config2;
config2.loadFile(tempFile.path());
BOOST_CHECK_EQUAL(config2.getGameDataPath(), "Liberty City"); BOOST_CHECK_EQUAL(config2.getGameDataPath(), "Liberty City");
simpleConfig_t cfg2 = readConfig(tempFile.path()); simpleConfig_t cfg2 = readConfig(tempFile.path());
@ -334,7 +340,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid_unknown_keys) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(config.isValid()); BOOST_CHECK(config.isValid());
@ -355,7 +362,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid_unknown_keys) {
tempFile.remove(); tempFile.remove();
config.saveConfig(); config.saveConfig();
GameConfig config2(tempFile.filename(), tempFile.dirname()); GameConfig config2;
config2.loadFile(tempFile.path());
const auto &unknownData2 = config2.getParseResult().getUnknownData(); const auto &unknownData2 = config2.getParseResult().getUnknownData();
BOOST_CHECK_EQUAL(unknownData2.size(), 2); BOOST_CHECK_EQUAL(unknownData2.size(), 2);
@ -379,8 +387,9 @@ BOOST_AUTO_TEST_CASE(test_config_save_readonly) {
tempFile.append(cfg); tempFile.append(cfg);
tempFile.change_perms_readonly(); tempFile.change_perms_readonly();
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
BOOST_CHECK_EQUAL(config.isValid(), true); config.loadFile(tempFile.path());
BOOST_CHECK(config.isValid());
auto writeResult = config.saveConfig(); auto writeResult = config.saveConfig();
BOOST_CHECK(!writeResult.isValid()); BOOST_CHECK(!writeResult.isValid());
@ -393,13 +402,15 @@ BOOST_AUTO_TEST_CASE(test_config_valid_default) {
TempFile tempFile; TempFile tempFile;
BOOST_CHECK(!tempFile.exists()); BOOST_CHECK(!tempFile.exists());
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());
auto defaultINI = config.getDefaultINIString(); auto defaultINI = config.getDefaultINIString();
tempFile.append(defaultINI); tempFile.append(defaultINI);
BOOST_CHECK(tempFile.exists());
config = GameConfig(tempFile.filename(), tempFile.dirname()); config.loadFile(tempFile.path());
BOOST_CHECK(config.isValid()); BOOST_CHECK(config.isValid());
} }
@ -411,7 +422,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_emptykey) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());
const auto &parseResult = config.getParseResult(); const auto &parseResult = config.getParseResult();
@ -427,7 +439,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_duplicate) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());
const auto &parseResult = config.getParseResult(); const auto &parseResult = config.getParseResult();
@ -443,7 +456,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_required_missing) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());
@ -465,7 +479,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_wrong_type) {
TempFile tempFile; TempFile tempFile;
tempFile.append(cfg); tempFile.append(cfg);
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());
@ -487,7 +502,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_empty) {
tempFile.touch(); tempFile.touch();
BOOST_CHECK(tempFile.exists()); BOOST_CHECK(tempFile.exists());
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());
@ -504,7 +520,9 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_nodir) {
BOOST_CHECK(!tempDir.exists()); BOOST_CHECK(!tempDir.exists());
BOOST_CHECK(!tempFile.exists()); BOOST_CHECK(!tempFile.exists());
GameConfig config(tempFile.filename(), tempFile.dirname());
GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());
@ -518,7 +536,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_nonexisting) {
TempFile tempFile; TempFile tempFile;
BOOST_CHECK(!tempFile.exists()); BOOST_CHECK(!tempFile.exists());
GameConfig config(tempFile.filename(), tempFile.dirname()); GameConfig config;
config.loadFile(tempFile.path());
BOOST_CHECK(!config.isValid()); BOOST_CHECK(!config.isValid());

View File

@ -4,6 +4,8 @@
#if RW_TEST_WITH_DATA #if RW_TEST_WITH_DATA
std::string Global::getGamePath() { std::string Global::getGamePath() {
return GameConfig("openrw.ini").getGameDataPath(); GameConfig config;
config.loadFile(GameConfig::getDefaultConfigPath() / "openrw.ini");
return config.getGameDataPath();
} }
#endif #endif