Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
20 kB · 414 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415#include "apps/openmw/options.hpp"
#include <components/files/configurationmanager.hpp>#include <components/files/conversion.hpp>
#include <gmock/gmock.h>#include <gtest/gtest.h>
#include <boost/program_options/options_description.hpp>#include <boost/program_options/variables_map.hpp>
#include <algorithm>#include <array>#include <string>#include <utility>#include <vector>
namespace{ using namespace testing; using namespace OpenMW;
namespace bpo = boost::program_options;
template <class T, std::size_t size> std::string makeString(const T (&range)[size]) { static_assert(size > 0); return std::string(std::begin(range), std::end(range) - 1); }
template <class... Args> std::vector<std::string> generateSupportedCharacters(Args&&... args) { std::vector<std::string> result; (result.emplace_back(makeString(args)), ...); for (int i = 1; i <= std::numeric_limits<char>::max(); ++i) if (i != '&' && i != '"' && i != ' ' && i != '\n') result.push_back(std::string(1, static_cast<char>(i))); return result; }
MATCHER_P(IsPath, v, "") { return Files::pathToUnicodeString(arg) == v; }
template <class T> void parseArgs(const T& arguments, bpo::variables_map& variables, bpo::options_description& description) { Files::parseArgs(static_cast<int>(arguments.size()), arguments.data(), variables, description); }
TEST(OpenMWOptionsFromArguments, should_support_equality_to_separate_flag_and_value) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame=save.omwsave" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save.omwsave"); }
TEST(OpenMWOptionsFromArguments, should_support_single_word_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", "save.omwsave" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save.omwsave"); }
TEST(OpenMWOptionsFromArguments, should_support_multi_component_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", "/home/user/openmw/save.omwsave" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "/home/user/openmw/save.omwsave"); }
TEST(OpenMWOptionsFromArguments, should_support_windows_multi_component_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", R"(C:\OpenMW\save.omwsave)" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(C:\OpenMW\save.omwsave)"); }
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_spaces) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", "my save.omwsave" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "my save.omwsave"); }
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_octothorpe) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", "my#save.omwsave" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "my#save.omwsave"); }
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_at_sign) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", "my@save.omwsave" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "my@save.omwsave"); }
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_quote) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", R"(my"save.omwsave)" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(my"save.omwsave)"); }
TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", R"("save".omwsave)" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(save)"); }
TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path_with_escaped_quote_by_ampersand) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", R"("save&".omwsave")" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(save".omwsave)"); }
TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path_with_escaped_ampersand) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", R"("save.omwsave&&")" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save.omwsave&"); }
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_ampersand) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", "save&.omwsave" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save&.omwsave"); }
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_multiple_quotes) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", R"(my"save".omwsave)" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(my"save".omwsave)"); }
TEST(OpenMWOptionsFromArguments, should_compose_data) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--data", "1", "--data", "2" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_THAT(variables["data"].as<Files::MaybeQuotedPathContainer>(), ElementsAre(IsPath("1"), IsPath("2"))); }
TEST(OpenMWOptionsFromArguments, should_compose_data_from_single_flag) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--data", "1", "2" }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_THAT(variables["data"].as<Files::MaybeQuotedPathContainer>(), ElementsAre(IsPath("1"), IsPath("2"))); }
TEST(OpenMWOptionsFromArguments, should_throw_on_multiple_load_savegame) { bpo::options_description description = makeOptionsDescription(); const std::array arguments{ "openmw", "--load-savegame", "1.omwsave", "--load-savegame", "2.omwsave" }; bpo::variables_map variables; EXPECT_THROW(parseArgs(arguments, variables, description), std::exception); }
struct OpenMWOptionsFromArgumentsStrings : TestWithParam<std::string> { };
TEST_P(OpenMWOptionsFromArgumentsStrings, should_support_paths_with_certain_characters_in_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); const std::string path = "save_" + std::string(GetParam()) + ".omwsave"; const std::string pathArgument = "\"" + path + "\""; const std::array arguments{ "openmw", "--load-savegame", pathArgument.c_str() }; bpo::variables_map variables; parseArgs(arguments, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), path); }
INSTANTIATE_TEST_SUITE_P(SupportedCharacters, OpenMWOptionsFromArgumentsStrings, ValuesIn(generateSupportedCharacters(u8"👍", u8"Ъ", u8"Ǽ", "\n")));
TEST(OpenMWOptionsFromConfig, should_support_single_word_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("load-savegame=save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save.omwsave"); }
TEST(OpenMWOptionsFromConfig, should_strip_quotes_from_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame="save.omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save.omwsave"); }
TEST(OpenMWOptionsFromConfig, should_strip_outer_quotes_from_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame=""save".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), ""); }
TEST(OpenMWOptionsFromConfig, should_strip_quotes_from_load_savegame_path_with_space) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame="my save.omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "my save.omwsave"); }
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_octothorpe) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("load-savegame=save#.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save#.omwsave"); }
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_at_sign) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("load-savegame=save@.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save@.omwsave"); }
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_quote) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame=save".omwsave)"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(save".omwsave)"); }
TEST(OpenMWOptionsFromConfig, should_support_confusing_savegame_path_with_lots_going_on) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame="one &"two"three".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(one "two)"); }
TEST(OpenMWOptionsFromConfig, should_support_confusing_savegame_path_with_even_more_going_on) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame="one &"two"three ".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(one "two)"); }
TEST(OpenMWOptionsFromConfig, should_ignore_commented_option) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("#load-savegame=save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), ""); }
TEST(OpenMWOptionsFromConfig, should_ignore_whitespace_prefixed_commented_option) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(" \t#load-savegame=save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), ""); }
TEST(OpenMWOptionsFromConfig, should_support_whitespace_around_option) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(" load-savegame = save.omwsave "); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save.omwsave"); }
TEST(OpenMWOptionsFromConfig, should_throw_on_multiple_load_savegame) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("load-savegame=1.omwsave\nload-savegame=2.omwsave"); bpo::variables_map variables; EXPECT_THROW(Files::parseConfig(stream, variables, description), std::exception); }
TEST(OpenMWOptionsFromConfig, should_support_multi_component_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("load-savegame=/home/user/openmw/save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "/home/user/openmw/save.omwsave"); }
TEST(OpenMWOptionsFromConfig, should_support_windows_multi_component_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame=C:\OpenMW\save.omwsave)"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(C:\OpenMW\save.omwsave)"); }
TEST(OpenMWOptionsFromConfig, should_compose_data) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("data=1\ndata=2"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_THAT(variables["data"].as<Files::MaybeQuotedPathContainer>(), ElementsAre(IsPath("1"), IsPath("2"))); }
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_escaped_quote_by_ampersand) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame="save&".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ( Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), R"(save".omwsave)"); }
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_escaped_ampersand) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream(R"(load-savegame="save.omwsave&&")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save.omwsave&"); }
TEST(OpenMWOptionsFromConfig, should_support_load_savegame_path_with_ampersand) { bpo::options_description description = makeOptionsDescription(); std::istringstream stream("load-savegame=save&.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save&.omwsave"); }
struct OpenMWOptionsFromConfigStrings : TestWithParam<std::string> { };
TEST_P(OpenMWOptionsFromConfigStrings, should_support_paths_with_certain_characters_in_load_savegame_path) { bpo::options_description description = makeOptionsDescription(); const std::string path = "save_" + std::string(GetParam()) + ".omwsave"; std::istringstream stream("load-savegame=\"" + path + "\""); bpo::variables_map variables; Files::parseConfig(stream, variables, description); EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), path); }
INSTANTIATE_TEST_SUITE_P(SupportedCharacters, OpenMWOptionsFromConfigStrings, ValuesIn(generateSupportedCharacters(u8"👍", u8"Ъ", u8"Ǽ")));}