diff --git a/.travis.yml b/.travis.yml index cbc67911..e202e8fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,7 @@ before_script: - cmake .. -DPROJECT_STATIC_RUNTIME=OFF -DBUILD_SHARED_LIBS=OFF script: - - '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && npm test || false' + - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then npm test; fi - make tests && ./tests before_deploy: diff --git a/CMakeLists.txt b/CMakeLists.txt index d94e2d44..50315406 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,34 +215,49 @@ set (LOOT_TESTS_SRC ${LOOT_SRC} "${CMAKE_SOURCE_DIR}/src/gui/loot_state.cpp" "${CMAKE_SOURCE_DIR}/src/tests/main.cpp") -set (LOOT_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/tests/fixtures.h" +set (LOOT_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/tests/base_game_test.h" "${CMAKE_SOURCE_DIR}/src/tests/printers.h" + + "${CMAKE_SOURCE_DIR}/src/tests/api/api_game_operations_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_apply_load_order_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_create_db_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_db_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_eval_lists_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_dirty_info_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_masterlist_revision_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_plugin_messages_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_plugin_tags_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_tag_map_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_load_lists_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_sort_plugins_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_update_masterlist_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/loot_write_minimal_list_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/test_api.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/test_loot_db.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/game/test_game.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/game/test_game_cache.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/game/test_game_settings.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/game/test_load_order_handler.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/test_git_helper.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/test_helpers.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/test_language.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/test_version.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/test_yaml_set_helpers.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_condition_grammar.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_conditional_metadata.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_file.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_location.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_message.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_message_content.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_plugin_dirty_info.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_plugin_metadata.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/test_tag.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/plugin/test_plugin.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/test_metadata_list.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/test_masterlist.h" - "${CMAKE_SOURCE_DIR}/src/tests/backend/test_plugin_sorter.h" - "${CMAKE_SOURCE_DIR}/src/tests/gui/test_loot_settings.h" - "${CMAKE_SOURCE_DIR}/src/tests/gui/test_loot_state.h") + + "${CMAKE_SOURCE_DIR}/src/tests/backend/game/game_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/game/game_cache_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/game/game_settings_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/game/load_order_handler_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/git_helper_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/helpers_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/language_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/version_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/yaml_set_helpers_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/condition_grammar_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/conditional_metadata_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/file_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/location_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/message_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/message_content_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/plugin_dirty_info_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/plugin_metadata_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata/tag_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/plugin/plugin_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/masterlist_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/metadata_list_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/backend/plugin_sorter_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/gui/loot_settings_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/gui/loot_state_test.h") source_group("Header Files\\backend" FILES ${LOOT_HEADERS}) source_group("Header Files\\gui" FILES ${LOOT_GUI_HEADERS}) @@ -289,8 +304,8 @@ ENDIF () # GCC and MinGW settings. IF (CMAKE_COMPILER_IS_GNUCXX) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -std=c++11") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -std=c++14") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++14") IF (PROJECT_STATIC_RUNTIME) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc") set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++ -static-libgcc") diff --git a/include/loot/api.h b/include/loot/api.h index dbb599bf..13ecf8fe 100644 --- a/include/loot/api.h +++ b/include/loot/api.h @@ -277,7 +277,6 @@ extern "C" *************************************************************************/ /**@{*/ - LOOT_API extern const unsigned int loot_lang_any; /**< Tells the API to select messages of any language. */ LOOT_API extern const unsigned int loot_lang_english; /**< Tells the API to preferentially select English messages. */ LOOT_API extern const unsigned int loot_lang_spanish; /**< Tells the API to preferentially select Spanish messages */ LOOT_API extern const unsigned int loot_lang_russian; /**< Tells the API to preferentially select Russian messages. */ diff --git a/src/api/api.cpp b/src/api/api.cpp index 5fc92793..dd7eacaf 100644 --- a/src/api/api.cpp +++ b/src/api/api.cpp @@ -69,7 +69,6 @@ const unsigned int loot_message_warn = loot::Message::warn; const unsigned int loot_message_error = loot::Message::error; // LOOT message languages. -const unsigned int loot_lang_any = loot::Language::any; const unsigned int loot_lang_english = loot::Language::english; const unsigned int loot_lang_spanish = loot::Language::spanish; const unsigned int loot_lang_russian = loot::Language::russian; @@ -283,8 +282,7 @@ LOOT_API unsigned int loot_load_lists(loot_db * const db, const char * const mas LOOT_API unsigned int loot_eval_lists(loot_db * const db, const unsigned int language) { if (db == nullptr) return c_error(loot_error_invalid_args, "Null pointer passed."); - if (language != loot_lang_any - && language != loot_lang_english + if (language != loot_lang_english && language != loot_lang_spanish && language != loot_lang_russian && language != loot_lang_french @@ -336,7 +334,7 @@ LOOT_API unsigned int loot_sort_plugins(loot_db * const db, //Sort plugins into their load order. loot::PluginSorter sorter; - db->setPluginNames(sorter.Sort(*db, loot_lang_any)); + db->setPluginNames(sorter.Sort(*db, loot::Language::english)); } catch (loot::error &e) { return c_error(e); diff --git a/src/api/loot_db.cpp b/src/api/loot_db.cpp index 411abb6d..97f3f84a 100644 --- a/src/api/loot_db.cpp +++ b/src/api/loot_db.cpp @@ -92,7 +92,7 @@ void loot_db::setPluginMessages(const std::list& pluginMessages) size_t i = 0; for (const auto& message : pluginMessages) { - pluginMessageStrings[i] = message.ChooseContent(loot::Language::any).Str(); + pluginMessageStrings[i] = message.ChooseContent(loot::Language::english).Str(); cPluginMessages[i].type = message.Type(); cPluginMessages[i].message = pluginMessageStrings[i].c_str(); diff --git a/src/backend/helpers/git_helper.cpp b/src/backend/helpers/git_helper.cpp index 88608072..53e9baa0 100644 --- a/src/backend/helpers/git_helper.cpp +++ b/src/backend/helpers/git_helper.cpp @@ -316,15 +316,14 @@ namespace loot { return revision; } - bool IsFileDifferent(const boost::filesystem::path& repoRoot, const std::string& filename) { - GitHelper git; - - if (!git.IsRepository(repoRoot)) { + bool GitHelper::IsFileDifferent(const boost::filesystem::path& repoRoot, const std::string& filename) { + if (!IsRepository(repoRoot)) { BOOST_LOG_TRIVIAL(info) << "Unknown masterlist revision: Git repository missing."; throw error(error::ok, lc::translate("Unknown: Git repository missing")); } BOOST_LOG_TRIVIAL(debug) << "Existing repository found, attempting to open it."; + GitHelper git; git.Call(git_repository_open(&git.repo, repoRoot.string().c_str())); // Perform a git diff, then iterate the deltas to see if one exists for the masterlist. diff --git a/src/backend/helpers/git_helper.h b/src/backend/helpers/git_helper.h index 4250f42e..0e115f77 100644 --- a/src/backend/helpers/git_helper.h +++ b/src/backend/helpers/git_helper.h @@ -43,6 +43,8 @@ namespace loot { static bool IsRepository(const boost::filesystem::path& path); + static bool IsFileDifferent(const boost::filesystem::path& repoRoot, const std::string& filename); + // Clones a repository and opens it. Sets 'repo'. void Clone(const boost::filesystem::path& path, const std::string& url); @@ -85,7 +87,5 @@ namespace loot { // created by libgit2. static void FixRepoPermissions(const boost::filesystem::path& path); }; - - bool IsFileDifferent(const boost::filesystem::path& repoRoot, const std::string& filename); } #endif diff --git a/src/backend/helpers/language.cpp b/src/backend/helpers/language.cpp index f0c094b5..270162de 100644 --- a/src/backend/helpers/language.cpp +++ b/src/backend/helpers/language.cpp @@ -25,7 +25,6 @@ #include "language.h" namespace loot { - const unsigned int Language::any = 0; const unsigned int Language::english = 1; const unsigned int Language::spanish = 2; const unsigned int Language::russian = 3; diff --git a/src/backend/helpers/language.h b/src/backend/helpers/language.h index c651fb3e..d656a96b 100644 --- a/src/backend/helpers/language.h +++ b/src/backend/helpers/language.h @@ -39,7 +39,6 @@ namespace loot { std::string Name() const; std::string Locale() const; - static const unsigned int any; // This shouldn't be used as a selectable language, just for when picking any string in a message. static const unsigned int english; static const unsigned int spanish; static const unsigned int russian; diff --git a/src/backend/masterlist.cpp b/src/backend/masterlist.cpp index 621f1bc1..e1303b58 100644 --- a/src/backend/masterlist.cpp +++ b/src/backend/masterlist.cpp @@ -77,7 +77,7 @@ namespace loot { info.date = out.str(); BOOST_LOG_TRIVIAL(trace) << "Diffing masterlist HEAD and working copy."; - if (IsFileDifferent(path.parent_path(), path.filename().string())) { + if (GitHelper::IsFileDifferent(path.parent_path(), path.filename().string())) { info.revision += string(" ") + lc::translate("(edited)").str(); info.date += string(" ") + lc::translate("(edited)").str(); } @@ -203,7 +203,7 @@ namespace loot { // must be performed and the checked-out file parsed. if (!updateBranchHead) { BOOST_LOG_TRIVIAL(trace) << "Local and remote branch heads are equal."; - if (!IsFileDifferent(repoPath, filename)) { + if (!GitHelper::IsFileDifferent(repoPath, filename)) { BOOST_LOG_TRIVIAL(info) << "Local branch and masterlist file are already up to date."; return false; } diff --git a/src/backend/metadata/location.cpp b/src/backend/metadata/location.cpp index 16f97619..ce68a6d3 100644 --- a/src/backend/metadata/location.cpp +++ b/src/backend/metadata/location.cpp @@ -31,8 +31,6 @@ using namespace std; namespace loot { Location::Location() {} - Location::Location(const std::string& url) : _url(url) {} - Location::Location(const std::string& url, const std::string& name) : _url(url), _name(name) {} bool Location::operator < (const Location& rhs) const { diff --git a/src/backend/metadata/location.h b/src/backend/metadata/location.h index 7a2adb91..080d2880 100644 --- a/src/backend/metadata/location.h +++ b/src/backend/metadata/location.h @@ -33,8 +33,7 @@ namespace loot { class Location { public: Location(); - Location(const std::string& url); - Location(const std::string& url, const std::string& name); + Location(const std::string& url, const std::string& name = ""); bool operator < (const Location& rhs) const; bool operator == (const Location& rhs) const; diff --git a/src/backend/metadata/message.cpp b/src/backend/metadata/message.cpp index cbb89eea..a5d0eb8e 100644 --- a/src/backend/metadata/message.cpp +++ b/src/backend/metadata/message.cpp @@ -24,6 +24,7 @@ #include "message.h" #include "../helpers/language.h" +#include "../error.h" #include @@ -42,7 +43,17 @@ namespace loot { } Message::Message(const unsigned int type, const std::vector& content, - const std::string& condition) : _type(type), _content(content), ConditionalMetadata(condition) {} + const std::string& condition) : _type(type), _content(content), ConditionalMetadata(condition) { + if (content.size() > 1) { + bool englishStringExists = false; + for (const auto &mc : content) { + if (mc.Language() == loot::Language::english) + englishStringExists = true; + } + if (!englishStringExists) + throw loot::error(error::invalid_args, "bad conversion: multilingual messages must contain an English content string"); + } + } bool Message::operator < (const Message& rhs) const { if (!_content.empty() && !rhs.Content().empty()) @@ -68,7 +79,7 @@ namespace loot { BOOST_LOG_TRIVIAL(trace) << "Choosing message content."; if (_content.empty()) return MessageContent(); - else if (_content.size() == 1 || language == Language::any) + else if (_content.size() == 1) return _content[0]; else { MessageContent english; diff --git a/src/backend/metadata/plugin_metadata.cpp b/src/backend/metadata/plugin_metadata.cpp index edd37110..7cde12b5 100644 --- a/src/backend/metadata/plugin_metadata.cpp +++ b/src/backend/metadata/plugin_metadata.cpp @@ -50,7 +50,8 @@ namespace loot { if (plugin.HasNameOnly()) return; - //For 'enabled' and 'priority' metadata, use the given plugin's values, but if the 'priority' user value is not explicit, ignore it. + // For 'enabled' and 'priority' metadata, use the given plugin's values, + // but if the 'priority' user value is not explicit, ignore it. enabled = plugin.Enabled(); if (plugin.IsPriorityExplicit()) { Priority(plugin.Priority()); @@ -58,29 +59,24 @@ namespace loot { _isPriorityExplicit = true; } - //Merge the following. If any files in the source already exist in the destination, they will be skipped. Files have display strings and condition strings which aren't considered when comparing them, so will be lost if the plugin being merged in has additional data in these strings. - std::set files = plugin.LoadAfter(); - loadAfter.insert(files.begin(), files.end()); + // Merge the following. If any files in the source already exist in the + // destination, they will be skipped. Files have display strings and + // condition strings which aren't considered when comparing them, so + // will be lost if the plugin being merged in has additional data in + // these strings. + loadAfter.insert(begin(plugin.loadAfter), end(plugin.loadAfter)); + requirements.insert(begin(plugin.requirements), end(plugin.requirements)); + incompatibilities.insert(begin(plugin.incompatibilities), end(plugin.incompatibilities)); - files = plugin.Reqs(); - requirements.insert(files.begin(), files.end()); + // Merge Bash Tags too. Conditions are ignored during comparison, but + // if a tag is added and removed, both instances will be in the set. + tags.insert(begin(plugin.tags), end(plugin.tags)); - files = plugin.Incs(); - incompatibilities.insert(files.begin(), files.end()); + // Messages are in an ordered list, and should be fully merged. + messages.insert(end(messages), begin(plugin.messages), end(plugin.messages)); - //Merge Bash Tags too. Conditions are ignored during comparison, but if a tag is added and removed, both instances will be in the set. - std::set bashTags = plugin.Tags(); - tags.insert(bashTags.begin(), bashTags.end()); - - //Messages are in an ordered list, and should be fully merged. - std::list pMessages = plugin.Messages(); - messages.insert(messages.end(), pMessages.begin(), pMessages.end()); - - set dirtyInfo = plugin.DirtyInfo(); - _dirtyInfo.insert(dirtyInfo.begin(), dirtyInfo.end()); - - set locations = plugin.Locations(); - _locations.insert(locations.begin(), locations.end()); + _dirtyInfo.insert(begin(plugin._dirtyInfo), end(plugin._dirtyInfo)); + _locations.insert(begin(plugin._locations), end(plugin._locations)); return; } @@ -96,19 +92,28 @@ namespace loot { } //Compare this plugin against the given plugin. - set files = plugin.LoadAfter(); set filesDiff; - set_symmetric_difference(loadAfter.begin(), loadAfter.end(), files.begin(), files.end(), inserter(filesDiff, filesDiff.begin())); + set_symmetric_difference(begin(loadAfter), + end(loadAfter), + begin(plugin.loadAfter), + end(plugin.loadAfter), + inserter(filesDiff, begin(filesDiff))); p.LoadAfter(filesDiff); filesDiff.clear(); - files = plugin.Reqs(); - set_symmetric_difference(requirements.begin(), requirements.end(), files.begin(), files.end(), inserter(filesDiff, filesDiff.begin())); + set_symmetric_difference(begin(requirements), + end(requirements), + begin(plugin.requirements), + end(plugin.requirements), + inserter(filesDiff, begin(filesDiff))); p.Reqs(filesDiff); filesDiff.clear(); - files = plugin.Incs(); - set_symmetric_difference(incompatibilities.begin(), incompatibilities.end(), files.begin(), files.end(), inserter(filesDiff, filesDiff.begin())); + set_symmetric_difference(begin(incompatibilities), + end(incompatibilities), + begin(plugin.incompatibilities), + end(plugin.incompatibilities), + inserter(filesDiff, begin(filesDiff))); p.Incs(filesDiff); list msgs1 = plugin.Messages(); @@ -116,22 +121,35 @@ namespace loot { msgs1.sort(); msgs2.sort(); list mDiff; - set_symmetric_difference(msgs2.begin(), msgs2.end(), msgs1.begin(), msgs1.end(), inserter(mDiff, mDiff.begin())); + set_symmetric_difference(begin(msgs2), + end(msgs2), + begin(msgs1), + end(msgs1), + inserter(mDiff, begin(mDiff))); p.Messages(mDiff); - set bashTags = plugin.Tags(); set tagDiff; - set_symmetric_difference(tags.begin(), tags.end(), bashTags.begin(), bashTags.end(), inserter(tagDiff, tagDiff.begin())); + set_symmetric_difference(begin(tags), + end(tags), + begin(plugin.tags), + end(plugin.tags), + inserter(tagDiff, begin(tagDiff))); p.Tags(tagDiff); - set dirtyInfo = plugin.DirtyInfo(); set dirtDiff; - set_symmetric_difference(_dirtyInfo.begin(), _dirtyInfo.end(), dirtyInfo.begin(), dirtyInfo.end(), inserter(dirtDiff, dirtDiff.begin())); + set_symmetric_difference(begin(_dirtyInfo), + end(_dirtyInfo), + begin(plugin._dirtyInfo), + end(plugin._dirtyInfo), + inserter(dirtDiff, begin(dirtDiff))); p.DirtyInfo(dirtDiff); - set locations = plugin.Locations(); set locationsDiff; - set_symmetric_difference(_locations.begin(), _locations.end(), locations.begin(), locations.end(), inserter(locationsDiff, locationsDiff.begin())); + set_symmetric_difference(begin(_locations), + end(_locations), + begin(plugin._locations), + end(plugin._locations), + inserter(locationsDiff, begin(locationsDiff))); p.Locations(locationsDiff); return p; @@ -142,19 +160,28 @@ namespace loot { PluginMetadata p(*this); //Compare this plugin against the given plugin. - set files = plugin.LoadAfter(); set filesDiff; - set_difference(loadAfter.begin(), loadAfter.end(), files.begin(), files.end(), inserter(filesDiff, filesDiff.begin())); + set_difference(begin(loadAfter), + end(loadAfter), + begin(plugin.loadAfter), + end(plugin.loadAfter), + inserter(filesDiff, begin(filesDiff))); p.LoadAfter(filesDiff); filesDiff.clear(); - files = plugin.Reqs(); - set_difference(requirements.begin(), requirements.end(), files.begin(), files.end(), inserter(filesDiff, filesDiff.begin())); + set_difference(begin(requirements), + end(requirements), + begin(plugin.requirements), + end(plugin.requirements), + inserter(filesDiff, begin(filesDiff))); p.Reqs(filesDiff); filesDiff.clear(); - files = plugin.Incs(); - set_difference(incompatibilities.begin(), incompatibilities.end(), files.begin(), files.end(), inserter(filesDiff, filesDiff.begin())); + set_difference(begin(incompatibilities), + end(incompatibilities), + begin(plugin.incompatibilities), + end(plugin.incompatibilities), + inserter(filesDiff, begin(filesDiff))); p.Incs(filesDiff); list msgs1 = plugin.Messages(); @@ -162,22 +189,35 @@ namespace loot { msgs1.sort(); msgs2.sort(); list mDiff; - set_difference(msgs2.begin(), msgs2.end(), msgs1.begin(), msgs1.end(), inserter(mDiff, mDiff.begin())); + set_difference(begin(msgs2), + end(msgs2), + begin(msgs1), + end(msgs1), + inserter(mDiff, begin(mDiff))); p.Messages(mDiff); - set bashTags = plugin.Tags(); set tagDiff; - set_difference(tags.begin(), tags.end(), bashTags.begin(), bashTags.end(), inserter(tagDiff, tagDiff.begin())); + set_difference(begin(tags), + end(tags), + begin(plugin.tags), + end(plugin.tags), + inserter(tagDiff, begin(tagDiff))); p.Tags(tagDiff); - set dirtyInfo = plugin.DirtyInfo(); set dirtDiff; - set_difference(_dirtyInfo.begin(), _dirtyInfo.end(), dirtyInfo.begin(), dirtyInfo.end(), inserter(dirtDiff, dirtDiff.begin())); + set_difference(begin(_dirtyInfo), + end(_dirtyInfo), + begin(plugin._dirtyInfo), + end(plugin._dirtyInfo), + inserter(dirtDiff, begin(dirtDiff))); p.DirtyInfo(dirtDiff); - set locations = plugin.Locations(); set locationsDiff; - set_difference(_locations.begin(), _locations.end(), locations.begin(), locations.end(), inserter(locationsDiff, locationsDiff.begin())); + set_difference(begin(_locations), + end(_locations), + begin(plugin._locations), + end(plugin._locations), + inserter(locationsDiff, begin(locationsDiff))); p.Locations(locationsDiff); return p; diff --git a/src/backend/plugin/plugin.cpp b/src/backend/plugin/plugin.cpp index bfac994b..ac54106c 100644 --- a/src/backend/plugin/plugin.cpp +++ b/src/backend/plugin/plugin.cpp @@ -92,15 +92,21 @@ namespace loot { _isActive = game.IsPluginActive(Name()); // Get whether the plugin loads an archive (BSA/BA2) or not. + string archiveExtension; + if (game.Id() == Game::fo4) + archiveExtension = ".ba2"; + else + archiveExtension = ".bsa"; + if (game.Id() == Game::tes5 || game.Id() == Game::fo4) { // Skyrim and Fallout 4 plugins only load archives that exactly match their basename. - _loadsArchive = boost::filesystem::exists(game.DataPath() / (Name().substr(0, Name().length() - 3) + "bsa")); + _loadsArchive = boost::filesystem::exists(game.DataPath() / (Name().substr(0, Name().length() - 4) + archiveExtension)); } else if (game.Id() != Game::tes4 || boost::iends_with(Name(), ".esp")) { //Oblivion .esp files and FO3, FNV plugins can load BSAs which begin with the plugin basename. string basename = Name().substr(0, Name().length() - 4); for (boost::filesystem::directory_iterator it(game.DataPath()); it != boost::filesystem::directory_iterator(); ++it) { - if (it->path().extension().string() == ".bsa" && boost::istarts_with(it->path().filename().string(), basename)) { + if (boost::iequals(it->path().extension().string(), archiveExtension) && boost::istarts_with(it->path().filename().string(), basename)) { _loadsArchive = true; break; } diff --git a/src/tests/api/api_game_operations_test.h b/src/tests/api/api_game_operations_test.h new file mode 100644 index 00000000..3216f91f --- /dev/null +++ b/src/tests/api/api_game_operations_test.h @@ -0,0 +1,118 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2013-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_API_GAME_OPERATIONS_TEST +#define LOOT_TEST_API_GAME_OPERATIONS_TEST + +#include "../base_game_test.h" + +namespace loot { + namespace test { + class ApiGameOperationsTest : public BaseGameTest { + protected: + ApiGameOperationsTest() : + db(nullptr), + masterlistPath(localPath / "masterlist.yaml"), + noteMessage("Do not clean ITM records, they are intentional and required for the mod to function."), + warningMessage("Check you are using v2+. If not, Update. v1 has a severe bug with the Mystic Emporium disappearing."), + errorMessage("Obsolete. Remove this and install Enhanced Weather.") {} + + inline virtual void SetUp() { + BaseGameTest::SetUp(); + + ASSERT_FALSE(boost::filesystem::exists(masterlistPath)); + + ASSERT_EQ(loot_ok, loot_create_db(&db, GetParam(), dataPath.parent_path().string().c_str(), localPath.string().c_str())); + } + + inline virtual void TearDown() { + BaseGameTest::TearDown(); + + ASSERT_NO_THROW(loot_destroy_db(db)); + + // The masterlist may have been created during the test, so delete it. + ASSERT_NO_THROW(boost::filesystem::remove(masterlistPath)); + } + + inline void generateMasterlist() { + using std::endl; + + boost::filesystem::ofstream masterlist(masterlistPath); + masterlist + << "plugins:" << endl + << " - name: " << blankEsm << endl + << " after:" << endl + << " - " << masterFile << endl + << " msg:" << endl + << " - type: say" << endl + << " content: '" << noteMessage << "'" << endl + << " tag:" << endl + << " - Actors.ACBS" << endl + << " - Actors.AIData" << endl + << " - '-C.Water'" << endl + << " - name: " << blankDifferentEsm << endl + << " after:" << endl + << " - " << blankMasterDependentEsm << endl + << " msg:" << endl + << " - type: warn" << endl + << " content: '" << warningMessage << "'" << endl + << " dirty:" << endl + << " - crc: 0x7d22f9df" << endl + << " util: TES4Edit" << endl + << " udr: 4" << endl + << " - name: " << blankDifferentEsp << endl + << " after:" << endl + << " - " << blankPluginDependentEsp << endl + << " msg:" << endl + << " - type: error" << endl + << " content: '" << errorMessage << "'" << endl + << " - name: " << blankEsp << endl + << " after:" << endl + << " - " << blankDifferentMasterDependentEsp << endl + << " - name: " << blankDifferentMasterDependentEsp << endl + << " after:" << endl + << " - " << blankMasterDependentEsp << endl + << " msg:" << endl + << " - type: say" << endl + << " content: '" << noteMessage << "'" << endl + << " - type: warn" << endl + << " content: '" << warningMessage << "'" << endl + << " - type: error" << endl + << " content: '" << errorMessage << "'" << endl; + + masterlist.close(); + } + + loot_db * db; + + const boost::filesystem::path masterlistPath; + + const std::string noteMessage; + const std::string warningMessage; + const std::string errorMessage; + }; + } +} + +#endif diff --git a/src/tests/api/loot_apply_load_order_test.h b/src/tests/api/loot_apply_load_order_test.h new file mode 100644 index 00000000..e798890f --- /dev/null +++ b/src/tests/api/loot_apply_load_order_test.h @@ -0,0 +1,77 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_APPLY_LOAD_ORDER +#define LOOT_TEST_LOOT_APPLY_LOAD_ORDER + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_apply_load_order_test : public ApiGameOperationsTest {}; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_apply_load_order_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_apply_load_order_test, shouldReturnAnInvalidArgsIfTheDbOrLoadOrderPointersAreNull) { + const char * loadOrder[1] = { + masterFile.c_str(), + }; + size_t numPlugins = 0; + + EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(NULL, loadOrder, numPlugins)); + EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(db, NULL, numPlugins)); + } + + TEST_P(loot_apply_load_order_test, shouldReturnOkIfLoadOrderGivenIsNotEmpty) { + const char * loadOrder[11] = { + masterFile.c_str(), + blankEsm.c_str(), + blankMasterDependentEsm.c_str(), + blankDifferentEsm.c_str(), + blankDifferentMasterDependentEsm.c_str(), + blankMasterDependentEsp.c_str(), + blankDifferentMasterDependentEsp.c_str(), + blankEsp.c_str(), + blankPluginDependentEsp.c_str(), + blankDifferentEsp.c_str(), + blankDifferentPluginDependentEsp.c_str(), + }; + size_t numPlugins = 11; + + EXPECT_EQ(loot_ok, loot_apply_load_order(db, loadOrder, numPlugins)); + } + } +} + +#endif diff --git a/src/tests/api/loot_create_db_test.h b/src/tests/api/loot_create_db_test.h new file mode 100644 index 00000000..09434741 --- /dev/null +++ b/src/tests/api/loot_create_db_test.h @@ -0,0 +1,97 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_CREATE_DB +#define LOOT_TEST_LOOT_CREATE_DB + +#include "../include/loot/api.h" +#include "tests/base_game_test.h" + +#include + +namespace loot { + namespace test { + class loot_create_db_test : public BaseGameTest { + protected: + loot_create_db_test() : + db(nullptr) {} + + inline virtual void TearDown() { + BaseGameTest::TearDown(); + + ASSERT_NO_THROW(loot_destroy_db(db)); + } + + loot_db * db; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_create_db_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_create_db_test, shouldSucceedIfPassedValidParametersWithRelativePaths) { + EXPECT_EQ(loot_ok, loot_create_db(&db, GetParam(), dataPath.parent_path().string().c_str(), localPath.string().c_str())); + EXPECT_NE(nullptr, db); + } + + TEST_P(loot_create_db_test, shouldSucceedIfPassedValidParametersWithAbsolutePaths) { + boost::filesystem::path game = boost::filesystem::current_path() / dataPath.parent_path(); + boost::filesystem::path local = boost::filesystem::current_path() / localPath; + + EXPECT_EQ(loot_ok, loot_create_db(&db, GetParam(), game.string().c_str(), local.string().c_str())); + EXPECT_NE(nullptr, db); + } + + TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedANullPointer) { + EXPECT_EQ(loot_error_invalid_args, loot_create_db(NULL, GetParam(), dataPath.parent_path().string().c_str(), localPath.string().c_str())); + } + + TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedAnInvalidGameType) { + EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, UINT_MAX, dataPath.parent_path().string().c_str(), localPath.string().c_str())); + } + + TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedAGamePathThatDoesNotExist) { + EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, GetParam(), missingPath.string().c_str(), localPath.string().c_str())); + } + + TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedALocalPathThatDoesNotExist) { + EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, GetParam(), dataPath.parent_path().string().c_str(), missingPath.string().c_str())); + } + +#ifdef _WIN32 + TEST_P(loot_create_db_test, shouldReturnOkIfPassedANullLocalPathPointer) { + EXPECT_EQ(loot_ok, loot_create_db(&db, GetParam(), dataPath.parent_path().string().c_str(), NULL)); + } +#endif + } +} + +#endif diff --git a/src/tests/api/test_loot_db.h b/src/tests/api/loot_db_test.h similarity index 77% rename from src/tests/api/test_loot_db.h rename to src/tests/api/loot_db_test.h index 01f3bd8b..e5d5ed6c 100644 --- a/src/tests/api/test_loot_db.h +++ b/src/tests/api/loot_db_test.h @@ -27,30 +27,52 @@ along with LOOT. If not, see #include "api/loot_db.h" #include "backend/game/game_settings.h" -#include "tests/fixtures.h" +#include "tests/base_game_test.h" namespace loot { namespace test { - class loot_db_test : public SkyrimTest { + class loot_db_test : public BaseGameTest { protected: - virtual void SetUp() { - SkyrimTest::SetUp(); + loot_db_test() : + db(nullptr) {} - db = new loot_db(Game::tes5, dataPath.parent_path().string().c_str(), localPath.string().c_str()); + virtual void SetUp() { + BaseGameTest::SetUp(); + + db = new loot_db(GetParam(), dataPath.parent_path().string().c_str(), localPath.string().c_str()); } + + inline virtual void TearDown() { + BaseGameTest::TearDown(); + + delete db; + } + + loot_db * db; }; - TEST_F(loot_db_test, settingRevisionIdStringShouldCopyIt) { + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_db_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_db_test, settingRevisionIdStringShouldCopyIt) { db->setRevisionIdString("id"); EXPECT_STREQ("id", db->getRevisionIdString()); } - TEST_F(loot_db_test, settingRevisionDateStringShouldCopyIt) { + TEST_P(loot_db_test, settingRevisionDateStringShouldCopyIt) { db->setRevisionDateString("date"); EXPECT_STREQ("date", db->getRevisionDateString()); } - TEST_F(loot_db_test, settingPluginNamesShouldCopyThem) { + TEST_P(loot_db_test, settingPluginNamesShouldCopyThem) { db->setPluginNames(std::vector({ PluginMetadata("Blank.esm"), PluginMetadata("Blank.esp"), @@ -61,7 +83,7 @@ namespace loot { EXPECT_STREQ("Blank.esp", db->getPluginNames()[1]); } - TEST_F(loot_db_test, settingPluginNamesTwiceShouldOverwriteTheFirstDataSet) { + TEST_P(loot_db_test, settingPluginNamesTwiceShouldOverwriteTheFirstDataSet) { db->setPluginNames(std::vector({ PluginMetadata("Blank.esm"), PluginMetadata("Blank.esp"), @@ -76,7 +98,7 @@ namespace loot { EXPECT_STREQ("Blank - Different.esp", db->getPluginNames()[1]); } - TEST_F(loot_db_test, addingNewBashTagsToTheMapShouldAppendThem) { + TEST_P(loot_db_test, addingNewBashTagsToTheMapShouldAppendThem) { db->addBashTagsToMap({ "C.Climate", "Relev", @@ -87,7 +109,7 @@ namespace loot { EXPECT_STREQ("Relev", db->getBashTagMap()[1]); } - TEST_F(loot_db_test, addingAnExistingBashTagToTheMapShouldNotDuplicateIt) { + TEST_P(loot_db_test, addingAnExistingBashTagToTheMapShouldNotDuplicateIt) { db->addBashTagsToMap({ "C.Climate", "Relev", @@ -99,11 +121,11 @@ namespace loot { EXPECT_STREQ("Relev", db->getBashTagMap()[1]); } - TEST_F(loot_db_test, gettingABashTagsUidForATagThatIsNotInTheMapShouldThrow) { + TEST_P(loot_db_test, gettingABashTagsUidForATagThatIsNotInTheMapShouldThrow) { EXPECT_ANY_THROW(db->getBashTagUid("Relev")); } - TEST_F(loot_db_test, gettingABashTagsUidShouldReturnItsTagMapIndex) { + TEST_P(loot_db_test, gettingABashTagsUidShouldReturnItsTagMapIndex) { db->addBashTagsToMap({ "C.Climate", "Relev", @@ -112,11 +134,11 @@ namespace loot { EXPECT_EQ(1, db->getBashTagUid("Relev")); } - TEST_F(loot_db_test, clearingAnEmptyBashTagMapShouldDoNothing) { + TEST_P(loot_db_test, clearingAnEmptyBashTagMapShouldDoNothing) { EXPECT_NO_THROW(db->clearBashTagMap()); } - TEST_F(loot_db_test, clearingABashTagMapShouldEmptyIt) { + TEST_P(loot_db_test, clearingABashTagMapShouldEmptyIt) { db->addBashTagsToMap({ "C.Climate", "Relev", @@ -126,7 +148,7 @@ namespace loot { EXPECT_TRUE(db->getBashTagMap().empty()); } - TEST_F(loot_db_test, clearingABashTagMapShouldAffectExistingReferences) { + TEST_P(loot_db_test, clearingABashTagMapShouldAffectExistingReferences) { db->addBashTagsToMap({ "C.Climate", "Relev", @@ -137,13 +159,13 @@ namespace loot { EXPECT_TRUE(bashTagMap.empty()); } - TEST_F(loot_db_test, settingAddedTagsWithNoTagMapShouldThrow) { + TEST_P(loot_db_test, settingAddedTagsWithNoTagMapShouldThrow) { EXPECT_ANY_THROW(db->setAddedTags({ "Relev", })); } - TEST_F(loot_db_test, gettingSetAddedTagsShouldReturnTheirUids) { + TEST_P(loot_db_test, gettingSetAddedTagsShouldReturnTheirUids) { db->addBashTagsToMap({ "C.Climate", "Relev", @@ -158,13 +180,13 @@ namespace loot { }), db->getAddedTagIds()); } - TEST_F(loot_db_test, settingRemovedTagsWithNoTagMapShouldThrow) { + TEST_P(loot_db_test, settingRemovedTagsWithNoTagMapShouldThrow) { EXPECT_ANY_THROW(db->setRemovedTags({ "Relev", })); } - TEST_F(loot_db_test, gettingSetRemovedTagsShouldReturnTheirUids) { + TEST_P(loot_db_test, gettingSetRemovedTagsShouldReturnTheirUids) { db->addBashTagsToMap({ "C.Climate", "Relev", @@ -179,7 +201,7 @@ namespace loot { }), db->getRemovedTagIds()); } - TEST_F(loot_db_test, settingPluginMessagesShouldCopyThem) { + TEST_P(loot_db_test, settingPluginMessagesShouldCopyThem) { db->setPluginMessages(std::list({ Message(Message::warn, "Test 1"), Message(Message::error, "Test 2"), @@ -192,7 +214,7 @@ namespace loot { EXPECT_STREQ("Test 2", db->getPluginMessages()[1].message); } - TEST_F(loot_db_test, settingPluginMessagesTwiceShouldOverwriteTheFirstDataSet) { + TEST_P(loot_db_test, settingPluginMessagesTwiceShouldOverwriteTheFirstDataSet) { db->setPluginMessages(std::list({ Message(Message::warn, "Test 1"), Message(Message::error, "Test 2"), @@ -212,7 +234,7 @@ namespace loot { EXPECT_STREQ("Test 5", db->getPluginMessages()[2].message); } - TEST_F(loot_db_test, clearingArraysShouldEmptyPluginNamesTagIdsAndMessages) { + TEST_P(loot_db_test, clearingArraysShouldEmptyPluginNamesTagIdsAndMessages) { db->setPluginMessages(std::list({ Message(Message::warn, "Test 1"), Message(Message::error, "Test 2"), @@ -247,7 +269,7 @@ namespace loot { EXPECT_TRUE(db->getRemovedTagIds().empty()); } - TEST_F(loot_db_test, clearingArraysShouldNotEmptyBashTagMap) { + TEST_P(loot_db_test, clearingArraysShouldNotEmptyBashTagMap) { db->addBashTagsToMap({ "C.Climate", "Relev", diff --git a/src/tests/api/loot_eval_lists_test.h b/src/tests/api/loot_eval_lists_test.h new file mode 100644 index 00000000..bca329fc --- /dev/null +++ b/src/tests/api/loot_eval_lists_test.h @@ -0,0 +1,87 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_EVAL_LISTS +#define LOOT_TEST_LOOT_EVAL_LISTS + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_eval_lists_test : public ApiGameOperationsTest {}; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_eval_lists_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_eval_lists_test, shouldReturnAnInvalidArgsErrorIfPassedANullPointer) { + EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(NULL, loot_lang_english)); + } + + TEST_P(loot_eval_lists_test, shouldReturnAnInvalidArgsErrorIfPassedAnInvalidLanguageCode) { + EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(db, UINT_MAX)); + } + + TEST_P(loot_eval_lists_test, shouldReturnOkForAllLanguagesWithNoListsLoaded) { + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_spanish)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_russian)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_french)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_chinese)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_polish)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_brazilian_portuguese)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_finnish)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_german)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_danish)); + } + + TEST_P(loot_eval_lists_test, shouldReturnOKForAllLanguagesWithAMasterlistLoaded) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_spanish)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_russian)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_french)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_chinese)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_polish)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_brazilian_portuguese)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_finnish)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_german)); + EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_danish)); + } + } +} + +#endif diff --git a/src/tests/api/loot_get_dirty_info_test.h b/src/tests/api/loot_get_dirty_info_test.h new file mode 100644 index 00000000..286512b4 --- /dev/null +++ b/src/tests/api/loot_get_dirty_info_test.h @@ -0,0 +1,81 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_GET_DIRTY_INFO +#define LOOT_TEST_LOOT_GET_DIRTY_INFO + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_get_dirty_info_test : public ApiGameOperationsTest { + protected: + loot_get_dirty_info_test() : + needsCleaning(0) {} + + unsigned int needsCleaning; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_get_dirty_info_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_get_dirty_info_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(NULL, blankEsp.c_str(), &needsCleaning)); + EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(db, NULL, &needsCleaning)); + EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(db, blankEsp.c_str(), NULL)); + } + + TEST_P(loot_get_dirty_info_test, shouldReturnOkAndOutputUnknownForAPluginWithNoDirtyInfo) { + EXPECT_EQ(loot_ok, loot_get_dirty_info(db, blankEsp.c_str(), &needsCleaning)); + EXPECT_EQ(loot_needs_cleaning_unknown, needsCleaning); + } + + TEST_P(loot_get_dirty_info_test, shouldReturnOkAndOutputYesForAPluginWithDirtyInfo) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_get_dirty_info(db, blankDifferentEsm.c_str(), &needsCleaning)); + EXPECT_EQ(loot_needs_cleaning_yes, needsCleaning); + } + + TEST_P(loot_get_dirty_info_test, shouldReturnOkAndOutputNoForAPluginWithADoNotCleanMessage) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_get_dirty_info(db, blankEsm.c_str(), &needsCleaning)); + EXPECT_EQ(loot_needs_cleaning_no, needsCleaning); + } + } +} + +#endif diff --git a/src/tests/api/loot_get_masterlist_revision_test.h b/src/tests/api/loot_get_masterlist_revision_test.h new file mode 100644 index 00000000..5894c540 --- /dev/null +++ b/src/tests/api/loot_get_masterlist_revision_test.h @@ -0,0 +1,119 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_GET_MASTERLIST_REVISION +#define LOOT_TEST_LOOT_GET_MASTERLIST_REVISION + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_get_masterlist_revision_test : public ApiGameOperationsTest { + protected: + loot_get_masterlist_revision_test() : + revisionId("foo"), + revisionDate("bar"), + isModified(true), + updated(false) {} + + const char * revisionId; + const char * revisionDate; + bool isModified; + bool updated; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_get_masterlist_revision_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_get_masterlist_revision_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(NULL, masterlistPath.string().c_str(), false, &revisionId, &revisionDate, &isModified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, NULL, false, &revisionId, &revisionDate, &isModified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, NULL, &revisionDate, &isModified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionId, NULL, &isModified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionId, &revisionDate, NULL)); + } + + TEST_P(loot_get_masterlist_revision_test, shouldSucceedIfNoMasterlistIsPresent) { + EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionId, &revisionDate, &isModified)); + EXPECT_EQ(NULL, revisionId); + EXPECT_EQ(NULL, revisionDate); + EXPECT_FALSE(isModified); + } + + TEST_P(loot_get_masterlist_revision_test, shouldSucceedIfANonVersionControlledMasterlistIsPresent) { + ASSERT_NO_THROW(generateMasterlist()); + EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionId, &revisionDate, &isModified)); + EXPECT_EQ(NULL, revisionId); + EXPECT_EQ(NULL, revisionDate); + EXPECT_FALSE(isModified); + } + + TEST_P(loot_get_masterlist_revision_test, shouldOutputLongStringsAndBooleanFalseIfAVersionControlledMasterlistIsPresentAndGetShortIdParameterIsFalse) { + ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); + + EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionId, &revisionDate, &isModified)); + EXPECT_STRNE(NULL, revisionId); + EXPECT_EQ(40, strlen(revisionId)); + EXPECT_STRNE(NULL, revisionDate); + EXPECT_EQ(10, strlen(revisionDate)); + EXPECT_FALSE(isModified); + } + + TEST_P(loot_get_masterlist_revision_test, shouldOutputShortStringsAndBooleanFalseIfAVersionControlledMasterlistIsPresentAndGetShortIdParameterIsTrue) { + ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); + + EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionId, &revisionDate, &isModified)); + EXPECT_STRNE(NULL, revisionId); + EXPECT_GE(size_t(40), strlen(revisionId)); + EXPECT_LE(size_t(7), strlen(revisionId)); + EXPECT_STRNE(NULL, revisionDate); + EXPECT_EQ(10, strlen(revisionDate)); + EXPECT_FALSE(isModified); + } + + TEST_P(loot_get_masterlist_revision_test, shouldSucceedIfAnEditedVersionControlledMasterlistIsPresent) { + ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); + + ASSERT_NO_THROW(generateMasterlist()); + EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionId, &revisionDate, &isModified)); + + EXPECT_STRNE(NULL, revisionId); + EXPECT_EQ(40, strlen(revisionId)); + EXPECT_STRNE(NULL, revisionDate); + EXPECT_EQ(10, strlen(revisionDate)); + EXPECT_TRUE(isModified); + } + } +} + +#endif diff --git a/src/tests/api/loot_get_plugin_messages_test.h b/src/tests/api/loot_get_plugin_messages_test.h new file mode 100644 index 00000000..9ddd0283 --- /dev/null +++ b/src/tests/api/loot_get_plugin_messages_test.h @@ -0,0 +1,113 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_GET_PLUGIN_MESSAGES +#define LOOT_TEST_LOOT_GET_PLUGIN_MESSAGES + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_get_plugin_messages_test : public ApiGameOperationsTest { + protected: + loot_get_plugin_messages_test() : + messages(nullptr), + numMessages(0) {} + + const loot_message * messages; + size_t numMessages; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_get_plugin_messages_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_get_plugin_messages_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(NULL, blankEsp.c_str(), &messages, &numMessages)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db, NULL, &messages, &numMessages)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db, blankEsp.c_str(), NULL, &numMessages)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db, blankEsp.c_str(), &messages, NULL)); + } + + TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputANullArrayIfAPluginWithNoMessagesIsQueried) { + EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, blankEsp.c_str(), &messages, &numMessages)); + EXPECT_EQ(0, numMessages); + EXPECT_EQ(NULL, messages); + } + + TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputANoteIfAPluginWithANoteMessageIsQueried) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, blankEsm.c_str(), &messages, &numMessages)); + ASSERT_EQ(1, numMessages); + EXPECT_EQ(loot_message_say, messages[0].type); + EXPECT_STREQ(noteMessage.c_str(), messages[0].message); + } + + TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputAWarningIfAPluginWithAWarningMessageIsQueried) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, blankDifferentEsm.c_str(), &messages, &numMessages)); + ASSERT_EQ(1, numMessages); + EXPECT_EQ(loot_message_warn, messages[0].type); + EXPECT_STREQ(warningMessage.c_str(), messages[0].message); + } + + TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputAnErrorIfAPluginWithAnErrorMessageIsQueried) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, blankDifferentEsp.c_str(), &messages, &numMessages)); + ASSERT_EQ(1, numMessages); + EXPECT_EQ(loot_message_error, messages[0].type); + EXPECT_STREQ(errorMessage.c_str(), messages[0].message); + } + + TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputMultipleMessagesIfAPluginWithMultipleMessagesIsQueried) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, blankDifferentMasterDependentEsp.c_str(), &messages, &numMessages)); + ASSERT_EQ(3, numMessages); + EXPECT_EQ(loot_message_say, messages[0].type); + EXPECT_STREQ(noteMessage.c_str(), messages[0].message); + EXPECT_EQ(loot_message_warn, messages[1].type); + EXPECT_STREQ(warningMessage.c_str(), messages[1].message); + EXPECT_EQ(loot_message_error, messages[2].type); + EXPECT_STREQ(errorMessage.c_str(), messages[2].message); + } + } +} + +#endif diff --git a/src/tests/api/loot_get_plugin_tags_test.h b/src/tests/api/loot_get_plugin_tags_test.h new file mode 100644 index 00000000..49026914 --- /dev/null +++ b/src/tests/api/loot_get_plugin_tags_test.h @@ -0,0 +1,140 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_GET_PLUGIN_TAGS +#define LOOT_TEST_LOOT_GET_PLUGIN_TAGS + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_get_plugin_tags_test : public ApiGameOperationsTest { + protected: + loot_get_plugin_tags_test() : + tagMap(nullptr), + numTags(0), + added(nullptr), + removed(nullptr), + numAdded(0), + numRemoved(0), + modified(false) {} + + const char * const * tagMap; + size_t numTags; + + const unsigned int * added; + const unsigned int * removed; + size_t numAdded; + size_t numRemoved; + bool modified; + + void getTagMap() { + ASSERT_EQ(loot_ok, loot_get_tag_map(db, &tagMap, &numTags)); + + ASSERT_EQ(3, numTags); + ASSERT_STREQ("Actors.ACBS", tagMap[0]); + ASSERT_STREQ("Actors.AIData", tagMap[1]); + ASSERT_STREQ("C.Water", tagMap[2]); + } + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_get_plugin_tags_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_get_plugin_tags_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(NULL, blankEsm.c_str(), &added, &numAdded, &removed, &numRemoved, &modified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, NULL, &added, &numAdded, &removed, &numRemoved, &modified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, blankEsm.c_str(), NULL, &numAdded, &removed, &numRemoved, &modified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, blankEsm.c_str(), &added, NULL, &removed, &numRemoved, &modified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, blankEsm.c_str(), &added, &numAdded, NULL, &numRemoved, &modified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, blankEsm.c_str(), &added, &numAdded, &removed, NULL, &modified)); + EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, blankEsm.c_str(), &added, &numAdded, &removed, &numRemoved, NULL)); + } + + TEST_P(loot_get_plugin_tags_test, shouldReturnANoTagMapIfCalledBeforeATagMapHasBeenGotten) { + EXPECT_EQ(loot_error_no_tag_map, loot_get_plugin_tags(db, blankEsm.c_str(), &added, &numAdded, &removed, &numRemoved, &modified)); + } + + TEST_P(loot_get_plugin_tags_test, shouldReturnOkAndOutputEmptyNonModifiedArraysIfAPluginWithoutTagsIsQueried) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + getTagMap(); + + EXPECT_EQ(loot_ok, loot_get_plugin_tags(db, blankEsp.c_str(), &added, &numAdded, &removed, &numRemoved, &modified)); + + EXPECT_EQ(0, numAdded); + EXPECT_EQ(NULL, added); + EXPECT_EQ(0, numRemoved); + EXPECT_EQ(NULL, removed); + EXPECT_FALSE(modified); + } + + TEST_P(loot_get_plugin_tags_test, shouldReturnOkAndNonEmptyNonModifiedArraysIfAPluginWithTagsIsQueried) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + getTagMap(); + + EXPECT_EQ(loot_ok, loot_get_plugin_tags(db, blankEsm.c_str(), &added, &numAdded, &removed, &numRemoved, &modified)); + + // The values are tag map indices, check they match up as expected. + ASSERT_EQ(2, numAdded); + EXPECT_EQ(0, added[0]); + EXPECT_EQ(1, added[1]); + + ASSERT_EQ(1, numRemoved); + EXPECT_EQ(2, removed[0]); + + EXPECT_FALSE(modified); + } + + TEST_P(loot_get_plugin_tags_test, shouldReturnOkAndNonEmptyModifiedArraysIfAPluginWithTagsIsQueriedAndMetadataWasAlsoLoadedFromAUserlist) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), masterlistPath.string().c_str())); + getTagMap(); + + EXPECT_EQ(loot_ok, loot_get_plugin_tags(db, blankEsm.c_str(), &added, &numAdded, &removed, &numRemoved, &modified)); + + // The values are tag map indices, check they match up as expected. + ASSERT_EQ(2, numAdded); + EXPECT_EQ(0, added[0]); + EXPECT_EQ(1, added[1]); + + ASSERT_EQ(1, numRemoved); + EXPECT_EQ(2, removed[0]); + + EXPECT_TRUE(modified); + } + } +} + +#endif diff --git a/src/tests/api/loot_get_tag_map_test.h b/src/tests/api/loot_get_tag_map_test.h new file mode 100644 index 00000000..3bf76771 --- /dev/null +++ b/src/tests/api/loot_get_tag_map_test.h @@ -0,0 +1,80 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_GET_TAG_MAP +#define LOOT_TEST_LOOT_GET_TAG_MAP + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_get_tag_map_test : public ApiGameOperationsTest { + protected: + loot_get_tag_map_test() : + tagMap(nullptr), + numTags(0) {} + + const char * const * tagMap; + size_t numTags; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_get_tag_map_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_get_tag_map_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_get_tag_map(NULL, &tagMap, &numTags)); + EXPECT_EQ(loot_error_invalid_args, loot_get_tag_map(db, NULL, &numTags)); + EXPECT_EQ(loot_error_invalid_args, loot_get_tag_map(db, &tagMap, NULL)); + } + + TEST_P(loot_get_tag_map_test, shouldReturnOkAndOutputAnEmptyTagMapIfNoMetadataHasBeenLoaded) { + EXPECT_EQ(loot_ok, loot_get_tag_map(db, &tagMap, &numTags)); + EXPECT_EQ(0, numTags); + EXPECT_EQ(NULL, tagMap); + } + + TEST_P(loot_get_tag_map_test, shouldReturnOKAndOutputANonEmptyTagMapIfMetadataHasBeenLoaded) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_get_tag_map(db, &tagMap, &numTags)); + + ASSERT_EQ(3, numTags); + EXPECT_STREQ("Actors.ACBS", tagMap[0]); + EXPECT_STREQ("Actors.AIData", tagMap[1]); + EXPECT_STREQ("C.Water", tagMap[2]); + } + } +} + +#endif diff --git a/src/tests/api/loot_load_lists_test.h b/src/tests/api/loot_load_lists_test.h new file mode 100644 index 00000000..6c29bced --- /dev/null +++ b/src/tests/api/loot_load_lists_test.h @@ -0,0 +1,82 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_LOAD_LISTS +#define LOOT_TEST_LOOT_LOAD_LISTS + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_load_lists_test : public ApiGameOperationsTest { + protected: + loot_load_lists_test() : + userlistPath(localPath / "userlist.yaml") {} + + inline virtual void TearDown() { + ApiGameOperationsTest::TearDown(); + + // The userlist may have been created during the test, so delete it. + ASSERT_NO_THROW(boost::filesystem::remove(userlistPath)); + } + + boost::filesystem::path userlistPath; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_load_lists_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_load_lists_test, shouldReturnAnInvalidArgsErrorIfTheDbOrMasterlistPathArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_load_lists(NULL, masterlistPath.string().c_str(), NULL)); + EXPECT_EQ(loot_error_invalid_args, loot_load_lists(db, NULL, NULL)); + } + + TEST_P(loot_load_lists_test, shouldReturnAPathNotFoundErrorIfNoMasterlistIsPresent) { + EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + } + + TEST_P(loot_load_lists_test, shouldReturnAPathNotFoundErrorIfAMasterlistIsPresentButAUserlistDoesNotExistAtTheGivenPath) { + ASSERT_NO_THROW(generateMasterlist()); + EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db, masterlistPath.string().c_str(), userlistPath.string().c_str())); + } + + TEST_P(loot_load_lists_test, shouldReturnOkIfTheMasterlistAndUserlistAreBothPresent) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_NO_THROW(boost::filesystem::copy(masterlistPath, userlistPath)); + + EXPECT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), userlistPath.string().c_str())); + } + } +} + +#endif diff --git a/src/tests/api/loot_sort_plugins_test.h b/src/tests/api/loot_sort_plugins_test.h new file mode 100644 index 00000000..0cb9a831 --- /dev/null +++ b/src/tests/api/loot_sort_plugins_test.h @@ -0,0 +1,91 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_SORT_PLUGINS +#define LOOT_TEST_LOOT_SORT_PLUGINS + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_sort_plugins_test : public ApiGameOperationsTest { + protected: + loot_sort_plugins_test() : + sortedPlugins(nullptr), + numPlugins(0) {} + + const char * const * sortedPlugins; + size_t numPlugins; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_sort_plugins_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_sort_plugins_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(NULL, &sortedPlugins, &numPlugins)); + EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db, NULL, &numPlugins)); + EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db, &sortedPlugins, NULL)); + } + + TEST_P(loot_sort_plugins_test, shouldSucceedIfPassedValidArguments) { + std::list expectedOrder = { + masterFile, + blankEsm, + blankMasterDependentEsm, + blankDifferentEsm, + blankDifferentMasterDependentEsm, + blankMasterDependentEsp, + blankDifferentMasterDependentEsp, + blankEsp, + blankPluginDependentEsp, + blankDifferentEsp, + blankDifferentPluginDependentEsp, + }; + + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_sort_plugins(db, &sortedPlugins, &numPlugins)); + + ASSERT_EQ(expectedOrder.size(), numPlugins); + + size_t i = 0; + for (const auto& plugin : expectedOrder) { + EXPECT_EQ(plugin, sortedPlugins[i]); + ++i; + } + } + } +} + +#endif diff --git a/src/tests/api/loot_update_masterlist_test.h b/src/tests/api/loot_update_masterlist_test.h new file mode 100644 index 00000000..dc69f43e --- /dev/null +++ b/src/tests/api/loot_update_masterlist_test.h @@ -0,0 +1,108 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_UPDATE_MASTERLIST +#define LOOT_TEST_LOOT_UPDATE_MASTERLIST + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_update_masterlist_test : public ApiGameOperationsTest { + protected: + loot_update_masterlist_test() : + updated(false) {} + + inline virtual void TearDown() { + ApiGameOperationsTest::TearDown(); + + // Also remove the ".git" folder if it has been created. + ASSERT_NO_THROW(boost::filesystem::remove_all(masterlistPath.parent_path() / ".git")); + } + + bool updated; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_update_masterlist_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_update_masterlist_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) { + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(NULL, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, NULL, "https://github.com/loot/testing-metadata.git", "master", &updated)); + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), NULL, "master", &updated)); + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", NULL, &updated)); + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", NULL)); + } + + TEST_P(loot_update_masterlist_test, shouldReturnAnInvalidArgsErrorIfTheMasterlistPathGivenIsInvalid) { + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, ";//\?", "https://github.com/loot/testing-metadata.git", "master", &updated)); + } + + TEST_P(loot_update_masterlist_test, shouldReturnAnInvalidArgsErrorIfTheMasterlistPathGivenIsEmpty) { + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, "", "https://github.com/loot/testing-metadata.git", "master", &updated)); + } + + TEST_P(loot_update_masterlist_test, shouldReturnAGitErrorIfTheRepositoryUrlGivenCannotBeFound) { + EXPECT_EQ(loot_error_git_error, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/oblivion-does-not-exist.git", "master", &updated)); + } + + TEST_P(loot_update_masterlist_test, shouldReturnAnInvalidArgsErrorIfTheRepositoryUrlGivenIsEmpty) { + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "", "master", &updated)); + } + + TEST_P(loot_update_masterlist_test, shouldReturnAGitErrorIfTheRepositoryBranchGivenCannotBeFound) { + EXPECT_EQ(loot_error_git_error, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "missing-branch", &updated)); + } + + TEST_P(loot_update_masterlist_test, shouldReturnAnInvalidArgsErrorIfTheRepositoryBranchGivenIsEmpty) { + EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "", &updated)); + } + + TEST_P(loot_update_masterlist_test, shouldSucceedIfPassedValidParametersAndOutputTrueIfTheMasterlistWasUpdated) { + EXPECT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); + EXPECT_TRUE(updated); + EXPECT_TRUE(boost::filesystem::exists(masterlistPath)); + } + + TEST_P(loot_update_masterlist_test, shouldSucceedIfCalledRepeatedlyButOnlyOutputTrueForTheFirstCall) { + EXPECT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); + EXPECT_TRUE(updated); + + EXPECT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); + EXPECT_FALSE(updated); + EXPECT_TRUE(boost::filesystem::exists(masterlistPath)); + } + } +} + +#endif diff --git a/src/tests/api/loot_write_minimal_list_test.h b/src/tests/api/loot_write_minimal_list_test.h new file mode 100644 index 00000000..9c7061d3 --- /dev/null +++ b/src/tests/api/loot_write_minimal_list_test.h @@ -0,0 +1,132 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_LOOT_WRITE_MINIMAL_LIST +#define LOOT_TEST_LOOT_WRITE_MINIMAL_LIST + +#include "../include/loot/api.h" +#include "api_game_operations_test.h" + +namespace loot { + namespace test { + class loot_write_minimal_list_test : public ApiGameOperationsTest { + protected: + loot_write_minimal_list_test() : + outputPath(localPath / "minimal.yml") {} + + void SetUp() { + ApiGameOperationsTest::SetUp(); + + ASSERT_FALSE(boost::filesystem::exists(outputPath)); + } + + void TearDown() { + ApiGameOperationsTest::TearDown(); + + ASSERT_NO_THROW(boost::filesystem::remove(outputPath)); + } + + std::string getExpectedContent() const { + using std::endl; + + std::stringstream expectedContent; + expectedContent + << "plugins:" << endl + << " - name: '" << blankEsm << "'" << endl + << " tag:" << endl + << " - Actors.ACBS" << endl + << " - Actors.AIData" << endl + << " - -C.Water" << endl + << " - name: '" << blankDifferentEsm << "'" << endl + << " dirty:" << endl + << " - crc: 0x7d22f9df" << endl + << " util: 'TES4Edit'" << endl + << " udr: 4"; + + return expectedContent.str(); + } + + const boost::filesystem::path outputPath; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + loot_write_minimal_list_test, + ::testing::Values( + loot_game_tes4, + loot_game_tes5, + loot_game_fo3, + loot_game_fonv, + loot_game_fo4)); + + TEST_P(loot_write_minimal_list_test, shouldReturnAnInvalidArgsErrorIfAPointerArgumentIsNull) { + EXPECT_EQ(loot_error_invalid_args, loot_write_minimal_list(NULL, outputPath.string().c_str(), false)); + EXPECT_EQ(loot_error_invalid_args, loot_write_minimal_list(db, NULL, false)); + } + + TEST_P(loot_write_minimal_list_test, shouldReturnAFileWriteErrorIfThePathGivenIsInvalid) { + EXPECT_EQ(loot_error_file_write_fail, loot_write_minimal_list(db, "/:?*", false)); + } + + TEST_P(loot_write_minimal_list_test, shouldReturnOkAndWriteToFileIfArgumentsGivenAreValid) { + EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputPath.string().c_str(), false)); + EXPECT_TRUE(boost::filesystem::exists(outputPath)); + } + + TEST_P(loot_write_minimal_list_test, shouldReturnAFileWriteErrorIfTheFileAlreadyExistsAndTheOverwriteArgumentIsFalse) { + ASSERT_EQ(loot_ok, loot_write_minimal_list(db, outputPath.string().c_str(), false)); + ASSERT_TRUE(boost::filesystem::exists(outputPath)); + + EXPECT_EQ(loot_error_file_write_fail, loot_write_minimal_list(db, outputPath.string().c_str(), false)); + } + + TEST_P(loot_write_minimal_list_test, shouldReturnOkAndWriteToFileIfTheArgumentsAreValidAndTheOverwriteArgumentIsTrue) { + EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputPath.string().c_str(), true)); + EXPECT_TRUE(boost::filesystem::exists(outputPath)); + } + + TEST_P(loot_write_minimal_list_test, shouldReturnOkIfTheFileAlreadyExistsAndTheOverwriteArgumentIsTrue) { + ASSERT_EQ(loot_ok, loot_write_minimal_list(db, outputPath.string().c_str(), false)); + ASSERT_TRUE(boost::filesystem::exists(outputPath)); + + EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputPath.string().c_str(), true)); + } + + TEST_P(loot_write_minimal_list_test, shouldWriteOnlyBashTagsAndDirtyInfo) { + ASSERT_NO_THROW(generateMasterlist()); + ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); + + EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputPath.string().c_str(), true)); + + boost::filesystem::ifstream in(outputPath); + std::stringstream content; + content << in.rdbuf(); + + EXPECT_EQ(getExpectedContent(), content.str()); + } + } +} + +#endif diff --git a/src/tests/api/test_api.h b/src/tests/api/test_api.h index c58060f5..94f6a4b0 100644 --- a/src/tests/api/test_api.h +++ b/src/tests/api/test_api.h @@ -26,604 +26,72 @@ along with LOOT. If not, see #define LOOT_TEST_API #include "../include/loot/api.h" -#include "tests/fixtures.h" -#include +namespace loot { + namespace test { + TEST(loot_get_version, shouldReturnAnInvalidArgsErrorIfPassedNullPointers) { + unsigned int vMajor, vMinor, vPatch; + EXPECT_EQ(loot_error_invalid_args, loot_get_version(&vMajor, NULL, NULL)); + EXPECT_EQ(loot_error_invalid_args, loot_get_version(NULL, &vMinor, NULL)); + EXPECT_EQ(loot_error_invalid_args, loot_get_version(NULL, NULL, &vPatch)); + EXPECT_EQ(loot_error_invalid_args, loot_get_version(NULL, NULL, NULL)); + } -TEST(GetVersion, HandlesNullInput) { - unsigned int vMajor, vMinor, vPatch; - EXPECT_EQ(loot_error_invalid_args, loot_get_version(&vMajor, NULL, NULL)); - EXPECT_EQ(loot_error_invalid_args, loot_get_version(NULL, &vMinor, NULL)); - EXPECT_EQ(loot_error_invalid_args, loot_get_version(NULL, NULL, &vPatch)); - EXPECT_EQ(loot_error_invalid_args, loot_get_version(NULL, NULL, NULL)); + TEST(loot_get_version, shouldReturnOkIfPassedNonNullPointers) { + unsigned int vMajor, vMinor, vPatch; + EXPECT_EQ(loot_ok, loot_get_version(&vMajor, &vMinor, &vPatch)); + } + + TEST(loot_get_build_id, shouldReturnAnInvalidArgsErrorIfPassedANullPointer) { + EXPECT_EQ(loot_error_invalid_args, loot_get_build_id(NULL)); + } + + TEST(loot_get_build_id, shouldReturnOkAndOutputANonNullNonPlaceholderRevisionString) { + const char * revision; + EXPECT_EQ(loot_ok, loot_get_build_id(&revision)); + EXPECT_STRNE(NULL, revision); + EXPECT_STRNE("@GIT_COMMIT_STRING@", revision); // The CMake placeholder. + } + + TEST(loot_is_compatible, shouldReturnTrueWithEqualMajorAndMinorVersionsAndUnequalPatchVersion) { + unsigned int vMajor, vMinor, vPatch; + EXPECT_EQ(loot_ok, loot_get_version(&vMajor, &vMinor, &vPatch)); + + EXPECT_TRUE(loot_is_compatible(vMajor, vMinor, vPatch + 1)); + } + + TEST(loot_is_compatible, shouldReturnFalseWithEqualMajorVersionAndUnequalMinorAndPatchVersions) { + unsigned int vMajor, vMinor, vPatch; + EXPECT_EQ(loot_ok, loot_get_version(&vMajor, &vMinor, &vPatch)); + + EXPECT_FALSE(loot_is_compatible(vMajor, vMinor + 1, vPatch + 1)); + } + + TEST(loot_get_error_message, shouldReturnAnInvalidArgsErrorIfPassedANullPointer) { + EXPECT_EQ(loot_error_invalid_args, loot_get_error_message(NULL)); + + const char * error; + EXPECT_EQ(loot_ok, loot_get_error_message(&error)); + ASSERT_STREQ("Null message pointer passed.", error); + } + + TEST(loot_get_error_message, shouldReturnOkIfPassedANonNullPointer) { + const char * error; + EXPECT_EQ(loot_ok, loot_get_error_message(&error)); + } + + TEST(loot_get_error_message, shouldOutputAnErrorMessageDetailingTheLastErrorIfAnErrorHasOccurred) { + EXPECT_EQ(loot_error_invalid_args, loot_get_error_message(NULL)); + + const char * error; + EXPECT_EQ(loot_ok, loot_get_error_message(&error)); + ASSERT_STREQ("Null message pointer passed.", error); + } + + TEST(loot_destroy_db, shouldNotThrowIfPassedANullPointer) { + ASSERT_NO_THROW(loot_destroy_db(NULL)); + } + } } -TEST(GetVersion, HandlesValidInput) { - unsigned int vMajor, vMinor, vPatch; - EXPECT_EQ(loot_ok, loot_get_version(&vMajor, &vMinor, &vPatch)); -} - -TEST(GetBuildID, HandlesNullInput) { - EXPECT_EQ(loot_error_invalid_args, loot_get_build_id(NULL)); -} - -TEST(GetBuildID, HandlesValidInput) { - const char * revision; - EXPECT_EQ(loot_ok, loot_get_build_id(&revision)); - EXPECT_STRNE(NULL, revision); - EXPECT_STRNE("@GIT_COMMIT_STRING@", revision); // The CMake placeholder. -} - -TEST(IsCompatible, shouldReturnTrueWithEqualMajorAndMinorVersionsAndUnequalPatchVersion) { - unsigned int vMajor, vMinor, vPatch; - EXPECT_EQ(loot_ok, loot_get_version(&vMajor, &vMinor, &vPatch)); - - EXPECT_TRUE(loot_is_compatible(vMajor, vMinor, vPatch + 1)); -} - -TEST(IsCompatible, shouldReturnFalseWithEqualMajorVersionAndUnequalMinorAndPatchVersions) { - unsigned int vMajor, vMinor, vPatch; - EXPECT_EQ(loot_ok, loot_get_version(&vMajor, &vMinor, &vPatch)); - - EXPECT_FALSE(loot_is_compatible(vMajor, vMinor + 1, vPatch + 1)); -} - -TEST(GetErrorMessage, HandlesInputCorrectly) { - EXPECT_EQ(loot_error_invalid_args, loot_get_error_message(NULL)); - - const char * error; - EXPECT_EQ(loot_ok, loot_get_error_message(&error)); - ASSERT_STREQ("Null message pointer passed.", error); -} - -TEST_F(OblivionTest, CreateDbHandlesValidInputs) { - EXPECT_EQ(loot_ok, loot_create_db(&db, loot_game_tes4, dataPath.parent_path().string().c_str(), localPath.string().c_str())); - ASSERT_NO_THROW(loot_destroy_db(db)); - db = nullptr; - - // Also test absolute paths. - boost::filesystem::path game = boost::filesystem::current_path() / dataPath.parent_path(); - boost::filesystem::path local = boost::filesystem::current_path() / localPath; - EXPECT_EQ(loot_ok, loot_create_db(&db, loot_game_tes4, game.string().c_str(), local.string().c_str())); -} - -TEST_F(OblivionTest, CreateDbHandlesInvalidHandleInput) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(NULL, loot_game_tes4, dataPath.parent_path().string().c_str(), localPath.string().c_str())); -} - -TEST_F(OblivionTest, CreateDbHandlesInvalidGameType) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, UINT_MAX, dataPath.parent_path().string().c_str(), localPath.string().c_str())); -} - -TEST_F(OblivionTest, CreateDbHandlesInvalidGamePathInput) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, loot_game_tes4, missingPath.string().c_str(), localPath.string().c_str())); -} - -TEST_F(OblivionTest, CreateDbHandlesInvalidLocalPathInput) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, loot_game_tes4, dataPath.parent_path().string().c_str(), missingPath.string().c_str())); -} - -#ifdef _WIN32 -TEST_F(OblivionTest, CreateDbHandlesNullLocalPath) { - EXPECT_EQ(loot_ok, loot_create_db(&db, loot_game_tes4, dataPath.parent_path().string().c_str(), NULL)); -} -#endif - -TEST_F(SkyrimTest, CreateDbHandlesValidInputs) { - EXPECT_EQ(loot_ok, loot_create_db(&db, loot_game_tes5, dataPath.parent_path().string().c_str(), localPath.string().c_str())); - ASSERT_NO_THROW(loot_destroy_db(db)); - db = nullptr; - - // Also test absolute paths. - boost::filesystem::path game = boost::filesystem::current_path() / dataPath.parent_path(); - boost::filesystem::path local = boost::filesystem::current_path() / localPath; - EXPECT_EQ(loot_ok, loot_create_db(&db, loot_game_tes5, game.string().c_str(), local.string().c_str())); -} - -TEST_F(SkyrimTest, CreateDbHandlesInvalidHandleInput) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(NULL, loot_game_tes5, dataPath.parent_path().string().c_str(), localPath.string().c_str())); -} - -TEST_F(SkyrimTest, CreateDbHandlesInvalidGameType) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, UINT_MAX, dataPath.parent_path().string().c_str(), localPath.string().c_str())); -} - -TEST_F(SkyrimTest, CreateDbHandlesInvalidGamePathInput) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, loot_game_tes5, missingPath.string().c_str(), localPath.string().c_str())); -} - -TEST_F(SkyrimTest, CreateDbHandlesInvalidLocalPathInput) { - EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db, loot_game_tes5, dataPath.parent_path().string().c_str(), missingPath.string().c_str())); -} - -#ifdef _WIN32 -TEST_F(SkyrimTest, CreateDbHandlesNullLocalPath) { - EXPECT_EQ(loot_ok, loot_create_db(&db, loot_game_tes5, dataPath.parent_path().string().c_str(), NULL)); -} -#endif - -TEST(GameHandleDestroyTest, HandledNullInput) { - ASSERT_NO_THROW(loot_destroy_db(NULL)); -} - -TEST_F(OblivionAPIOperationsTest, UpdateMasterlist) { - bool updated; - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(NULL, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, NULL, "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), NULL, "master", &updated)); - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", NULL, &updated)); - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", NULL)); - - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, ";//\?", "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, "", "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_EQ(loot_error_git_error, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/oblivion-does-not-exist.git", "master", &updated)); - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "", "master", &updated)); - EXPECT_EQ(loot_error_git_error, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "missing-branch", &updated)); - EXPECT_EQ(loot_error_invalid_args, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "", &updated)); - - // Test actual masterlist update. - EXPECT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_TRUE(updated); - - // Test with an up-to-date masterlist. - EXPECT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_FALSE(updated); -} - -TEST_F(OblivionAPIOperationsTest, GetMasterlistRevision) { - const char * revisionID; - const char * revisionDate; - bool isModified; - EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(NULL, masterlistPath.string().c_str(), false, &revisionID, &revisionDate, &isModified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, NULL, false, &revisionID, &revisionDate, &isModified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, NULL, &revisionDate, &isModified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionID, NULL, &isModified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionID, &revisionDate, NULL)); - - // Test with no masterlist. - EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionID, &revisionDate, &isModified)); - EXPECT_EQ(NULL, revisionID); - EXPECT_EQ(NULL, revisionDate); - EXPECT_FALSE(isModified); - - // Test with a generated (non-revision-control) masterlist. - ASSERT_NO_THROW(GenerateMasterlist()); - EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionID, &revisionDate, &isModified)); - EXPECT_EQ(NULL, revisionID); - EXPECT_EQ(NULL, revisionDate); - EXPECT_FALSE(isModified); - - // Update the masterlist and test. - bool updated; - ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - ASSERT_TRUE(updated); - EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionID, &revisionDate, &isModified)); - EXPECT_STRNE(NULL, revisionID); - EXPECT_EQ(40, strlen(revisionID)); - EXPECT_STRNE(NULL, revisionDate); - EXPECT_EQ(10, strlen(revisionDate)); - EXPECT_FALSE(isModified); - - // Test with a short revision string. - EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), true, &revisionID, &revisionDate, &isModified)); - EXPECT_STRNE(NULL, revisionID); - EXPECT_GE(size_t(40), strlen(revisionID)); - EXPECT_LE(size_t(7), strlen(revisionID)); - EXPECT_STRNE(NULL, revisionDate); - EXPECT_EQ(10, strlen(revisionDate)); - EXPECT_FALSE(isModified); - - // Overwrite the masterlist with a generated one. - ASSERT_NO_THROW(GenerateMasterlist()); - EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db, masterlistPath.string().c_str(), false, &revisionID, &revisionDate, &isModified)); - EXPECT_STRNE(NULL, revisionID); - EXPECT_EQ(40, strlen(revisionID)); - EXPECT_STRNE(NULL, revisionDate); - EXPECT_EQ(10, strlen(revisionDate)); - EXPECT_TRUE(isModified); -} - -TEST_F(OblivionAPIOperationsTest, LoadLists) { - EXPECT_EQ(loot_error_invalid_args, loot_load_lists(NULL, masterlistPath.string().c_str(), NULL)); - EXPECT_EQ(loot_error_invalid_args, loot_load_lists(db, NULL, NULL)); - - EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - bool updated; - ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db, masterlistPath.string().c_str(), userlistPath.string().c_str())); - - ASSERT_NO_THROW(boost::filesystem::copy(masterlistPath, userlistPath)); - EXPECT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), userlistPath.string().c_str())); -} - -TEST_F(SkyrimAPIOperationsTest, LoadLists) { - EXPECT_EQ(loot_error_invalid_args, loot_load_lists(NULL, masterlistPath.string().c_str(), NULL)); - EXPECT_EQ(loot_error_invalid_args, loot_load_lists(db, NULL, NULL)); - - EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - bool updated; - ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db, masterlistPath.string().c_str(), userlistPath.string().c_str())); - - ASSERT_NO_THROW(boost::filesystem::copy(masterlistPath, userlistPath)); - EXPECT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), userlistPath.string().c_str())); -} - -TEST_F(OblivionAPIOperationsTest, EvalLists) { - // No lists loaded. - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_any)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_spanish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_russian)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_french)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_chinese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_polish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_brazilian_portuguese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_finnish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_german)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_danish)); - - // Invalid args. - EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(NULL, loot_lang_any)); - EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(db, UINT_MAX)); - - // Now test different languages with a list loaded. - bool updated; - ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_any)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_spanish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_russian)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_french)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_chinese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_polish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_brazilian_portuguese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_finnish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_german)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_danish)); -} - -TEST_F(SkyrimAPIOperationsTest, EvalLists) { - // No lists loaded. - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_any)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_spanish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_russian)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_french)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_chinese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_polish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_brazilian_portuguese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_finnish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_german)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_danish)); - - // Invalid args. - EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(NULL, loot_lang_any)); - EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(db, UINT_MAX)); - - // Now test different languages with a list loaded. - bool updated; - ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_any)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_english)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_spanish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_russian)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_french)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_chinese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_polish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_brazilian_portuguese)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_finnish)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_german)); - EXPECT_EQ(loot_ok, loot_eval_lists(db, loot_lang_danish)); -} - -TEST_F(OblivionAPIOperationsTest, SortPlugins) { - const char * const * sortedPlugins; - size_t numPlugins; - EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(NULL, &sortedPlugins, &numPlugins)); - EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db, NULL, &numPlugins)); - EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db, &sortedPlugins, NULL)); - - EXPECT_EQ(loot_ok, loot_sort_plugins(db, &sortedPlugins, &numPlugins)); - - // Expected order was obtained from running the API function once. - std::list expectedOrder = { - "Oblivion.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp", - }; - std::list actualOrder; - for (size_t i = 0; i < numPlugins; ++i) { - actualOrder.push_back(sortedPlugins[i]); - } - EXPECT_EQ(11, numPlugins); - EXPECT_EQ(expectedOrder, actualOrder); -} - -TEST_F(SkyrimAPIOperationsTest, SortPlugins) { - const char * const * sortedPlugins; - size_t numPlugins; - EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(NULL, &sortedPlugins, &numPlugins)); - EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db, NULL, &numPlugins)); - EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db, &sortedPlugins, NULL)); - - EXPECT_EQ(loot_ok, loot_sort_plugins(db, &sortedPlugins, &numPlugins)); - - // Expected order was obtained from running the API function once. - std::list expectedOrder = { - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp", - }; - std::list actualOrder; - for (size_t i = 0; i < numPlugins; ++i) { - actualOrder.push_back(sortedPlugins[i]); - } - EXPECT_EQ(11, numPlugins); - EXPECT_EQ(expectedOrder, actualOrder); -} - -TEST_F(OblivionAPIOperationsTest, ApplyLoadOrder) { - const char * loadOrder[11] = { - "Oblivion.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Different Master Dependent.esm", - "Blank - Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Different Master Dependent.esp", - "Blank - Different Plugin Dependent.esp", - "Blank - Master Dependent.esp", - "Blank - Plugin Dependent.esp", - }; - size_t numPlugins = 11; - EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(NULL, loadOrder, numPlugins)); - EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(db, NULL, numPlugins)); - - EXPECT_EQ(loot_ok, loot_apply_load_order(db, loadOrder, numPlugins)); -} - -TEST_F(SkyrimAPIOperationsTest, ApplyLoadOrder) { - const char * loadOrder[11] = { - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Different Master Dependent.esm", - "Blank - Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Different Master Dependent.esp", - "Blank - Different Plugin Dependent.esp", - "Blank - Master Dependent.esp", - "Blank - Plugin Dependent.esp", - }; - size_t numPlugins = 11; - EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(NULL, loadOrder, numPlugins)); - EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(db, NULL, numPlugins)); - - EXPECT_EQ(loot_ok, loot_apply_load_order(db, loadOrder, numPlugins)); -} - -TEST_F(OblivionAPIOperationsTest, GetTagMap) { - const char * const * tagMap; - size_t numTags; - EXPECT_EQ(loot_error_invalid_args, loot_get_tag_map(NULL, &tagMap, &numTags)); - EXPECT_EQ(loot_error_invalid_args, loot_get_tag_map(db, NULL, &numTags)); - EXPECT_EQ(loot_error_invalid_args, loot_get_tag_map(db, &tagMap, NULL)); - - // Get tag map with no masterlist loaded: should have no tags. - EXPECT_EQ(loot_ok, loot_get_tag_map(db, &tagMap, &numTags)); - EXPECT_EQ(0, numTags); - EXPECT_EQ(NULL, tagMap); - - // Get a masterlist, then get tags from it. - ASSERT_NO_THROW(GenerateMasterlist()); - ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - EXPECT_EQ(loot_ok, loot_get_tag_map(db, &tagMap, &numTags)); - ASSERT_EQ(22, numTags); - EXPECT_STREQ("Actors.ACBS", tagMap[0]); - EXPECT_STREQ("Actors.AIData", tagMap[1]); - EXPECT_STREQ("Actors.AIPackages", tagMap[2]); - EXPECT_STREQ("Actors.CombatStyle", tagMap[3]); - EXPECT_STREQ("Actors.DeathItem", tagMap[4]); - EXPECT_STREQ("Actors.Stats", tagMap[5]); - EXPECT_STREQ("C.Climate", tagMap[6]); - EXPECT_STREQ("C.Light", tagMap[7]); - EXPECT_STREQ("C.Music", tagMap[8]); - EXPECT_STREQ("C.Name", tagMap[9]); - EXPECT_STREQ("C.Owner", tagMap[10]); - EXPECT_STREQ("C.Water", tagMap[11]); - EXPECT_STREQ("Creatures.Blood", tagMap[12]); - EXPECT_STREQ("Delev", tagMap[13]); - EXPECT_STREQ("Factions", tagMap[14]); - EXPECT_STREQ("Invent", tagMap[15]); - EXPECT_STREQ("NPC.Class", tagMap[16]); - EXPECT_STREQ("Names", tagMap[17]); - EXPECT_STREQ("Relations", tagMap[18]); - EXPECT_STREQ("Relev", tagMap[19]); - EXPECT_STREQ("Scripts", tagMap[20]); - EXPECT_STREQ("Stats", tagMap[21]); -} - -TEST_F(OblivionAPIOperationsTest, GetPluginTags) { - const unsigned int * added; - const unsigned int * removed; - size_t numAdded, numRemoved; - bool modified; - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(NULL, "Unofficial Oblivion Patch.esp", &added, &numAdded, &removed, &numRemoved, &modified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, NULL, &added, &numAdded, &removed, &numRemoved, &modified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", NULL, &numAdded, &removed, &numRemoved, &modified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", &added, NULL, &removed, &numRemoved, &modified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", &added, &numAdded, NULL, &numRemoved, &modified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", &added, &numAdded, &removed, NULL, &modified)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", &added, &numAdded, &removed, &numRemoved, NULL)); - - // Get tags before getting a tag map. - EXPECT_EQ(loot_error_no_tag_map, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", &added, &numAdded, &removed, &numRemoved, &modified)); - - // Load tag map. - const char * const * tagMap; - size_t numTags; - ASSERT_NO_THROW(GenerateMasterlist()); - ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - ASSERT_EQ(loot_ok, loot_get_tag_map(db, &tagMap, &numTags)); - - // Get tags for a plugin without any. - EXPECT_EQ(loot_ok, loot_get_plugin_tags(db, "Blank.esp", &added, &numAdded, &removed, &numRemoved, &modified)); - EXPECT_EQ(0, numAdded); - EXPECT_EQ(NULL, added); - EXPECT_EQ(0, numRemoved); - EXPECT_EQ(NULL, removed); - EXPECT_FALSE(modified); - - // Get tags for a plugin with some. - EXPECT_EQ(loot_ok, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", &added, &numAdded, &removed, &numRemoved, &modified)); - ASSERT_EQ(21, numAdded); - for (size_t i = 0; i < 11; ++i) { - EXPECT_EQ(i, added[i]); - } - for (size_t i = 11; i < 21; ++i) { - EXPECT_EQ(i + 1, added[i]); - } - - ASSERT_EQ(1, numRemoved); - EXPECT_EQ(11, removed[0]); - EXPECT_FALSE(modified); - - // Now load the masterlist as the userlist too, and check the modified flag. - ASSERT_NO_THROW(boost::filesystem::copy_file(masterlistPath, userlistPath)); - ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), userlistPath.string().c_str())); - ASSERT_EQ(loot_ok, loot_get_tag_map(db, &tagMap, &numTags)); - - EXPECT_EQ(loot_ok, loot_get_plugin_tags(db, "Unofficial Oblivion Patch.esp", &added, &numAdded, &removed, &numRemoved, &modified)); - ASSERT_EQ(21, numAdded); - for (size_t i = 0; i < 11; ++i) { - EXPECT_EQ(i, added[i]); - } - for (size_t i = 11; i < 21; ++i) { - EXPECT_EQ(i + 1, added[i]); - } - EXPECT_EQ(0, added[0]); - ASSERT_EQ(1, numRemoved); - EXPECT_EQ(11, removed[0]); - EXPECT_TRUE(modified); -} - -TEST_F(OblivionAPIOperationsTest, GetPluginMessages) { - const loot_message * messages; - size_t numMessages; - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(NULL, "EnhancedWeatherSIOnly.esm", &messages, &numMessages)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db, NULL, &messages, &numMessages)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db, "EnhancedWeatherSIOnly.esm", NULL, &numMessages)); - EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db, "EnhancedWeatherSIOnly.esm", &messages, NULL)); - - // Fetch and load the metadata. - ASSERT_NO_THROW(GenerateMasterlist()); - ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - - // Test for plugin with no messages. - EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, "Silgrad_Tower.esm", &messages, &numMessages)); - EXPECT_EQ(0, numMessages); - EXPECT_EQ(NULL, messages); - - // Test for plugin with one note. - EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, "No Lights Flicker.esm", &messages, &numMessages)); - EXPECT_EQ(1, numMessages); - EXPECT_EQ(loot_message_say, messages[0].type); - EXPECT_STREQ("Use Wrye Bash Bashed Patch tweak instead.", messages[0].message); - - // Test for plugin with one warning. - EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, "bookplacing.esm", &messages, &numMessages)); - EXPECT_EQ(1, numMessages); - EXPECT_EQ(loot_message_warn, messages[0].type); - EXPECT_STREQ("Check you are using v2+. If not, Update. v1 has a severe bug with the Mystic Emporium disappearing.", messages[0].message); - - // Test for plugin with one error. - EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, "EnhancedWeatherSIOnly.esm", &messages, &numMessages)); - EXPECT_EQ(1, numMessages); - EXPECT_EQ(loot_message_error, messages[0].type); - EXPECT_STREQ("Obsolete. Remove this and install Enhanced Weather.", messages[0].message); - - // Test for plugin with more than one message. - EXPECT_EQ(loot_ok, loot_get_plugin_messages(db, "nVidia Black Screen Fix.esp", &messages, &numMessages)); - EXPECT_EQ(2, numMessages); - EXPECT_EQ(loot_message_say, messages[0].type); - EXPECT_STREQ("Use Wrye Bash Bashed Patch tweak instead.", messages[0].message); - EXPECT_EQ(loot_message_say, messages[1].type); - EXPECT_STREQ("Alternatively, remove this and use UOP v3.0.1+ instead.", messages[1].message); -} - -TEST_F(OblivionAPIOperationsTest, GetDirtyInfo) { - unsigned int needsCleaning; - EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(NULL, "Oblivion.esm", &needsCleaning)); - EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(db, NULL, &needsCleaning)); - EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(db, "Oblivion.esm", NULL)); - - // Fetch and load the metadata. - ASSERT_NO_THROW(GenerateMasterlist()); - ASSERT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - - // A plugin with no metadata. - EXPECT_EQ(loot_ok, loot_get_dirty_info(db, "Oblivion.esm", &needsCleaning)); - EXPECT_EQ(loot_needs_cleaning_unknown, needsCleaning); - - // A plugin with dirty metadata. - EXPECT_EQ(loot_ok, loot_get_dirty_info(db, "Hammerfell.esm", &needsCleaning)); - EXPECT_EQ(loot_needs_cleaning_yes, needsCleaning); - - // A plugin with a standard "Do not clean" message. - EXPECT_EQ(loot_ok, loot_get_dirty_info(db, "Unofficial Oblivion Patch.esp", &needsCleaning)); - EXPECT_EQ(loot_needs_cleaning_no, needsCleaning); -} - -TEST_F(OblivionAPIOperationsTest, WriteMinimalList) { - std::string outputFile = (localPath / "minimal.yml").string(); - EXPECT_EQ(loot_error_invalid_args, loot_write_minimal_list(NULL, outputFile.c_str(), false)); - EXPECT_EQ(loot_error_invalid_args, loot_write_minimal_list(db, NULL, false)); - EXPECT_EQ(loot_error_file_write_fail, loot_write_minimal_list(db, "/:?*", false)); - - ASSERT_FALSE(boost::filesystem::exists(outputFile)); - EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputFile.c_str(), false)); - EXPECT_TRUE(boost::filesystem::exists(outputFile)); - EXPECT_EQ(loot_error_file_write_fail, loot_write_minimal_list(db, outputFile.c_str(), false)); - - EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputFile.c_str(), true)); - ASSERT_NO_THROW(boost::filesystem::remove(outputFile)); - EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputFile.c_str(), true)); - EXPECT_TRUE(boost::filesystem::exists(outputFile)); - ASSERT_NO_THROW(boost::filesystem::remove(outputFile)); - - // Check that Bash Tag removals get outputted correctly. - bool updated; - ASSERT_EQ(loot_ok, loot_update_masterlist(db, masterlistPath.string().c_str(), "https://github.com/loot/testing-metadata.git", "master", &updated)); - EXPECT_EQ(loot_ok, loot_load_lists(db, masterlistPath.string().c_str(), NULL)); - EXPECT_EQ(loot_ok, loot_write_minimal_list(db, outputFile.c_str(), false)); - - boost::filesystem::ifstream in(outputFile); - std::string line; - while (std::getline(in, line)) { - EXPECT_FALSE(boost::contains(line, "- \"-\"")); - } - in.close(); - ASSERT_NO_THROW(boost::filesystem::remove(outputFile)); -} #endif diff --git a/src/tests/backend/game/game_cache_test.h b/src/tests/backend/game/game_cache_test.h new file mode 100644 index 00000000..5b8445a0 --- /dev/null +++ b/src/tests/backend/game/game_cache_test.h @@ -0,0 +1,226 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_GAME_CACHE +#define LOOT_TEST_BACKEND_GAME_CACHE + +#include "backend/game/game_cache.h" + +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class GameCacheTest : public BaseGameTest { + protected: + GameCacheTest() : + condition("Condition"), + conditionLowercase("condition") {} + + void initialiseGame() { + game = Game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + } + + Game game; + GameCache cache; + + const std::string condition; + const std::string conditionLowercase; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + // Just test with one game because if it works for one it will work for them + // all. + INSTANTIATE_TEST_CASE_P(, + GameCacheTest, + ::testing::Values( + Game::tes5)); + + TEST_P(GameCacheTest, copyConstructorShouldCopyCachedData) { + initialiseGame(); + + cache.CacheCondition(condition, true); + cache.AddPlugin(Plugin(game, blankEsm, true)); + Message expectedMessage(Message::say, "1"); + cache.AppendMessage(expectedMessage); + cache.SetLoadOrderSorted(true); + + GameCache otherCache(cache); + EXPECT_EQ(std::make_pair(true, true), otherCache.GetCachedCondition(conditionLowercase)); + EXPECT_EQ(blankEsm, otherCache.GetPlugin(blankEsm).Name()); + ASSERT_EQ(1, otherCache.GetMessages().size()); + EXPECT_EQ(expectedMessage, otherCache.GetMessages()[0]); + } + + TEST_P(GameCacheTest, assignmentOperatorShouldCopyCachedData) { + initialiseGame(); + + cache.CacheCondition(condition, true); + cache.AddPlugin(Plugin(game, blankEsm, true)); + Message expectedMessage(Message::say, "1"); + cache.AppendMessage(expectedMessage); + cache.SetLoadOrderSorted(true); + + GameCache otherCache = cache; + EXPECT_EQ(std::make_pair(true, true), otherCache.GetCachedCondition(conditionLowercase)); + EXPECT_EQ(blankEsm, otherCache.GetPlugin(blankEsm).Name()); + ASSERT_EQ(1, otherCache.GetMessages().size()); + EXPECT_EQ(expectedMessage, otherCache.GetMessages()[0]); + } + + TEST_P(GameCacheTest, gettingATrueConditionShouldReturnATrueTruePair) { + EXPECT_NO_THROW(cache.CacheCondition(condition, true)); + + EXPECT_EQ(std::make_pair(true, true), cache.GetCachedCondition(conditionLowercase)); + } + + TEST_P(GameCacheTest, gettingAFalseConditionShouldReturnAFalseTruePair) { + EXPECT_NO_THROW(cache.CacheCondition(condition, false)); + + EXPECT_EQ(std::make_pair(false, true), cache.GetCachedCondition(conditionLowercase)); + } + + TEST_P(GameCacheTest, gettingANonCachedConditionShouldReturnAFalseFalsePair) { + EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition(condition)); + } + + TEST_P(GameCacheTest, addingAPluginThatDoesNotExistShouldSucceed) { + initialiseGame(); + + cache.AddPlugin(Plugin(game, blankEsm, true)); + EXPECT_EQ(blankEsm, cache.GetPlugin(blankEsm).Name()); + } + + TEST_P(GameCacheTest, addingAPluginThatIsAlreadyCachedShouldOverwriteExistingEntry) { + initialiseGame(); + + cache.AddPlugin(Plugin(game, blankEsm, true)); + EXPECT_EQ(0, cache.GetPlugin(blankEsm).Crc()); + + cache.AddPlugin(Plugin(game, blankEsm, false)); + EXPECT_EQ(blankEsmCrc, cache.GetPlugin(blankEsm).Crc()); + } + + TEST_P(GameCacheTest, gettingAPluginThatIsNotCachedShouldThrow) { + EXPECT_ANY_THROW(cache.GetPlugin(blankEsm)); + } + + TEST_P(GameCacheTest, gettingAPluginShouldBeCaseInsensitive) { + initialiseGame(); + + cache.AddPlugin(Plugin(game, blankEsm, true)); + EXPECT_EQ(blankEsm, cache.GetPlugin(blankEsm).Name()); + } + + TEST_P(GameCacheTest, gettingPluginsShouldReturnAnEmptySetIfNoPluginsHaveBeenCached) { + EXPECT_TRUE(cache.GetPlugins().empty()); + } + + TEST_P(GameCacheTest, gettingPluginsShouldReturnASetOfCachedPluginsIfPluginsHaveBeenCached) { + initialiseGame(); + + cache.AddPlugin(Plugin(game, blankEsm, true)); + cache.AddPlugin(Plugin(game, blankMasterDependentEsm, true)); + + EXPECT_EQ(std::set({ + Plugin(game, blankEsm, true), + Plugin(game, blankMasterDependentEsm, true), + }), cache.GetPlugins()); + } + + TEST_P(GameCacheTest, clearingCachedConditionsShouldNotThrowIfNoConditionsAreCached) { + EXPECT_NO_THROW(cache.ClearCachedConditions()); + } + + TEST_P(GameCacheTest, clearingCachedConditionsShouldClearAnyCachedConditions) { + EXPECT_NO_THROW(cache.CacheCondition(condition, true)); + + EXPECT_NO_THROW(cache.ClearCachedConditions()); + + EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition(conditionLowercase)); + } + + TEST_P(GameCacheTest, clearingCachedPluginsShouldNotThrowIfNoPluginsAreCached) { + EXPECT_NO_THROW(cache.ClearCachedPlugins()); + } + + TEST_P(GameCacheTest, clearingCachedPluginsShouldClearAnyCachedPlugins) { + initialiseGame(); + + cache.AddPlugin(Plugin(game, blankEsm, true)); + cache.ClearCachedPlugins(); + + EXPECT_TRUE(cache.GetPlugins().empty()); + } + + TEST_P(GameCacheTest, aMessageShouldBeCachedByDefault) { + ASSERT_EQ(1, cache.GetMessages().size()); + } + + TEST_P(GameCacheTest, settingLoadOrderSortedToTrueShouldSupressDefaultCachedMessage) { + cache.SetLoadOrderSorted(true); + + ASSERT_TRUE(cache.GetMessages().empty()); + } + + TEST_P(GameCacheTest, settingLoadOrderSortedToFalseShouldReverseTheDefaultCachedMessageSuppression) { + auto expectedMessages = cache.GetMessages(); + cache.SetLoadOrderSorted(true); + cache.SetLoadOrderSorted(false); + + ASSERT_EQ(expectedMessages, cache.GetMessages()); + } + + TEST_P(GameCacheTest, appendingMessagesShouldStoreThemInTheGivenOrder) { + std::vector messages({ + Message(Message::say, "1"), + Message(Message::error, "2"), + }); + for (const auto& message : messages) + cache.AppendMessage(message); + + ASSERT_EQ(3, cache.GetMessages().size()); + EXPECT_EQ(messages[0], cache.GetMessages()[0]); + EXPECT_EQ(messages[1], cache.GetMessages()[1]); + } + + TEST_P(GameCacheTest, clearingMessagesShouldRemoveAllAppendedMessages) { + std::vector messages({ + Message(Message::say, "1"), + Message(Message::error, "2"), + }); + for (const auto& message : messages) + cache.AppendMessage(message); + + auto previousSize = cache.GetMessages().size(); + + cache.ClearMessages(); + + EXPECT_EQ(previousSize - messages.size(), cache.GetMessages().size()); + } + } +} + +#endif diff --git a/src/tests/backend/game/game_settings_test.h b/src/tests/backend/game/game_settings_test.h new file mode 100644 index 00000000..c56adcf9 --- /dev/null +++ b/src/tests/backend/game/game_settings_test.h @@ -0,0 +1,267 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_GAME_SETTINGS +#define LOOT_TEST_BACKEND_GAME_SETTINGS + +#include "backend/globals.h" +#include "backend/game/game_settings.h" + +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class GameSettingsTest : public BaseGameTest { + protected: + GameSettings game; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + // Just test with one game because if it works for one it will work for them + // all. + INSTANTIATE_TEST_CASE_P(, + GameSettingsTest, + ::testing::Values( + GameSettings::tes5)); + + TEST_P(GameSettingsTest, defaultConstructorShouldInitialiseIdToAutodetectAndAllOtherSettingsToEmptyStrings) { + EXPECT_EQ(GameSettings::autodetect, game.Id()); + EXPECT_EQ("", game.Name()); + EXPECT_EQ("", game.FolderName()); + EXPECT_EQ("", game.Master()); + EXPECT_EQ("", game.RegistryKey()); + EXPECT_EQ("", game.RepoURL()); + EXPECT_EQ("", game.RepoBranch()); + + EXPECT_EQ("", game.GamePath()); + EXPECT_EQ("", game.DataPath()); + EXPECT_EQ("", game.MasterlistPath()); + EXPECT_EQ("", game.UserlistPath()); + } + + TEST_P(GameSettingsTest, idConstructorShouldInitialiseSettingsToDefaultsForThatGame) { + game = GameSettings(GameSettings::tes5); + + EXPECT_EQ(GameSettings::tes5, game.Id()); + EXPECT_EQ("TES V: Skyrim", game.Name()); + EXPECT_EQ("Skyrim", game.FolderName()); + EXPECT_EQ("Skyrim.esm", game.Master()); + EXPECT_EQ("Software\\Bethesda Softworks\\Skyrim\\Installed Path", game.RegistryKey()); + EXPECT_EQ("https://github.com/loot/skyrim.git", game.RepoURL()); + // Repo branch changes between LOOT versions, so don't check an exact value. + EXPECT_NE("", game.RepoBranch()); + + EXPECT_EQ("", game.GamePath()); + EXPECT_EQ("", game.DataPath()); + EXPECT_EQ(g_path_local / "Skyrim" / "masterlist.yaml", game.MasterlistPath()); + EXPECT_EQ(g_path_local / "Skyrim" / "userlist.yaml", game.UserlistPath()); + } + + TEST_P(GameSettingsTest, idConstructorShouldSetGameFolderIfGiven) { + game = GameSettings(GameSettings::tes5, "folder"); + + EXPECT_EQ("folder", game.FolderName()); + EXPECT_EQ(g_path_local / "folder" / "masterlist.yaml", game.MasterlistPath()); + EXPECT_EQ(g_path_local / "folder" / "userlist.yaml", game.UserlistPath()); + } + + TEST_P(GameSettingsTest, isInstalledShouldBeFalseIfGamePathIsNotSet) { + GameSettings game; + EXPECT_FALSE(game.IsInstalled()); + } + + TEST_P(GameSettingsTest, isInstalledShouldBeTrueIfGamePathIsValid) { + game = GameSettings(GameSettings::tes5); + game.SetGamePath(dataPath.parent_path()); + EXPECT_TRUE(game.IsInstalled()); + } + + TEST_P(GameSettingsTest, gameSettingsWithTheSameIdsShouldBeEqual) { + GameSettings game1 = GameSettings(GameSettings::tes5, "game1") + .SetMaster("master1") + .SetRegistryKey("key1") + .SetRepoURL("url1") + .SetRepoBranch("branch1") + .SetGamePath("path1"); + GameSettings game2 = GameSettings(GameSettings::tes5, "game2") + .SetMaster("master2") + .SetRegistryKey("key2") + .SetRepoURL("url2") + .SetRepoBranch("branch2") + .SetGamePath("path2"); + + EXPECT_TRUE(game1 == game2); + } + + TEST_P(GameSettingsTest, gameSettingsWithTheSameNameShouldBeEqual) { + GameSettings game1 = GameSettings(GameSettings::tes4) + .SetName("name"); + GameSettings game2 = GameSettings(GameSettings::tes5) + .SetName("name"); + + EXPECT_TRUE(game1 == game2); + } + + TEST_P(GameSettingsTest, gameSettingsWithDifferentIdsAndNamesShouldNotBeEqual) { + GameSettings game1 = GameSettings(GameSettings::tes4); + GameSettings game2 = GameSettings(GameSettings::tes5); + + EXPECT_FALSE(game1 == game2); + } + + TEST_P(GameSettingsTest, setNameShouldStoreGivenValue) { + GameSettings game; + game.SetName("name"); + EXPECT_EQ("name", game.Name()); + } + + TEST_P(GameSettingsTest, setMasterShouldStoreGivenValue) { + GameSettings game; + game.SetMaster("master"); + EXPECT_EQ("master", game.Master()); + } + + TEST_P(GameSettingsTest, setRegistryKeyShouldStoreGivenValue) { + GameSettings game; + game.SetRegistryKey("key"); + EXPECT_EQ("key", game.RegistryKey()); + } + + TEST_P(GameSettingsTest, setRepoUrlShouldStoreGivenValue) { + GameSettings game; + game.SetRepoURL("url"); + EXPECT_EQ("url", game.RepoURL()); + } + + TEST_P(GameSettingsTest, setRepoBranchShouldStoreGivenValue) { + GameSettings game; + game.SetRepoBranch("branch"); + EXPECT_EQ("branch", game.RepoBranch()); + } + + TEST_P(GameSettingsTest, setGamePathShouldStoreGivenValue) { + std::string pathValue = "path"; + GameSettings game; + + game.SetGamePath(pathValue); + EXPECT_EQ(pathValue, game.GamePath().string()); + EXPECT_EQ(boost::filesystem::path(pathValue) / "Data", game.DataPath()); + } + + TEST_P(GameSettingsTest, emittingYamlShouldSerialiseDataCorrectly) { + GameSettings game(GameSettings::tes5, "folder1"); + game.SetName("name1") + .SetMaster("master1") + .SetRegistryKey("key1") + .SetRepoURL("url1") + .SetRepoBranch("branch1") + .SetGamePath("path1"); + + YAML::Emitter e; + e << game; + EXPECT_STREQ("type: 'Skyrim'\n" + "folder: 'folder1'\n" + "name: 'name1'\n" + "master: 'master1'\n" + "repo: 'url1'\n" + "branch: 'branch1'\n" + "path: 'path1'\n" + "registry: 'key1'", e.c_str()); + } + + TEST_P(GameSettingsTest, encodingAsYamlShouldConvertDataCorrectly) { + GameSettings game(GameSettings::tes5, "folder1"); + game.SetName("name1") + .SetMaster("master1") + .SetRegistryKey("key1") + .SetRepoURL("url1") + .SetRepoBranch("branch1") + .SetGamePath("path1"); + + YAML::Node node; + node = game; + EXPECT_EQ("Skyrim", node["type"].as()); + EXPECT_EQ("folder1", node["folder"].as()); + EXPECT_EQ("name1", node["name"].as()); + EXPECT_EQ("master1", node["master"].as()); + EXPECT_EQ("url1", node["repo"].as()); + EXPECT_EQ("branch1", node["branch"].as()); + EXPECT_EQ("path1", node["path"].as()); + EXPECT_EQ("key1", node["registry"].as()); + } + + TEST_P(GameSettingsTest, decodingFromYamlShouldInterpretTheYamlCorrectly) { + YAML::Node node = YAML::Load("type: 'Skyrim'\n" + "folder: 'folder1'\n" + "name: 'name1'\n" + "master: 'master1'\n" + "repo: 'url1'\n" + "branch: 'branch1'\n" + "path: 'path1'\n" + "registry: 'key1'"); + + GameSettings game = node.as(); + EXPECT_EQ(GameSettings::tes5, game.Id()); + EXPECT_EQ("name1", game.Name()); + EXPECT_EQ("folder1", game.FolderName()); + EXPECT_EQ("master1", game.Master()); + EXPECT_EQ("key1", game.RegistryKey()); + EXPECT_EQ("url1", game.RepoURL()); + EXPECT_EQ("branch1", game.RepoBranch()); + EXPECT_EQ("path1", game.GamePath()); + } + + TEST_P(GameSettingsTest, decodingFromAnInvalidYamlMapShouldThrowAnException) { + YAML::Node node = YAML::Load("type: 'Invalid'\n"); + EXPECT_ANY_THROW(node.as()); + } + + TEST_P(GameSettingsTest, decodingFromAYamlScalarShouldThrowAnException) { + YAML::Node node = YAML::Load("scalar"); + EXPECT_ANY_THROW(node.as()); + } + + TEST_P(GameSettingsTest, decodingFromAYamlListShouldThrowAnException) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + EXPECT_ANY_THROW(node.as()); + } + + TEST_P(GameSettingsTest, decodingFromAnIncompleteYamlMapShouldUseDefaultValuesForMissingSettings) { + // Test inheritance of unspecified settings. + YAML::Node node = YAML::Load("type: 'Skyrim'\n" + "folder: 'folder1'\n" + "master: 'master1'\n" + "repo: 'url1'\n" + "branch: 'branch1'\n"); + + game = node.as(); + EXPECT_EQ(GameSettings::tes5, game.Id()); + EXPECT_EQ("TES V: Skyrim", game.Name()); + EXPECT_EQ("Software\\Bethesda Softworks\\Skyrim\\Installed Path", game.RegistryKey()); + EXPECT_EQ("", game.GamePath()); + } + } +} +#endif diff --git a/src/tests/backend/game/game_test.h b/src/tests/backend/game/game_test.h new file mode 100644 index 00000000..4ad16b99 --- /dev/null +++ b/src/tests/backend/game/game_test.h @@ -0,0 +1,323 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_GAME +#define LOOT_TEST_BACKEND_GAME + +#include "backend/error.h" +#include "backend/globals.h" +#include "backend/game/game.h" + +#include "load_order_handler_test.h" + +namespace loot { + namespace test { + class GameTest : public BaseGameTest { + protected: +#ifndef _WIN32 + void TearDown() { + BaseGameTest::TearDown(); + + ASSERT_NO_THROW(boost::filesystem::remove_all(g_path_local)); + } +#endif + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + GameTest, + ::testing::Values( + GameSettings::tes4, + GameSettings::tes5, + GameSettings::fo3, + GameSettings::fonv, + GameSettings::fo4)); + + TEST_P(GameTest, defaultConstructorShouldConstructWithDefaultGameSettings) { + GameSettings settings; + Game game; + + EXPECT_EQ(settings.Id(), game.Id()); + EXPECT_EQ(settings.FolderName(), game.FolderName()); + } + + TEST_P(GameTest, constructingFromGameSettingsShouldUseTheirValues) { + GameSettings settings = GameSettings(GetParam(), "folder"); + settings.SetName("foo"); + settings.SetMaster(blankEsm); + settings.SetRegistryKey("foo"); + settings.SetRepoURL("foo"); + settings.SetRepoBranch("foo"); + settings.SetGamePath(localPath); + Game game = Game(settings); + + EXPECT_EQ(GetParam(), game.Id()); + EXPECT_EQ(settings.Name(), game.Name()); + EXPECT_EQ(settings.FolderName(), game.FolderName()); + EXPECT_EQ(settings.Master(), game.Master()); + EXPECT_EQ(settings.RegistryKey(), game.RegistryKey()); + EXPECT_EQ(settings.RepoURL(), game.RepoURL()); + EXPECT_EQ(settings.RepoBranch(), game.RepoBranch()); + + EXPECT_EQ(settings.GamePath(), game.GamePath()); + } + + TEST_P(GameTest, constructingFromIdAndFolderShouldPassThemToGameSettingsConstructor) { + GameSettings settings = GameSettings(GetParam(), "folder"); + Game game = Game(GetParam(), "folder"); + + EXPECT_EQ(settings.Id(), game.Id()); + EXPECT_EQ(settings.FolderName(), game.FolderName()); + } + + TEST_P(GameTest, initShouldThrowIfGameHasAnInvalidId) { + Game game; + EXPECT_THROW(game.Init(false), error); + EXPECT_THROW(game.Init(true), error); + EXPECT_THROW(game.Init(false, localPath), error); + EXPECT_THROW(game.Init(true, localPath), error); + } + +#ifndef _WIN32 + // Testing on Windows will find real game installs in the Registry, so cannot + // test autodetection fully unless on Linux. + TEST_P(GameTest, initShouldThrowOnLinuxIfGamePathIsNotGiven) { + Game game = Game(GetParam()); + EXPECT_THROW(game.Init(false), error); + EXPECT_THROW(game.Init(true), error); + EXPECT_THROW(game.Init(false, localPath), error); + EXPECT_THROW(game.Init(true, localPath), error); + } + + TEST_P(GameTest, initShouldThrowOnLinuxIfLocalPathIsNotGiven) { + Game game = Game(GetParam()).SetGamePath(dataPath.parent_path()); + ASSERT_FALSE(boost::filesystem::exists(g_path_local / game.FolderName())); + EXPECT_THROW(game.Init(false), error); + } + + // Testing on Windows will find real LOOT installs, and they shouldn't be + // interfered with. + TEST_P(GameTest, initShouldNotCreateAGameFolderIfTheCreateFolderArgumentIsFalse) { + Game game = Game(GetParam()).SetGamePath(dataPath.parent_path()); + + ASSERT_FALSE(boost::filesystem::exists(g_path_local / game.FolderName())); + EXPECT_NO_THROW(game.Init(false, localPath)); + + EXPECT_FALSE(boost::filesystem::exists(g_path_local / game.FolderName())); + } + + TEST_P(GameTest, initShouldCreateAGameFolderIfTheCreateFolderArgumentIsTrue) { + Game game = Game(GetParam()).SetGamePath(dataPath.parent_path()); + + ASSERT_FALSE(boost::filesystem::exists(g_path_local / game.FolderName())); + EXPECT_NO_THROW(game.Init(true, localPath)); + + EXPECT_TRUE(boost::filesystem::exists(g_path_local / game.FolderName())); + } +#else + TEST_P(GameTest, initShouldNotThrowOnWindowsIfLocalPathIsNotGiven) { + Game game = Game(GetParam()).SetGamePath(dataPath.parent_path()); + + EXPECT_NO_THROW(game.Init(false)); + } +#endif + + TEST_P(GameTest, initShouldNotThrowIfGameAndLocalPathsAreGiven) { + Game game = Game(GetParam()).SetGamePath(dataPath.parent_path()); + + EXPECT_NO_THROW(game.Init(false, localPath)); + } + + TEST_P(GameTest, redatePluginsShouldThrowIfTheGameHasNotYetBeenInitialisedForSkyrimAndNotForOtherGames) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + if (GetParam() == Game::tes5) + EXPECT_THROW(game.RedatePlugins(), error); + else + EXPECT_NO_THROW(game.RedatePlugins()); + } + + TEST_P(GameTest, redatePluginsShouldRedatePluginsForSkyrimAndDoNothingForOtherGames) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + game.Init(false, localPath); + + std::vector loadOrder = getInitialLoadOrder(); + + // First set reverse timestamps to be sure. + time_t time = boost::filesystem::last_write_time(dataPath / masterFile); + for (size_t i = 1; i < loadOrder.size(); ++i) { + if (!boost::filesystem::exists(dataPath / loadOrder[i])) + loadOrder[i] += ".ghost"; + + boost::filesystem::last_write_time(dataPath / loadOrder[i], time - i * 60); + ASSERT_EQ(time - i * 60, boost::filesystem::last_write_time(dataPath / loadOrder[i])); + } + + EXPECT_NO_THROW(game.RedatePlugins()); + + time_t interval = 60; + if (GetParam() != Game::tes5) + interval *= -1; + for (size_t i = 0; i < loadOrder.size(); ++i) { + EXPECT_EQ(time + i * interval, boost::filesystem::last_write_time(dataPath / loadOrder[i])); + } + } + + TEST_P(GameTest, loadPluginsWithHeadersOnlyTrueShouldLoadTheHeadersOfAllInstalledPlugins) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_NO_THROW(game.LoadPlugins(true)); + EXPECT_EQ(11, game.GetPlugins().size()); + + // Check that one plugin's header has been read. + ASSERT_NO_THROW(game.GetPlugin(masterFile)); + Plugin plugin = game.GetPlugin(masterFile); + EXPECT_EQ("v5.0", plugin.getDescription()); + + // Check that only the header has been read. + EXPECT_EQ(0, plugin.Crc()); + } + + TEST_P(GameTest, loadPluginsWithHeadersOnlyFalseShouldFullyLoadAllInstalledPlugins) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_NO_THROW(game.LoadPlugins(false)); + EXPECT_EQ(11, game.GetPlugins().size()); + + // Check that one plugin's header has been read. + ASSERT_NO_THROW(game.GetPlugin(blankEsm)); + Plugin plugin = game.GetPlugin(blankEsm); + EXPECT_EQ("v5.0", plugin.getDescription()); + + // Check that not only the header has been read. + EXPECT_EQ(blankEsmCrc, plugin.Crc()); + } + + TEST_P(GameTest, pluginsShouldNotBeFullyLoadedByDefault) { + EXPECT_FALSE(Game().ArePluginsFullyLoaded()); + EXPECT_FALSE(Game(GameSettings()).ArePluginsFullyLoaded()); + EXPECT_FALSE(Game(GetParam(), "folder").ArePluginsFullyLoaded()); + } + + TEST_P(GameTest, pluginsShouldNotBeFullyLoadedAfterLoadingHeadersOnly) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_FALSE(game.ArePluginsFullyLoaded()); + } + + TEST_P(GameTest, pluginsShouldBeFullyLoadedAfterFullyLoadingThem) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + ASSERT_NO_THROW(game.LoadPlugins(false)); + + EXPECT_TRUE(game.ArePluginsFullyLoaded()); + } + + TEST_P(GameTest, shouldThrowIfCheckingIfPluginThatIsntLoadedIsActiveAndGameHasNotBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_ANY_THROW(game.IsPluginActive(blankEsm)); + } + + TEST_P(GameTest, shouldShowBlankEsmAsActiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + + EXPECT_TRUE(game.IsPluginActive(blankEsm)); + } + + TEST_P(GameTest, shouldShowBlankEspAsInactiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + + EXPECT_FALSE(game.IsPluginActive(blankEsp)); + } + + TEST_P(GameTest, shouldShowBlankEsmAsInactiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_FALSE(game.IsPluginActive(blankEsm)); + } + + TEST_P(GameTest, shouldShowBlankEspAsInactiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_FALSE(game.IsPluginActive(blankEsp)); + } + + TEST_P(GameTest, shouldShowBlankEsmAsActiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_TRUE(game.IsPluginActive(blankEsm)); + } + + TEST_P(GameTest, shouldShowBlankEspAsInactiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_FALSE(game.IsPluginActive(blankEsp)); + } + + TEST_P(GameTest, shouldShowBlankEsmAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(false)); + + EXPECT_TRUE(game.IsPluginActive(blankEsm)); + } + + TEST_P(GameTest, shouldShowBlankEspAsInactiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(false)); + + EXPECT_FALSE(game.IsPluginActive(blankEsp)); + } + } +} + +#endif diff --git a/src/tests/backend/game/load_order_handler_test.h b/src/tests/backend/game/load_order_handler_test.h new file mode 100644 index 00000000..5832e168 --- /dev/null +++ b/src/tests/backend/game/load_order_handler_test.h @@ -0,0 +1,155 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_LOAD_ORDER_HANDLER +#define LOOT_TEST_BACKEND_LOAD_ORDER_HANDLER + +#include "backend/error.h" +#include "backend/game/load_order_handler.h" + +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class LoadOrderHandlerTest : public BaseGameTest { + protected: + LoadOrderHandler loh; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + LoadOrderHandlerTest, + ::testing::Values( + GameSettings::tes4, + GameSettings::tes5, + GameSettings::fo3, + GameSettings::fonv, + GameSettings::fo4)); + + TEST_P(LoadOrderHandlerTest, initShouldThrowForAnInvalidGameId) { + GameSettings game(GameSettings::autodetect); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_THROW(loh.Init(game), error); + EXPECT_THROW(loh.Init(game), error); + EXPECT_THROW(loh.Init(game, localPath), error); + EXPECT_THROW(loh.Init(game, localPath), error); + } + + TEST_P(LoadOrderHandlerTest, initShouldThrowIfNoGamePathIsSet) { + GameSettings game(GetParam()); + + EXPECT_THROW(loh.Init(game), error); + EXPECT_THROW(loh.Init(game), error); + EXPECT_THROW(loh.Init(game, localPath), error); + EXPECT_THROW(loh.Init(game, localPath), error); + } + +#ifndef _WIN32 + TEST_P(LoadOrderHandlerTest, initShouldThrowOnLinuxIfNoLocalPathIsSet) { + GameSettings game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_THROW(loh.Init(game), error); + } +#endif + + TEST_P(LoadOrderHandlerTest, initShouldNotThrowIfAValidGameIdAndGamePathAndLocalPathAreSet) { + GameSettings game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_NO_THROW(loh.Init(game, localPath)); + } + + TEST_P(LoadOrderHandlerTest, isPluginActiveShouldThrowIfTheHandlerHasNotBeenInitialised) { + EXPECT_THROW(loh.IsPluginActive(masterFile), error); + } + + TEST_P(LoadOrderHandlerTest, isPluginActiveShouldReturnCorrectPluginStatesAfterInitialisation) { + GameSettings game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(loh.Init(game, localPath)); + + EXPECT_TRUE(loh.IsPluginActive(masterFile)); + EXPECT_TRUE(loh.IsPluginActive(blankEsm)); + EXPECT_FALSE(loh.IsPluginActive(blankEsp)); + } + + TEST_P(LoadOrderHandlerTest, getLoadOrderShouldThrowIfTheHandlerHasNotBeenInitialised) { + EXPECT_THROW(loh.GetLoadOrder(), error); + } + + TEST_P(LoadOrderHandlerTest, getLoadOrderShouldReturnTheCurrentLoadOrder) { + GameSettings game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(loh.Init(game, localPath)); + + ASSERT_EQ(getLoadOrder(), loh.GetLoadOrder()); + } + + TEST_P(LoadOrderHandlerTest, setLoadOrderShouldThrowIfTheHandlerHasNotBeenInitialised) { + std::list loadOrder({ + masterFile, + blankEsm, + blankMasterDependentEsm, + blankDifferentEsm, + blankDifferentMasterDependentEsm, + blankDifferentEsp, + blankDifferentPluginDependentEsp, + blankEsp, + blankMasterDependentEsp, + blankDifferentMasterDependentEsp, + blankPluginDependentEsp, + }); + + EXPECT_THROW(loh.SetLoadOrder(std::list()), error); + } + + TEST_P(LoadOrderHandlerTest, setLoadOrderShouldSetTheLoadOrder) { + GameSettings game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(loh.Init(game, localPath)); + + std::list loadOrder({ + masterFile, + blankEsm, + blankMasterDependentEsm, + blankDifferentEsm, + blankDifferentMasterDependentEsm, + blankDifferentEsp, + blankDifferentPluginDependentEsp, + blankEsp, + blankMasterDependentEsp, + blankDifferentMasterDependentEsp, + blankPluginDependentEsp, + }); + + EXPECT_NO_THROW(loh.SetLoadOrder(loadOrder)); + EXPECT_EQ(loadOrder, getLoadOrder()); + } + } +} + +#endif diff --git a/src/tests/backend/game/test_game.h b/src/tests/backend/game/test_game.h deleted file mode 100644 index 0bd22283..00000000 --- a/src/tests/backend/game/test_game.h +++ /dev/null @@ -1,658 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_GAME -#define LOOT_TEST_BACKEND_GAME - -#include "backend/error.h" -#include "backend/globals.h" -#include "backend/game/game.h" - -#include "tests/fixtures.h" - -class Game : public SkyrimTest {}; - -TEST_F(Game, Constructors) { - // The constructors should just passthrough to the GameSettings - // members, so just check that is happening. - loot::Game game; - loot::GameSettings settings; - - EXPECT_EQ(loot::Game::autodetect, game.Id()); - EXPECT_EQ(settings.Name(), game.Name()); - EXPECT_EQ(settings.FolderName(), game.FolderName()); - EXPECT_EQ(settings.Master(), game.Master()); - EXPECT_EQ(settings.RegistryKey(), game.RegistryKey()); - EXPECT_EQ(settings.RepoURL(), game.RepoURL()); - EXPECT_EQ(settings.RepoBranch(), game.RepoBranch()); - - EXPECT_EQ(settings.GamePath(), game.GamePath()); - EXPECT_EQ(settings.DataPath(), game.DataPath()); - EXPECT_EQ(settings.MasterlistPath(), game.MasterlistPath()); - EXPECT_EQ(settings.UserlistPath(), game.UserlistPath()); - - EXPECT_FALSE(game.ArePluginsFullyLoaded()); - - game = loot::Game(loot::Game::tes5); - settings = loot::GameSettings(loot::GameSettings::tes5); - - EXPECT_EQ(loot::Game::tes5, game.Id()); - EXPECT_EQ(settings.Name(), game.Name()); - EXPECT_EQ(settings.FolderName(), game.FolderName()); - EXPECT_EQ(settings.Master(), game.Master()); - EXPECT_EQ(settings.RegistryKey(), game.RegistryKey()); - EXPECT_EQ(settings.RepoURL(), game.RepoURL()); - EXPECT_EQ(settings.RepoBranch(), game.RepoBranch()); - - EXPECT_EQ(settings.GamePath(), game.GamePath()); - EXPECT_EQ(settings.DataPath(), game.DataPath()); - EXPECT_EQ(settings.MasterlistPath(), game.MasterlistPath()); - EXPECT_EQ(settings.UserlistPath(), game.UserlistPath()); - - EXPECT_FALSE(game.ArePluginsFullyLoaded()); - - game = loot::Game(loot::Game::tes5, "folder"); - settings = loot::GameSettings(loot::GameSettings::tes5, "folder"); - - EXPECT_EQ(loot::Game::tes5, game.Id()); - EXPECT_EQ(settings.Name(), game.Name()); - EXPECT_EQ(settings.FolderName(), game.FolderName()); - EXPECT_EQ(settings.Master(), game.Master()); - EXPECT_EQ(settings.RegistryKey(), game.RegistryKey()); - EXPECT_EQ(settings.RepoURL(), game.RepoURL()); - EXPECT_EQ(settings.RepoBranch(), game.RepoBranch()); - - EXPECT_EQ(settings.GamePath(), game.GamePath()); - EXPECT_EQ(settings.DataPath(), game.DataPath()); - EXPECT_EQ(settings.MasterlistPath(), game.MasterlistPath()); - EXPECT_EQ(settings.UserlistPath(), game.UserlistPath()); - - EXPECT_FALSE(game.ArePluginsFullyLoaded()); - - game = loot::Game(settings); - - EXPECT_EQ(loot::Game::tes5, game.Id()); - EXPECT_EQ(settings.Name(), game.Name()); - EXPECT_EQ(settings.FolderName(), game.FolderName()); - EXPECT_EQ(settings.Master(), game.Master()); - EXPECT_EQ(settings.RegistryKey(), game.RegistryKey()); - EXPECT_EQ(settings.RepoURL(), game.RepoURL()); - EXPECT_EQ(settings.RepoBranch(), game.RepoBranch()); - - EXPECT_EQ(settings.GamePath(), game.GamePath()); - EXPECT_EQ(settings.DataPath(), game.DataPath()); - EXPECT_EQ(settings.MasterlistPath(), game.MasterlistPath()); - EXPECT_EQ(settings.UserlistPath(), game.UserlistPath()); - - EXPECT_FALSE(game.ArePluginsFullyLoaded()); -} - -TEST_F(Game, Init) { - // Should throw for invalid ID. - loot::Game game; - EXPECT_THROW(game.Init(false), loot::error); - EXPECT_THROW(game.Init(true), loot::error); - EXPECT_THROW(game.Init(false, localPath), loot::error); - EXPECT_THROW(game.Init(true, localPath), loot::error); - -#ifndef _WIN32 - // No point testing installation detection on Windows, because it will - // find real installs, and the multi-game fixtures are set up so that they - // won't get auto-detected. Test for failure on Linux though. - game = loot::Game(loot::Game::tes5); - EXPECT_THROW(game.Init(false), loot::error); - EXPECT_THROW(game.Init(true), loot::error); - EXPECT_THROW(game.Init(false, localPath), loot::error); - EXPECT_THROW(game.Init(true, localPath), loot::error); - - // No point testing LOOT folder creation on Windows, because there may be - // a real LOOT install. - // Not supplying a game local path on Linux should throw an exception. - game = loot::Game(loot::Game::tes5).SetGamePath(dataPath.parent_path()); - ASSERT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName())); - EXPECT_THROW(game.Init(false), loot::error); - EXPECT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName())); - - game = loot::Game(loot::Game::tes5).SetGamePath(dataPath.parent_path()); - EXPECT_NO_THROW(game.Init(false, localPath)); - EXPECT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName())); - EXPECT_TRUE(game.IsPluginActive("Skyrim.esm")); - EXPECT_TRUE(game.IsPluginActive("skyrim.esm")); - EXPECT_TRUE(game.IsPluginActive("Blank.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp")); - EXPECT_TRUE(game.IsPluginActive("Blank - Different Master Dependent.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp")); - - game = loot::Game(loot::Game::tes5).SetGamePath(dataPath.parent_path()); - EXPECT_NO_THROW(game.Init(true, localPath)); - EXPECT_TRUE(boost::filesystem::exists(loot::g_path_local / game.FolderName())); - EXPECT_TRUE(game.IsPluginActive("Skyrim.esm")); - EXPECT_TRUE(game.IsPluginActive("skyrim.esm")); - EXPECT_TRUE(game.IsPluginActive("Blank.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm")); - EXPECT_FALSE(game.IsPluginActive("Blank.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp")); - EXPECT_TRUE(game.IsPluginActive("Blank - Different Master Dependent.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp")); - EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp")); -#else - game = loot::Game(loot::Game::tes5).SetGamePath(dataPath.parent_path()); - EXPECT_NO_THROW(game.Init(false)); - - game = loot::Game(loot::Game::tes5).SetGamePath(dataPath.parent_path()); - EXPECT_NO_THROW(game.Init(false, localPath)); - -#endif -} - -TEST_F(Game, RedatePlugins) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - // Throw because game hasn't been initialised yet. - EXPECT_THROW(game.RedatePlugins(), loot::error); - - game.Init(false, localPath); - - std::vector loadOrder({ - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm.ghost", - "Blank - Different Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp", - }); - - time_t time = boost::filesystem::last_write_time(dataPath / "Skyrim.esm"); - // First set reverse timestamps to be sure. - for (size_t i = 1; i < loadOrder.size(); ++i) { - boost::filesystem::last_write_time(dataPath / loadOrder[i], time - i * 60); - ASSERT_EQ(time - i * 60, boost::filesystem::last_write_time(dataPath / loadOrder[i])); - } - EXPECT_NO_THROW(game.RedatePlugins()); - EXPECT_EQ(time, boost::filesystem::last_write_time(dataPath / "Skyrim.esm")); - for (size_t i = 1; i < loadOrder.size(); ++i) { - ASSERT_EQ(time + i * 60, boost::filesystem::last_write_time(dataPath / loadOrder[i])); - } -} - -TEST_F(Game, LoadPlugins) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - EXPECT_NO_THROW(game.LoadPlugins(false)); - EXPECT_EQ(11, game.GetPlugins().size()); - - // Check that all the plugins' data have loaded correctly. - ASSERT_NO_THROW(game.GetPlugin("Skyrim.esm")); - loot::Plugin plugin = game.GetPlugin("Skyrim.esm"); - EXPECT_EQ("Skyrim.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Skyrim.esm", std::vector(), 0xCF0), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF1), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF2), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF3), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF4), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF5), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF6), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF7), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF8), - libespm::FormId("Skyrim.esm", std::vector(), 0xCF9), - }), plugin.getFormIds()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("v5.0", plugin.getDescription()); - EXPECT_EQ(0x187BE342, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank.esm")); - plugin = game.GetPlugin("blank.esm"); - EXPECT_EQ("Blank.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esm", std::vector(), 0xCF0), - libespm::FormId("Blank.esm", std::vector(), 0xCF1), - libespm::FormId("Blank.esm", std::vector(), 0xCF2), - libespm::FormId("Blank.esm", std::vector(), 0xCF3), - libespm::FormId("Blank.esm", std::vector(), 0xCF4), - libespm::FormId("Blank.esm", std::vector(), 0xCF5), - libespm::FormId("Blank.esm", std::vector(), 0xCF6), - libespm::FormId("Blank.esm", std::vector(), 0xCF7), - libespm::FormId("Blank.esm", std::vector(), 0xCF8), - libespm::FormId("Blank.esm", std::vector(), 0xCF9), - }), plugin.getFormIds()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("v5.0", plugin.getDescription()); - EXPECT_EQ(0x187BE342, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("Blank - Different.esm")); - plugin = game.GetPlugin("Blank - Different.esm"); - EXPECT_EQ("Blank - Different.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank - Different.esm", std::vector(), 0xCEF), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF0), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF1), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF2), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF3), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF4), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF5), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF6), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF7), - }), plugin.getFormIds()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0x64B9F757, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esm")); - plugin = game.GetPlugin("blank - master dependent.esm"); - EXPECT_EQ("Blank - Master Dependent.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esm", std::vector(), 0xCF0), - libespm::FormId("Blank.esm", std::vector(), 0xCF1), - libespm::FormId("Blank.esm", std::vector(), 0xCF2), - libespm::FormId("Blank.esm", std::vector(), 0xCF3), - libespm::FormId("Blank - Master Dependent.esm", std::vector(), 0xCEA), - libespm::FormId("Blank - Master Dependent.esm", std::vector(), 0xCEB), - libespm::FormId("Blank - Master Dependent.esm", std::vector(), 0xCEC), - libespm::FormId("Blank - Master Dependent.esm", std::vector(), 0xCED), - }), plugin.getFormIds()); - EXPECT_EQ(std::vector({ - "Blank.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0xB2D4119E, plugin.Crc()); - EXPECT_EQ(4, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esm")); - plugin = game.GetPlugin("blank - different master dependent.esm"); - EXPECT_EQ("Blank - Different Master Dependent.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank - Different.esm", std::vector(), 0xCEF), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF0), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF1), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF2), - libespm::FormId("Blank - Different Master Dependent.esm", std::vector(), 0xCE9), - libespm::FormId("Blank - Different Master Dependent.esm", std::vector(), 0xCEA), - libespm::FormId("Blank - Different Master Dependent.esm", std::vector(), 0xCEB), - }), plugin.getFormIds()); - EXPECT_EQ(std::vector({ - "Blank - Different.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0xAADF6710, plugin.Crc()); - EXPECT_EQ(4, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank.esp")); - plugin = game.GetPlugin("blank.esp"); - EXPECT_EQ("Blank.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esp", std::vector(), 0xCEC), - libespm::FormId("Blank.esp", std::vector(), 0xCED), - libespm::FormId("Blank.esp", std::vector(), 0xCEE), - libespm::FormId("Blank.esp", std::vector(), 0xCEF), - libespm::FormId("Blank.esp", std::vector(), 0xCF0), - libespm::FormId("Blank.esp", std::vector(), 0xCF1), - }), plugin.getFormIds()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("\xE2\x82\xAC\xC6\x92\xC5\xA0", plugin.getDescription()); - EXPECT_EQ(0x24F0E2A1, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different.esp")); - plugin = game.GetPlugin("blank - different.esp"); - EXPECT_EQ("Blank - Different.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank - Different.esp", std::vector(), 0xCEB), - libespm::FormId("Blank - Different.esp", std::vector(), 0xCEC), - libespm::FormId("Blank - Different.esp", std::vector(), 0xCED), - libespm::FormId("Blank - Different.esp", std::vector(), 0xCEE), - libespm::FormId("Blank - Different.esp", std::vector(), 0xCEF), - }), plugin.getFormIds()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0xD4C9B7AE, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esp")); - plugin = game.GetPlugin("blank - master dependent.esp"); - EXPECT_EQ("Blank - Master Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esm", std::vector(), 0xCF0), - libespm::FormId("Blank.esm", std::vector(), 0xCF1), - libespm::FormId("Blank - Master Dependent.esp", std::vector(), 0xCE9), - libespm::FormId("Blank - Master Dependent.esp", std::vector(), 0xCEA), - }), plugin.getFormIds()); - EXPECT_EQ(std::vector({ - "Blank.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0x832152DC, plugin.Crc()); - EXPECT_EQ(2, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esp")); - plugin = game.GetPlugin("blank - different master dependent.esp"); - EXPECT_EQ("Blank - Different Master Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank - Different.esm", std::vector(), 0xCEF), - libespm::FormId("Blank - Different.esm", std::vector(), 0xCF0), - libespm::FormId("Blank - Different Master Dependent.esp", std::vector(), 0xCE7), - }), plugin.getFormIds()); - EXPECT_EQ(std::vector({ - "Blank - Different.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0x3AD17683, plugin.Crc()); - EXPECT_EQ(2, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - plugin dependent.esp")); - plugin = game.GetPlugin("blank - plugin dependent.esp"); - EXPECT_EQ("Blank - Plugin Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esp", std::vector(), 0xCEC), - libespm::FormId("Blank - Plugin Dependent.esp", std::vector(), 0xCE7), - }), plugin.getFormIds()); - EXPECT_EQ(std::vector({ - "Blank.esp" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0x28EF26DB, plugin.Crc()); - EXPECT_EQ(1, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different plugin dependent.esp")); - plugin = game.GetPlugin("blank - different plugin dependent.esp"); - EXPECT_EQ("Blank - Different Plugin Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank - Different.esp", std::vector(), 0xCEB), - }), plugin.getFormIds()); - EXPECT_EQ(std::vector({ - "Blank - Different.esp" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0xEB47BE63, plugin.Crc()); - EXPECT_EQ(1, plugin.NumOverrideFormIDs()); -} - -TEST_F(Game, LoadPlugins_HeadersOnly) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - EXPECT_NO_THROW(game.LoadPlugins(true)); - EXPECT_EQ(11, game.GetPlugins().size()); - - // Check that all the plugins' data have loaded correctly. - ASSERT_NO_THROW(game.GetPlugin("Skyrim.esm")); - loot::Plugin plugin = game.GetPlugin("Skyrim.esm"); - EXPECT_EQ("Skyrim.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("v5.0", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank.esm")); - plugin = game.GetPlugin("blank.esm"); - EXPECT_EQ("Blank.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("v5.0", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("Blank - Different.esm")); - plugin = game.GetPlugin("Blank - Different.esm"); - EXPECT_EQ("Blank - Different.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esm")); - plugin = game.GetPlugin("blank - master dependent.esm"); - EXPECT_EQ("Blank - Master Dependent.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_EQ(std::vector({ - "Blank.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esm")); - plugin = game.GetPlugin("blank - different master dependent.esm"); - EXPECT_EQ("Blank - Different Master Dependent.esm", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_EQ(std::vector({ - "Blank - Different.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank.esp")); - plugin = game.GetPlugin("blank.esp"); - EXPECT_EQ("Blank.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("\xE2\x82\xAC\xC6\x92\xC5\xA0", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different.esp")); - plugin = game.GetPlugin("blank - different.esp"); - EXPECT_EQ("Blank - Different.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esp")); - plugin = game.GetPlugin("blank - master dependent.esp"); - EXPECT_EQ("Blank - Master Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_EQ(std::vector({ - "Blank.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esp")); - plugin = game.GetPlugin("blank - different master dependent.esp"); - EXPECT_EQ("Blank - Different Master Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_EQ(std::vector({ - "Blank - Different.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - plugin dependent.esp")); - plugin = game.GetPlugin("blank - plugin dependent.esp"); - EXPECT_EQ("Blank - Plugin Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_EQ(std::vector({ - "Blank.esp" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - - ASSERT_NO_THROW(game.GetPlugin("blank - different plugin dependent.esp")); - plugin = game.GetPlugin("blank - different plugin dependent.esp"); - EXPECT_EQ("Blank - Different Plugin Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_EQ(std::vector({ - "Blank - Different.esp" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - EXPECT_EQ(0, plugin.NumOverrideFormIDs()); -} - -TEST_F(Game, ArePluginsFullyLoaded) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - EXPECT_FALSE(game.ArePluginsFullyLoaded()); - - ASSERT_NO_THROW(game.LoadPlugins(false)); - EXPECT_TRUE(game.ArePluginsFullyLoaded()); -} - -TEST_F(Game, shouldThrowIfCheckingIfPluginThatIsntLoadedIsActiveAndGameHasNotBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - EXPECT_ANY_THROW(game.IsPluginActive("Blank.esm")); -} - -TEST_F(Game, shouldShowBlankEsmAsActiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - EXPECT_TRUE(game.IsPluginActive("Blank.esm")); -} - -TEST_F(Game, shouldShowBlankEspAsInctiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - EXPECT_FALSE(game.IsPluginActive("Blank.esp")); -} - -TEST_F(Game, shouldShowBlankEsmAsInactiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - EXPECT_FALSE(game.IsPluginActive("Blank.esm")); -} - -TEST_F(Game, shouldShowBlankEspAsActiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - EXPECT_FALSE(game.IsPluginActive("Blank.esp")); -} - -TEST_F(Game, shouldShowBlankEsmAsActiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - EXPECT_TRUE(game.IsPluginActive("Blank.esm")); -} - -TEST_F(Game, shouldShowBlankEspAsActiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - EXPECT_FALSE(game.IsPluginActive("Blank.esp")); -} - -TEST_F(Game, shouldShowBlankEsmAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(false)); - - EXPECT_TRUE(game.IsPluginActive("Blank.esm")); -} - -TEST_F(Game, shouldShowBlankEspAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(false)); - - EXPECT_FALSE(game.IsPluginActive("Blank.esp")); -} - -#endif diff --git a/src/tests/backend/game/test_game_cache.h b/src/tests/backend/game/test_game_cache.h deleted file mode 100644 index 6a6f734d..00000000 --- a/src/tests/backend/game/test_game_cache.h +++ /dev/null @@ -1,218 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_GAME_CACHE -#define LOOT_TEST_BACKEND_GAME_CACHE - -#include "backend/game/game_cache.h" - -#include "tests/fixtures.h" - -namespace loot { - namespace test { - class GameCache : public SkyrimTest { - protected: - loot::GameCache cache; - }; - - TEST_F(GameCache, copyConstructorShouldCopyCachedData) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - cache.CacheCondition("True Condition", true); - cache.AddPlugin(loot::Plugin(game, "Blank.esm", true)); - Message expectedMessage(Message::say, "1"); - cache.AppendMessage(expectedMessage); - cache.SetLoadOrderSorted(true); - - loot::GameCache otherCache(cache); - EXPECT_EQ(std::make_pair(true, true), otherCache.GetCachedCondition("true Condition")); - EXPECT_EQ("Blank.esm", otherCache.GetPlugin("Blank.esm").Name()); - ASSERT_EQ(1, otherCache.GetMessages().size()); - EXPECT_EQ(expectedMessage, otherCache.GetMessages()[0]); - } - - TEST_F(GameCache, assignmentOperatorShouldCopyCachedData) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - cache.CacheCondition("True Condition", true); - cache.AddPlugin(loot::Plugin(game, "Blank.esm", true)); - Message expectedMessage(Message::say, "1"); - cache.AppendMessage(expectedMessage); - cache.SetLoadOrderSorted(true); - - loot::GameCache otherCache = cache; - EXPECT_EQ(std::make_pair(true, true), otherCache.GetCachedCondition("true Condition")); - EXPECT_EQ("Blank.esm", otherCache.GetPlugin("Blank.esm").Name()); - ASSERT_EQ(1, otherCache.GetMessages().size()); - EXPECT_EQ(expectedMessage, otherCache.GetMessages()[0]); - } - - TEST_F(GameCache, gettingATrueConditionShouldReturnATrueTruePair) { - EXPECT_NO_THROW(cache.CacheCondition("True Condition", true)); - - EXPECT_EQ(std::make_pair(true, true), cache.GetCachedCondition("true Condition")); - } - - TEST_F(GameCache, gettingAFalseConditionShouldReturnAFalseTruePair) { - EXPECT_NO_THROW(cache.CacheCondition("False Condition", false)); - - EXPECT_EQ(std::make_pair(false, true), cache.GetCachedCondition("false Condition")); - } - - TEST_F(GameCache, gettingANonCachedConditionShouldReturnAFalseFalsePair) { - EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("true missing Condition")); - } - - TEST_F(GameCache, addingAPluginThatDoesNotExistShouldSucceed) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - cache.AddPlugin(loot::Plugin(game, "Blank.esm", true)); - EXPECT_EQ("Blank.esm", cache.GetPlugin("Blank.esm").Name()); - } - - TEST_F(GameCache, addingAPluginThatIsAlreadyCachedShouldOverwriteExistingEntry) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - cache.AddPlugin(loot::Plugin(game, "Blank.esm", true)); - EXPECT_EQ(0, cache.GetPlugin("Blank.esm").Crc()); - - cache.AddPlugin(loot::Plugin(game, "Blank.esm", false)); - EXPECT_EQ(0x187BE342, cache.GetPlugin("Blank.esm").Crc()); - } - - TEST_F(GameCache, gettingAPluginThatIsNotCachedShouldThrow) { - EXPECT_ANY_THROW(cache.GetPlugin("Blank.esm")); - } - - TEST_F(GameCache, gettingAPluginShouldBeCaseInsensitive) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - cache.AddPlugin(loot::Plugin(game, "Blank.esm", true)); - EXPECT_EQ("Blank.esm", cache.GetPlugin("blanK.esm").Name()); - } - - TEST_F(GameCache, gettingPluginsShouldReturnAnEmptySetIfNoPluginsHaveBeenCached) { - EXPECT_TRUE(cache.GetPlugins().empty()); - } - - TEST_F(GameCache, gettingPluginsShouldReturnASetOfCachedPluginsIfPluginsHaveBeenCached) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - cache.AddPlugin(loot::Plugin(game, "Blank.esm", true)); - cache.AddPlugin(loot::Plugin(game, "Blank - Master Dependent.esp", true)); - - EXPECT_EQ(std::set({ - loot::Plugin(game, "Blank.esm", true), - loot::Plugin(game, "Blank - Master Dependent.esp", true), - }), cache.GetPlugins()); - } - - TEST_F(GameCache, clearingCachedConditionsShouldNotThrowIfNoConditionsAreCached) { - EXPECT_NO_THROW(cache.ClearCachedConditions()); - } - - TEST_F(GameCache, clearingCachedConditionsShouldClearAnyCachedConditions) { - EXPECT_NO_THROW(cache.CacheCondition("True Condition", true)); - - EXPECT_NO_THROW(cache.ClearCachedConditions()); - - EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("true Condition")); - } - - TEST_F(GameCache, clearingCachedPluginsShouldNotThrowIfNoPluginsAreCached) { - EXPECT_NO_THROW(cache.ClearCachedPlugins()); - } - - TEST_F(GameCache, clearingCachedPluginsShouldClearAnyCachedPlugins) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - cache.AddPlugin(loot::Plugin(game, "Blank.esm", true)); - cache.ClearCachedPlugins(); - - EXPECT_TRUE(cache.GetPlugins().empty()); - } - - TEST_F(GameCache, aMessageShouldBeCachedByDefault) { - ASSERT_EQ(1, cache.GetMessages().size()); - } - - TEST_F(GameCache, settingLoadOrderSortedToTrueShouldSupressDefaultCachedMessage) { - cache.SetLoadOrderSorted(true); - - ASSERT_TRUE(cache.GetMessages().empty()); - } - - TEST_F(GameCache, settingLoadOrderSortedToFalseShouldReverseTheDefaultCachedMessageSuppression) { - auto expectedMessages = cache.GetMessages(); - cache.SetLoadOrderSorted(true); - cache.SetLoadOrderSorted(false); - - ASSERT_EQ(expectedMessages, cache.GetMessages()); - } - - TEST_F(GameCache, appendingMessagesShouldStoreThemInTheGivenOrder) { - std::vector messages({ - Message(Message::say, "1"), - Message(Message::error, "2"), - }); - for (const auto& message : messages) - cache.AppendMessage(message); - - ASSERT_EQ(3, cache.GetMessages().size()); - EXPECT_EQ(messages[0], cache.GetMessages()[0]); - EXPECT_EQ(messages[1], cache.GetMessages()[1]); - } - - TEST_F(GameCache, clearingMessagesShouldRemoveAllAppendedMessages) { - std::vector messages({ - Message(Message::say, "1"), - Message(Message::error, "2"), - }); - for (const auto& message : messages) - cache.AppendMessage(message); - - auto previousSize = cache.GetMessages().size(); - - cache.ClearMessages(); - - EXPECT_EQ(previousSize - messages.size(), cache.GetMessages().size()); - } - } -} - -#endif diff --git a/src/tests/backend/game/test_game_settings.h b/src/tests/backend/game/test_game_settings.h deleted file mode 100644 index e6f95691..00000000 --- a/src/tests/backend/game/test_game_settings.h +++ /dev/null @@ -1,254 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_GAME_SETTINGS -#define LOOT_TEST_BACKEND_GAME_SETTINGS - -#include "backend/globals.h" -#include "backend/game/game_settings.h" -#include "tests/fixtures.h" - -class GameSettings : public SkyrimTest {}; - -TEST_F(GameSettings, ConstructorsAndDataAccess) { - loot::GameSettings game; - - EXPECT_EQ(loot::GameSettings::autodetect, game.Id()); - EXPECT_EQ("", game.Name()); - EXPECT_EQ("", game.FolderName()); - EXPECT_EQ("", game.Master()); - EXPECT_EQ("", game.RegistryKey()); - EXPECT_EQ("", game.RepoURL()); - EXPECT_EQ("", game.RepoBranch()); - - EXPECT_EQ("", game.GamePath()); - EXPECT_EQ("", game.DataPath()); - EXPECT_EQ("", game.MasterlistPath()); - EXPECT_EQ("", game.UserlistPath()); - - game = loot::GameSettings(loot::GameSettings::tes5); - - EXPECT_EQ(loot::GameSettings::tes5, game.Id()); - EXPECT_EQ("TES V: Skyrim", game.Name()); - EXPECT_EQ("Skyrim", game.FolderName()); - EXPECT_EQ("Skyrim.esm", game.Master()); - EXPECT_EQ("Software\\Bethesda Softworks\\Skyrim\\Installed Path", game.RegistryKey()); - EXPECT_EQ("https://github.com/loot/skyrim.git", game.RepoURL()); - // Repo branch changes between LOOT versions, so don't check an exact value. - EXPECT_NE("", game.RepoBranch()); - - EXPECT_EQ("", game.GamePath()); - EXPECT_EQ("", game.DataPath()); - EXPECT_EQ(loot::g_path_local / "Skyrim" / "masterlist.yaml", game.MasterlistPath()); - EXPECT_EQ(loot::g_path_local / "Skyrim" / "userlist.yaml", game.UserlistPath()); - - game = loot::GameSettings(loot::GameSettings::tes5, "folder"); - - EXPECT_EQ(loot::GameSettings::tes5, game.Id()); - EXPECT_EQ("TES V: Skyrim", game.Name()); - EXPECT_EQ("folder", game.FolderName()); - EXPECT_EQ("Skyrim.esm", game.Master()); - EXPECT_EQ("Software\\Bethesda Softworks\\Skyrim\\Installed Path", game.RegistryKey()); - EXPECT_EQ("https://github.com/loot/skyrim.git", game.RepoURL()); - // Repo branch changes between LOOT versions, so don't check an exact value. - EXPECT_NE("", game.RepoBranch()); - - EXPECT_EQ("", game.GamePath()); - EXPECT_EQ("", game.DataPath()); - EXPECT_EQ(loot::g_path_local / "folder" / "masterlist.yaml", game.MasterlistPath()); - EXPECT_EQ(loot::g_path_local / "folder" / "userlist.yaml", game.UserlistPath()); -} - -TEST_F(GameSettings, IsInstalled) { - loot::GameSettings game; - EXPECT_FALSE(game.IsInstalled()); - - game = loot::GameSettings(loot::GameSettings::tes5); - game.SetGamePath(dataPath.parent_path()); - EXPECT_TRUE(game.IsInstalled()); - EXPECT_EQ(dataPath.parent_path(), game.GamePath()); - - game = loot::GameSettings(loot::GameSettings::fo3); - EXPECT_FALSE(game.IsInstalled()); -} - -TEST_F(GameSettings, EqualityOperators) { - loot::GameSettings game1, game2; - EXPECT_TRUE(game1 == game2); - - game1 = loot::GameSettings(loot::GameSettings::tes5); - game2 = loot::GameSettings(loot::GameSettings::tes5); - EXPECT_TRUE(game1 == game2); - - game1 = loot::GameSettings(loot::GameSettings::tes5, "game1") - .SetMaster("master1") - .SetRegistryKey("key1") - .SetRepoURL("url1") - .SetRepoBranch("branch1") - .SetGamePath("path1"); - game2 = loot::GameSettings(loot::GameSettings::tes5, "game2") - .SetMaster("master2") - .SetRegistryKey("key2") - .SetRepoURL("url2") - .SetRepoBranch("branch2") - .SetGamePath("path2"); - EXPECT_TRUE(game1 == game2); - - game1 = loot::GameSettings(loot::GameSettings::tes4) - .SetName("name"); - game2 = loot::GameSettings(loot::GameSettings::tes5) - .SetName("name"); - EXPECT_TRUE(game1 == game2); - - game1 = loot::GameSettings(loot::GameSettings::tes4); - game2 = loot::GameSettings(loot::GameSettings::tes5); - EXPECT_FALSE(game1 == game2); -} - -TEST_F(GameSettings, SetName) { - loot::GameSettings game; - game.SetName("name"); - EXPECT_EQ("name", game.Name()); -} - -TEST_F(GameSettings, SetMaster) { - loot::GameSettings game; - game.SetMaster("master"); - EXPECT_EQ("master", game.Master()); -} - -TEST_F(GameSettings, SetRegistryKey) { - loot::GameSettings game; - game.SetRegistryKey("key"); - EXPECT_EQ("key", game.RegistryKey()); -} - -TEST_F(GameSettings, SetRepoURL) { - loot::GameSettings game; - game.SetRepoURL("url"); - EXPECT_EQ("url", game.RepoURL()); -} - -TEST_F(GameSettings, SetRepoBranch) { - loot::GameSettings game; - game.SetRepoBranch("branch"); - EXPECT_EQ("branch", game.RepoBranch()); -} - -TEST_F(GameSettings, SetGamePath) { - loot::GameSettings game; - game.SetGamePath("path"); - EXPECT_EQ("path", game.GamePath().string()); - EXPECT_EQ(boost::filesystem::path("path") / "Data", game.DataPath()); -} - -TEST_F(GameSettings, YamlEmitter) { - loot::GameSettings game(loot::GameSettings::tes5, "folder1"); - game.SetName("name1") - .SetMaster("master1") - .SetRegistryKey("key1") - .SetRepoURL("url1") - .SetRepoBranch("branch1") - .SetGamePath("path1"); - - YAML::Emitter e; - e << game; - EXPECT_STREQ("type: 'Skyrim'\n" - "folder: 'folder1'\n" - "name: 'name1'\n" - "master: 'master1'\n" - "repo: 'url1'\n" - "branch: 'branch1'\n" - "path: 'path1'\n" - "registry: 'key1'", e.c_str()); -} - -TEST_F(GameSettings, YamlEncode) { - loot::GameSettings game(loot::GameSettings::tes5, "folder1"); - game.SetName("name1") - .SetMaster("master1") - .SetRegistryKey("key1") - .SetRepoURL("url1") - .SetRepoBranch("branch1") - .SetGamePath("path1"); - - YAML::Node node; - node = game; - EXPECT_EQ("Skyrim", node["type"].as()); - EXPECT_EQ("folder1", node["folder"].as()); - EXPECT_EQ("name1", node["name"].as()); - EXPECT_EQ("master1", node["master"].as()); - EXPECT_EQ("url1", node["repo"].as()); - EXPECT_EQ("branch1", node["branch"].as()); - EXPECT_EQ("path1", node["path"].as()); - EXPECT_EQ("key1", node["registry"].as()); -} - -TEST_F(GameSettings, YamlDecode) { - YAML::Node node = YAML::Load("type: 'Skyrim'\n" - "folder: 'folder1'\n" - "name: 'name1'\n" - "master: 'master1'\n" - "repo: 'url1'\n" - "branch: 'branch1'\n" - "path: 'path1'\n" - "registry: 'key1'"); - - loot::GameSettings game = node.as(); - EXPECT_EQ(loot::GameSettings::tes5, game.Id()); - EXPECT_EQ("name1", game.Name()); - EXPECT_EQ("folder1", game.FolderName()); - EXPECT_EQ("master1", game.Master()); - EXPECT_EQ("key1", game.RegistryKey()); - EXPECT_EQ("url1", game.RepoURL()); - EXPECT_EQ("branch1", game.RepoBranch()); - EXPECT_EQ("path1", game.GamePath()); - - node = YAML::Load("type: 'Invalid'\n"); - EXPECT_ANY_THROW(node.as()); - - node = YAML::Load("scalar"); - EXPECT_ANY_THROW(node.as()); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_ANY_THROW(node.as()); - - // Test inheritance of unspecified settings. - node = YAML::Load("type: 'Skyrim'\n" - "folder: 'folder1'\n" - "master: 'master1'\n" - "repo: 'url1'\n" - "branch: 'branch1'\n"); - - game = node.as(); - EXPECT_EQ(loot::GameSettings::tes5, game.Id()); - EXPECT_EQ("TES V: Skyrim", game.Name()); - EXPECT_EQ("folder1", game.FolderName()); - EXPECT_EQ("master1", game.Master()); - EXPECT_EQ("Software\\Bethesda Softworks\\Skyrim\\Installed Path", game.RegistryKey()); - EXPECT_EQ("url1", game.RepoURL()); - EXPECT_EQ("branch1", game.RepoBranch()); - EXPECT_EQ("", game.GamePath()); -} -#endif diff --git a/src/tests/backend/game/test_load_order_handler.h b/src/tests/backend/game/test_load_order_handler.h deleted file mode 100644 index 0e076195..00000000 --- a/src/tests/backend/game/test_load_order_handler.h +++ /dev/null @@ -1,142 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_LOAD_ORDER_HANDLER -#define LOOT_TEST_BACKEND_LOAD_ORDER_HANDLER - -#include "backend/error.h" -#include "backend/game/load_order_handler.h" - -#include "tests/fixtures.h" - -class LoadOrderHandler : public SkyrimTest {}; - -TEST_F(LoadOrderHandler, Constructors) { - loot::LoadOrderHandler * loh = nullptr; - EXPECT_NO_THROW(loh = new loot::LoadOrderHandler); - EXPECT_NO_THROW(delete loh); -} - -TEST_F(LoadOrderHandler, Init) { - // Should throw for invalid game settings ID. - loot::LoadOrderHandler loh; - loot::GameSettings game(loot::GameSettings::autodetect); - EXPECT_THROW(loh.Init(game), loot::error); - EXPECT_THROW(loh.Init(game), loot::error); - EXPECT_THROW(loh.Init(game, localPath), loot::error); - EXPECT_THROW(loh.Init(game, localPath), loot::error); - - // Should throw an exception if no game path has been set. - game = loot::GameSettings(loot::GameSettings::tes5); - EXPECT_THROW(loh.Init(game), loot::error); - EXPECT_THROW(loh.Init(game), loot::error); - EXPECT_THROW(loh.Init(game, localPath), loot::error); - EXPECT_THROW(loh.Init(game, localPath), loot::error); - -#ifndef _WIN32 - // Should throw on Linux if no game local app data path is given. - game = loot::GameSettings(loot::GameSettings::tes5) - .SetGamePath(dataPath.parent_path()); - EXPECT_THROW(loh.Init(game), loot::error); -#endif - - game = loot::GameSettings(loot::GameSettings::tes5) - .SetGamePath(dataPath.parent_path()); - EXPECT_NO_THROW(loh.Init(game, localPath)); -} - -TEST_F(LoadOrderHandler, IsPluginActive) { - loot::LoadOrderHandler loh; - loot::GameSettings game(loot::GameSettings::tes5); - game.SetGamePath(dataPath.parent_path()); - - EXPECT_THROW(loh.IsPluginActive("Skyrim.esm"), loot::error); - - ASSERT_NO_THROW(loh.Init(game, localPath)); - - EXPECT_TRUE(loh.IsPluginActive("Skyrim.esm")); - EXPECT_TRUE(loh.IsPluginActive("Blank.esm")); - EXPECT_TRUE(loh.IsPluginActive("Blank - Different Master Dependent.esp")); - EXPECT_FALSE(loh.IsPluginActive("Blank.esp")); -} - -TEST_F(LoadOrderHandler, GetLoadOrder) { - loot::LoadOrderHandler loh; - loot::GameSettings game(loot::GameSettings::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(loh.Init(game, localPath)); - - std::list expected({ - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp" - }); - - EXPECT_EQ(expected, loh.GetLoadOrder()); -} - -TEST_F(LoadOrderHandler, SetLoadOrder) { - loot::LoadOrderHandler loh; - loot::GameSettings game(loot::GameSettings::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(loh.Init(game, localPath)); - - std::list loadOrder({ - "Skyrim.esm", - "Blank.esm", - "Blank - Master Dependent.esm", - "Blank - Different.esm", - "Blank - Different Master Dependent.esm", - "Blank - Different.esp", - "Blank - Different Plugin Dependent.esp", - "Blank.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Plugin Dependent.esp", - }); - - EXPECT_NO_THROW(loh.SetLoadOrder(loadOrder)); - - std::list actual; - boost::filesystem::ifstream in(localPath / "loadorder.txt"); - while (in) { - std::string line; - std::getline(in, line); - - if (!line.empty()) - actual.push_back(line); - } - - EXPECT_EQ(loadOrder, actual); -} - -#endif diff --git a/src/tests/backend/helpers/git_helper_test.h b/src/tests/backend/helpers/git_helper_test.h new file mode 100644 index 00000000..23a7469f --- /dev/null +++ b/src/tests/backend/helpers/git_helper_test.h @@ -0,0 +1,153 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_HELPERS_GIT_HELPER +#define LOOT_TEST_BACKEND_HELPERS_GIT_HELPER + +#include "backend/error.h" +#include "backend/helpers/git_helper.h" + +#include + +namespace loot { + namespace test { + class GitHelperTest : public ::testing::Test { + protected: + GitHelperTest() : + parentRepoRoot(getRepoRoot()) {} + + inline virtual void SetUp() { + ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "README.md")); + + // Create a backup of CONTRIBUTING.md. + ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md")); + ASSERT_FALSE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md.copy")); + ASSERT_NO_THROW(boost::filesystem::copy(parentRepoRoot / "CONTRIBUTING.md", parentRepoRoot / "CONTRIBUTING.md.copy")); + ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md.copy")); + + // Edit CONTRIBUTING.md + boost::filesystem::ofstream out(parentRepoRoot / "CONTRIBUTING.md"); + out.close(); + } + + inline virtual void TearDown() { + // Restore original CONTRIBUTING.md + ASSERT_NO_THROW(boost::filesystem::remove(parentRepoRoot / "CONTRIBUTING.md")); + ASSERT_NO_THROW(boost::filesystem::rename(parentRepoRoot / "CONTRIBUTING.md.copy", parentRepoRoot / "CONTRIBUTING.md")); + ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md")); + ASSERT_FALSE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md.copy")); + } + + GitHelper git; + + const boost::filesystem::path parentRepoRoot; + + private: + inline static boost::filesystem::path getRepoRoot() { + boost::filesystem::path dir = boost::filesystem::current_path(); + while (!boost::filesystem::exists(dir / ".git")) { + dir = dir.parent_path(); + } + + return dir; + } + }; + + TEST_F(GitHelperTest, repoShouldInitialiseAsANullPointer) { + EXPECT_EQ(nullptr, git.repo); + } + + TEST_F(GitHelperTest, destructorShouldCallLibgit2CleanupFunction) { + ASSERT_EQ(2, git_libgit2_init()); + + GitHelper * gitPointer = new GitHelper(); + ASSERT_EQ(4, git_libgit2_init()); + + delete gitPointer; + EXPECT_EQ(2, git_libgit2_shutdown()); + } + + TEST_F(GitHelperTest, callShouldNotThrowIfPassedAZeroValue) { + EXPECT_NO_THROW(git.Call(0)); + } + + TEST_F(GitHelperTest, callShouldThrowIfPassedANonZeroValue) { + EXPECT_THROW(git.Call(1), error); + EXPECT_THROW(git.Call(-1), error); + } + + TEST_F(GitHelperTest, setErrorMessageShouldSetTheMessageForThrownExceptions) { + const char * errorMessage = "test message"; + git.SetErrorMessage(errorMessage); + + try { + git.Call(1); + ADD_FAILURE() << "An exception should have been thrown."; + } + catch (error& e) { + EXPECT_NE(nullptr, strstr(e.what(), errorMessage)); + } + } + + TEST_F(GitHelperTest, freeShouldFreeMemoryAllocatedToMembers) { + // Initialise buffer member, it's simplest to test with. + GitHelper git; + git_buf_set(&git.buf, "foo", 4); + ASSERT_NE(nullptr, git.buf.ptr); + ASSERT_EQ(4, git.buf.size); + + git.Free(); + EXPECT_EQ(nullptr, git.buf.ptr); + EXPECT_EQ(0, git.buf.size); + } + + TEST_F(GitHelperTest, isRepositoryShouldReturnTrueForARepositoryRoot) { + EXPECT_TRUE(GitHelper::IsRepository(parentRepoRoot)); + } + + TEST_F(GitHelperTest, isRepositoryShouldReturnFalseForRepositorySubdirectory) { + EXPECT_FALSE(GitHelper::IsRepository(boost::filesystem::current_path())); + } + + TEST_F(GitHelperTest, isFileDifferentShouldThrowIfGivenANonRepositoryPath) { + EXPECT_THROW(GitHelper::IsFileDifferent(boost::filesystem::current_path(), "README.md"), error); + } + + TEST_F(GitHelperTest, isFileDifferentShouldReturnFalseForAnUntrackedFile) { + // New files not in the index are not tracked by Git, so aren't considered + // different. + EXPECT_FALSE(GitHelper::IsFileDifferent(parentRepoRoot, "CONTRIBUTING.md.copy")); + } + + TEST_F(GitHelperTest, isFileDifferentShouldReturnFalseForAnUnchangedTrackedFile) { + EXPECT_FALSE(GitHelper::IsFileDifferent(parentRepoRoot, "README.md")); + } + + TEST_F(GitHelperTest, isFileDifferentShouldReturnTrueForAChangedTrackedFile) { + EXPECT_TRUE(GitHelper::IsFileDifferent(parentRepoRoot, "CONTRIBUTING.md")); + } + } +} + +#endif diff --git a/src/tests/backend/helpers/helpers_test.h b/src/tests/backend/helpers/helpers_test.h new file mode 100644 index 00000000..d8b6b80f --- /dev/null +++ b/src/tests/backend/helpers/helpers_test.h @@ -0,0 +1,64 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_HELPERS +#define LOOT_TEST_BACKEND_HELPERS + +#include "backend/helpers/helpers.h" +#include "backend/error.h" + +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class GetCrc32Test : public BaseGameTest {}; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + // Just test with one game because if it works for one it will work for them + // all. + INSTANTIATE_TEST_CASE_P(, + GetCrc32Test, + ::testing::Values( + GameSettings::tes5)); + + TEST_P(GetCrc32Test, gettingTheCrcOfAMissingFileShouldThrow) { + EXPECT_THROW(GetCrc32(dataPath / missingEsp), error); + } + + TEST_P(GetCrc32Test, gettingTheCrcOfAFileShouldReturnTheCorrectValue) { + EXPECT_EQ(blankEsmCrc, GetCrc32(dataPath / blankEsm)); + } + + TEST(IntToHexString, intToHexStringShouldOutputANonZeroPositiveIntegerCorrectly) { + EXPECT_EQ("14", IntToHexString(20)); + } + + TEST(IntToHexString, intToHexStringShouldOutputZeroCorrectly) { + EXPECT_EQ("0", IntToHexString(0)); + } + } +} + +#endif diff --git a/src/tests/backend/helpers/language_test.h b/src/tests/backend/helpers/language_test.h new file mode 100644 index 00000000..d8208cf2 --- /dev/null +++ b/src/tests/backend/helpers/language_test.h @@ -0,0 +1,92 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_HELPERS_LANGUAGE +#define LOOT_TEST_BACKEND_HELPERS_LANGUAGE + +#include "backend/helpers/language.h" + +#include + +namespace loot { + namespace test { + TEST(Language, codeConstructorShouldSetTheCorrectData) { + Language lang(Language::english); + EXPECT_EQ(Language::english, lang.Code()); + EXPECT_EQ("English", lang.Name()); + EXPECT_EQ("en", lang.Locale()); + + lang = Language(Language::polish); + EXPECT_EQ(Language::polish, lang.Code()); + EXPECT_EQ("Polski", lang.Name()); + EXPECT_EQ("pl", lang.Locale()); + } + + TEST(Language, localeConstructorShouldSetTheCorrectData) { + Language lang("en"); + EXPECT_EQ(Language::english, lang.Code()); + EXPECT_EQ("English", lang.Name()); + EXPECT_EQ("en", lang.Locale()); + + lang = Language("de"); + EXPECT_EQ(Language::german, lang.Code()); + EXPECT_EQ("Deutsch", lang.Name()); + EXPECT_EQ("de", lang.Locale()); + } + + TEST(Language, codeConstructorShouldTreatAnInvalidCodeAsEnglish) { + Language lang(1000); + EXPECT_EQ(Language::english, lang.Code()); + EXPECT_EQ("English", lang.Name()); + EXPECT_EQ("en", lang.Locale()); + } + + TEST(Language, localeConstructorShouldTreatAnInvalidLocaleAsEnglish) { + Language lang("foo"); + EXPECT_EQ(Language::english, lang.Code()); + EXPECT_EQ("English", lang.Name()); + EXPECT_EQ("en", lang.Locale()); + } + + TEST(Language, codesShouldContainAllExpectedLanguageCodes) { + std::vector codes = { + Language::english, + Language::spanish, + Language::russian, + Language::french, + Language::chinese, + Language::polish, + Language::brazilian_portuguese, + Language::finnish, + Language::german, + Language::danish, + Language::korean + }; + + EXPECT_EQ(codes, Language::Codes); + } + } +} + +#endif diff --git a/src/tests/backend/helpers/test_git_helper.h b/src/tests/backend/helpers/test_git_helper.h deleted file mode 100644 index e680ae33..00000000 --- a/src/tests/backend/helpers/test_git_helper.h +++ /dev/null @@ -1,135 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_HELPERS_LANGUAGE -#define LOOT_TEST_BACKEND_HELPERS_LANGUAGE - -#include "backend/error.h" -#include "backend/helpers/git_helper.h" -#include "tests/fixtures.h" - -using loot::GitHelper; - -#ifdef _WIN32 -boost::filesystem::path parentRepoRoot = boost::filesystem::current_path().parent_path().parent_path(); -#else -boost::filesystem::path parentRepoRoot = boost::filesystem::current_path().parent_path(); -#endif - -TEST(GitHelper, ConstructorAndDestructor) { - GitHelper * git = new GitHelper(); - EXPECT_EQ(nullptr, git->repo); - - EXPECT_EQ(2, git_libgit2_init()); - delete git; - EXPECT_EQ(0, git_libgit2_shutdown()); -} - -TEST(GitHelper, Call) { - GitHelper git; - EXPECT_NO_THROW(git.Call(0)); - EXPECT_THROW(git.Call(1), loot::error); - EXPECT_THROW(git.Call(-1), loot::error); -} - -TEST(GitHelper, SetErrorMessage) { - GitHelper git; - git.SetErrorMessage("test message"); - - try { - git.Call(1); - ADD_FAILURE() << "An exception should have been thrown."; - } - catch (loot::error& e) { - EXPECT_NE(nullptr, strstr(e.what(), "test message")); - } -} - -TEST(GitHelper, Free) { - // Initialise buffer member, it's simplest to test with. - GitHelper git; - git_buf_set(&git.buf, "foo", 4); - EXPECT_NE(nullptr, git.buf.ptr); - EXPECT_EQ(4, git.buf.size); - - git.Free(); - EXPECT_EQ(nullptr, git.buf.ptr); - EXPECT_EQ(0, git.buf.size); -} - -TEST(GitHelper, IsRepository) { - GitHelper git; - - ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot)); - EXPECT_TRUE(git.IsRepository(parentRepoRoot)); - EXPECT_FALSE(git.IsRepository(boost::filesystem::current_path())); -} - -class IsFileDifferent : public ::testing::Test { - inline virtual void SetUp() { - GitHelper git; - ASSERT_TRUE(git.IsRepository(parentRepoRoot)); - ASSERT_FALSE(git.IsRepository(boost::filesystem::current_path())); - - ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "README.md")); - - // Create a backup of CONTRIBUTING.md. - ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md")); - ASSERT_FALSE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md.copy")); - ASSERT_NO_THROW(boost::filesystem::copy(parentRepoRoot / "CONTRIBUTING.md", parentRepoRoot / "CONTRIBUTING.md.copy")); - ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md.copy")); - - // Edit CONTRIBUTING.md - boost::filesystem::ofstream out(parentRepoRoot / "CONTRIBUTING.md"); - out.close(); - } - - inline virtual void TearDown() { - // Restore original CONTRIBUTING.md - ASSERT_NO_THROW(boost::filesystem::remove(parentRepoRoot / "CONTRIBUTING.md")); - ASSERT_NO_THROW(boost::filesystem::rename(parentRepoRoot / "CONTRIBUTING.md.copy", parentRepoRoot / "CONTRIBUTING.md")); - ASSERT_TRUE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md")); - ASSERT_FALSE(boost::filesystem::exists(parentRepoRoot / "CONTRIBUTING.md.copy")); - } -}; - -TEST_F(IsFileDifferent, InvalidRepository) { - EXPECT_THROW(loot::IsFileDifferent(boost::filesystem::current_path(), "README.md"), loot::error); -} - -TEST_F(IsFileDifferent, SameFile) { - EXPECT_FALSE(loot::IsFileDifferent(parentRepoRoot, "README.md")); -} - -TEST_F(IsFileDifferent, NewFile) { - // New files not in the index are not tracked by Git, so aren't considered - // different. - EXPECT_FALSE(loot::IsFileDifferent(parentRepoRoot, "CONTRIBUTING.md.copy")); -} - -TEST_F(IsFileDifferent, DifferentFile) { - EXPECT_TRUE(loot::IsFileDifferent(parentRepoRoot, "CONTRIBUTING.md")); -} - -#endif diff --git a/src/tests/backend/helpers/test_helpers.h b/src/tests/backend/helpers/test_helpers.h deleted file mode 100644 index ee917d8d..00000000 --- a/src/tests/backend/helpers/test_helpers.h +++ /dev/null @@ -1,47 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_HELPERS -#define LOOT_TEST_BACKEND_HELPERS - -#include "backend/helpers/helpers.h" -#include "backend/error.h" -#include "tests/fixtures.h" - -class GetCrc32 : public SkyrimTest {}; - -TEST_F(GetCrc32, MissingFile) { - EXPECT_THROW(loot::GetCrc32(dataPath / "Blank.missing.esp"), loot::error); -} - -TEST_F(GetCrc32, ValidFile) { - EXPECT_EQ(0x24F0E2A1, loot::GetCrc32(dataPath / "Blank.esp")); -} - -TEST(IntToHexString, PositiveAndZeroValues) { - EXPECT_EQ("14", loot::IntToHexString(20)); - EXPECT_EQ("0", loot::IntToHexString(0)); -} - -#endif diff --git a/src/tests/backend/helpers/test_language.h b/src/tests/backend/helpers/test_language.h deleted file mode 100644 index 681a4eee..00000000 --- a/src/tests/backend/helpers/test_language.h +++ /dev/null @@ -1,88 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_HELPERS_LANGUAGE -#define LOOT_TEST_BACKEND_HELPERS_LANGUAGE - -#include "backend/helpers/language.h" -#include "tests/fixtures.h" - -using loot::Language; - -TEST(Language, ConstructorsAndDataAccess) { - // Test English code and locale. - Language lang(Language::english); - EXPECT_EQ(Language::english, lang.Code()); - EXPECT_EQ("English", lang.Name()); - EXPECT_EQ("en", lang.Locale()); - - lang = Language("en"); - EXPECT_EQ(Language::english, lang.Code()); - EXPECT_EQ("English", lang.Name()); - EXPECT_EQ("en", lang.Locale()); - - // Test code and locale for a couple of other languages, in case English - // is wrongly being used for everything. No point testing all languages, - // because that would just be copying the class code. - lang = Language(Language::polish); - EXPECT_EQ(Language::polish, lang.Code()); - EXPECT_EQ("Polski", lang.Name()); - EXPECT_EQ("pl", lang.Locale()); - - lang = Language("de"); - EXPECT_EQ(Language::german, lang.Code()); - EXPECT_EQ("Deutsch", lang.Name()); - EXPECT_EQ("de", lang.Locale()); - - // Test that invalid values get treated as English. - lang = Language(1000); - EXPECT_EQ(Language::english, lang.Code()); - EXPECT_EQ("English", lang.Name()); - EXPECT_EQ("en", lang.Locale()); - - lang = Language("foo"); - EXPECT_EQ(Language::english, lang.Code()); - EXPECT_EQ("English", lang.Name()); - EXPECT_EQ("en", lang.Locale()); -} - -TEST(Language, Codes) { - // Check that all the expected codes are given. - std::vector codes = { - Language::english, - Language::spanish, - Language::russian, - Language::french, - Language::chinese, - Language::polish, - Language::brazilian_portuguese, - Language::finnish, - Language::german, - Language::danish, - Language::korean - }; - EXPECT_EQ(Language::Codes, codes); -} - -#endif diff --git a/src/tests/backend/helpers/test_yaml_set_helpers.h b/src/tests/backend/helpers/test_yaml_set_helpers.h deleted file mode 100644 index a863c3b0..00000000 --- a/src/tests/backend/helpers/test_yaml_set_helpers.h +++ /dev/null @@ -1,119 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_HELPERS_YAML_SET_HELPERS -#define LOOT_TEST_BACKEND_HELPERS_YAML_SET_HELPERS - -#include "backend/helpers/yaml_set_helpers.h" -#include "tests/fixtures.h" - -TEST(set, YamlEncode) { - YAML::Node node; - std::set stringSet({"a", "b", "c"}); - node = stringSet; - EXPECT_EQ("a", node[0].as()); - EXPECT_EQ("b", node[1].as()); - EXPECT_EQ("c", node[2].as()); -} - -TEST(set, YamlDecode) { - YAML::Node node; - std::set stringSet; - - node = YAML::Load("[a, b, c]"); - stringSet = node.as>(); - EXPECT_EQ(stringSet.begin(), stringSet.find("a")); - EXPECT_EQ(++stringSet.begin(), stringSet.find("b")); - EXPECT_EQ(--stringSet.end(), stringSet.find("c")); - - node = YAML::Load("[a, b, c, c]"); - EXPECT_ANY_THROW(node.as>()); -} - -TEST(set, YamlEmitter) { - std::set stringSet({"a", "b", "c"}); - YAML::Emitter e1; - e1 << stringSet; - EXPECT_STREQ("- a\n- b\n- c", e1.c_str()); -} - -bool nodeContains(const std::string& value, const YAML::Node& node) { - for (const auto& element : node) { - if (element.as() == value) - return true; - } - return false; -} - -TEST(unordered_set, YamlEncode) { - YAML::Node node; - std::unordered_set stringSet({"a", "b", "c"}); - node = stringSet; - // Check that the values are all present in the node. - EXPECT_PRED2(nodeContains, "a", node); - EXPECT_PRED2(nodeContains, "b", node); - EXPECT_PRED2(nodeContains, "c", node); -} - -TEST(unordered_set, YAMLDecode) { - YAML::Node node; - std::unordered_set stringSet; - - node = YAML::Load("[a, b, c]"); - stringSet = node.as>(); - EXPECT_EQ(1, stringSet.count("a")); - EXPECT_EQ(1, stringSet.count("b")); - EXPECT_EQ(1, stringSet.count("c")); - - node = YAML::Load("[a, b, c, c]"); - EXPECT_ANY_THROW(node.as>()); -} - -bool sequenceOf(const char val1, - const char val2, - const char val3, - const std::string& seq) { - if (seq.substr(0, 2) != "- " - || seq.substr(3, 3) != "\n- " - || seq.substr(7, 3) != "\n- ") - return false; - - std::list values({val1, val2, val3}); - std::list found({seq[2], seq[6], seq[10]}); - - values.sort(); - found.sort(); - - return values == found; -} - -TEST(unordered_set, YamlEmitter) { - std::unordered_set stringSet({"a", "b", "c"}); - YAML::Emitter e1; - e1 << stringSet; - ASSERT_EQ(11, e1.size()); - EXPECT_PRED4(sequenceOf, 'a', 'b', 'c', e1.c_str()); -} - -#endif diff --git a/src/tests/backend/helpers/test_version.h b/src/tests/backend/helpers/version_test.h similarity index 99% rename from src/tests/backend/helpers/test_version.h rename to src/tests/backend/helpers/version_test.h index 3e8deeab..6f540899 100644 --- a/src/tests/backend/helpers/test_version.h +++ b/src/tests/backend/helpers/version_test.h @@ -27,14 +27,15 @@ along with LOOT. If not, see #include "backend/globals.h" #include "backend/helpers/version.h" -#include "tests/fixtures.h" + +#include namespace loot { namespace test { #ifdef _WIN32 TEST(Version, shouldExtractVersionFromApiDll) { // Use the API DLL built. - Version version(boost::filesystem::path("loot32.dll")); + Version version(boost::filesystem::path("loot_api.dll")); std::string expected( std::to_string(g_version_major) + "." + std::to_string(g_version_minor) + "." + diff --git a/src/tests/backend/helpers/yaml_set_helpers_test.h b/src/tests/backend/helpers/yaml_set_helpers_test.h new file mode 100644 index 00000000..86361865 --- /dev/null +++ b/src/tests/backend/helpers/yaml_set_helpers_test.h @@ -0,0 +1,138 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_HELPERS_YAML_SET_HELPERS +#define LOOT_TEST_BACKEND_HELPERS_YAML_SET_HELPERS + +#include "backend/helpers/yaml_set_helpers.h" + +#include + +namespace loot { + namespace test { + TEST(set, encodingAsYamlShouldStoreAllValuesInSetOrder) { + std::set stringSet({"a", "b", "c"}); + YAML::Node node; + node = stringSet; + + EXPECT_TRUE(node.IsSequence()); + ASSERT_EQ(3, node.size()); + EXPECT_EQ("a", node[0].as()); + EXPECT_EQ("b", node[1].as()); + EXPECT_EQ("c", node[2].as()); + } + + TEST(set, decodingFromAYamlListShouldStoreValuesCorrectly) { + YAML::Node node = YAML::Load("[a, b, c]"); + std::set stringSet = node.as>(); + std::set expectedStringSet({"a", "b", "c"}); + + EXPECT_EQ(expectedStringSet, stringSet); + } + + TEST(set, decodingFromAYamlListThatContainsDuplicateElementsShouldThrow) { + YAML::Node node = YAML::Load("[a, b, c, c]"); + EXPECT_ANY_THROW(node.as>()); + } + + TEST(set, emittingAsYamlShouldOutputAYamlListContainingAllValues) { + std::set stringSet({"a", "b", "c"}); + YAML::Emitter e1; + e1 << stringSet; + + YAML::Node node = YAML::Load(e1.c_str()); + EXPECT_TRUE(node.IsSequence()); + ASSERT_EQ(3, node.size()); + EXPECT_EQ("a", node[0].as()); + EXPECT_EQ("b", node[1].as()); + EXPECT_EQ("c", node[2].as()); + } + + class unordered_set : public ::testing::Test { + protected: + static bool nodeContains(const YAML::Node& node, const std::string& value) { + for (const auto& element : node) { + if (element.as() == value) + return true; + } + return false; + } + + static bool isSequenceOf(const std::string& sequence, const std::vector& values) { + std::set sortedValues(std::begin(values), std::end(values)); + + std::set found; + size_t i = 2; + while (i < sequence.length()) { + size_t separatorPos = sequence.find("\n- ", i); + found.insert(sequence.substr(i, separatorPos)); + } + + return sortedValues == found; + } + }; + + TEST_F(unordered_set, encodingAsYamlShouldStoreAllValuesInUndefinedOrder) { + std::unordered_set stringSet({"a", "b", "c"}); + YAML::Node node; + node = stringSet; + + EXPECT_TRUE(node.IsSequence()); + ASSERT_EQ(3, node.size()); + EXPECT_PRED2(&nodeContains, node, "a"); + EXPECT_PRED2(&nodeContains, node, "b"); + EXPECT_PRED2(&nodeContains, node, "c"); + } + + TEST_F(unordered_set, decodingFromAYamlListShouldStoreValuesCorrectly) { + YAML::Node node = YAML::Load("[a, b, c]"); + std::unordered_set stringSet = node.as>(); + + EXPECT_EQ(1, stringSet.count("a")); + EXPECT_EQ(1, stringSet.count("b")); + EXPECT_EQ(1, stringSet.count("c")); + } + + TEST_F(unordered_set, decodingFromAYamlListThatContainsDuplicateElementsShouldThrow) { + YAML::Node node = YAML::Load("[a, b, c, c]"); + + EXPECT_ANY_THROW(node.as>()); + } + + TEST_F(unordered_set, emittingAsYamlShouldOutputAYamlListContainingAllValues) { + std::unordered_set stringSet({"a", "b", "c"}); + YAML::Emitter e1; + e1 << stringSet; + + YAML::Node node = YAML::Load(e1.c_str()); + EXPECT_TRUE(node.IsSequence()); + ASSERT_EQ(3, node.size()); + EXPECT_PRED2(&nodeContains, node, "a"); + EXPECT_PRED2(&nodeContains, node, "b"); + EXPECT_PRED2(&nodeContains, node, "c"); + } + } +} + +#endif diff --git a/src/tests/backend/masterlist_test.h b/src/tests/backend/masterlist_test.h new file mode 100644 index 00000000..a663ac51 --- /dev/null +++ b/src/tests/backend/masterlist_test.h @@ -0,0 +1,215 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_MASTERLIST +#define LOOT_TEST_BACKEND_MASTERLIST + +#include "backend/masterlist.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class MasterlistTest : public BaseGameTest { + protected: + MasterlistTest() : + repoBranch("master"), + repoUrl("https://github.com/loot/testing-metadata.git"), + masterlistPath(localPath / "masterlist.yaml") {} + + void SetUp() { + BaseGameTest::SetUp(); + + ASSERT_FALSE(boost::filesystem::exists(masterlistPath)); + ASSERT_FALSE(boost::filesystem::exists(localPath / ".git")); + + ASSERT_NO_THROW(boost::filesystem::create_directories(g_path_local / Game(GetParam()).FolderName())); + } + + void TearDown() { + BaseGameTest::TearDown(); + + ASSERT_NO_THROW(boost::filesystem::remove(masterlistPath)); + ASSERT_NO_THROW(boost::filesystem::remove_all(localPath / ".git")); + + ASSERT_NO_THROW(boost::filesystem::remove(g_path_local / Game(GetParam()).FolderName() / "masterlist.yaml")); + ASSERT_NO_THROW(boost::filesystem::remove_all(g_path_local / Game(GetParam()).FolderName() / ".git")); + } + + const std::string repoUrl; + const std::string repoBranch; + + const boost::filesystem::path masterlistPath; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + MasterlistTest, + ::testing::Values( + GameSettings::tes4, + GameSettings::tes5, + GameSettings::fo3, + GameSettings::fonv, + GameSettings::fo4)); + + TEST_P(MasterlistTest, updateWithGameParameterShouldReturnTrueIfNoMasterlistExists) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + game.SetRepoURL(repoUrl); + game.SetRepoBranch(repoBranch); + ASSERT_NO_THROW(game.Init(false, localPath)); + + // This may fail on Windows if a 'real' LOOT install is also present. + Masterlist masterlist; + EXPECT_TRUE(masterlist.Update(game)); + EXPECT_TRUE(boost::filesystem::exists(game.MasterlistPath())); + } + + TEST_P(MasterlistTest, updateWithGameParameterShouldReturnFalseIfAnUpToDateMasterlistExists) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + game.SetRepoURL(repoUrl); + game.SetRepoBranch(repoBranch); + ASSERT_NO_THROW(game.Init(false, localPath)); + + // This may fail on Windows if a 'real' LOOT install is also present. + Masterlist masterlist; + EXPECT_TRUE(masterlist.Update(game)); + EXPECT_TRUE(boost::filesystem::exists(game.MasterlistPath())); + + EXPECT_FALSE(masterlist.Update(game)); + EXPECT_TRUE(boost::filesystem::exists(game.MasterlistPath())); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldThrowIfAnInvalidPathIsGiven) { + Masterlist masterlist; + + EXPECT_ANY_THROW(masterlist.Update(";//\?", repoUrl, repoBranch)); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldThrowIfABlankPathIsGiven) { + Masterlist masterlist; + + EXPECT_ANY_THROW(masterlist.Update("", repoUrl, repoBranch)); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldThrowIfABranchThatDoesNotExistIsGiven) { + Masterlist masterlist; + + EXPECT_ANY_THROW(masterlist.Update(masterlistPath, + repoUrl, + "missing-branch")); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldThrowIfABlankBranchIsGiven) { + Masterlist masterlist; + + EXPECT_ANY_THROW(masterlist.Update(masterlistPath, repoUrl, "")); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldThrowIfAUrlThatDoesNotExistIsGiven) { + Masterlist masterlist; + + EXPECT_ANY_THROW(masterlist.Update(masterlistPath, + "https://github.com/loot/does-not-exist.git", + repoBranch)); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldThrowIfABlankUrlIsGiven) { + Masterlist masterlist; + EXPECT_ANY_THROW(masterlist.Update(masterlistPath, "", repoBranch)); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldReturnTrueIfNoMasterlistExists) { + Masterlist masterlist; + EXPECT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + } + + TEST_P(MasterlistTest, updateWithSeparateParametersShouldReturnFalseIfAnUpToDateMasterlistExists) { + Masterlist masterlist; + + EXPECT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + + EXPECT_FALSE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + } + + TEST_P(MasterlistTest, getInfoShouldThrowIfNoMasterlistExistsAtTheGivenPath) { + Masterlist masterlist; + EXPECT_ANY_THROW(masterlist.GetInfo(masterlistPath, false)); + } + + TEST_P(MasterlistTest, getInfoShouldThrowIfTheGivenPathDoesNotBelongToAGitRepository) { + ASSERT_NO_THROW(boost::filesystem::copy("./testing-metadata/masterlist.yaml", masterlistPath)); + + Masterlist masterlist; + EXPECT_ANY_THROW(masterlist.GetInfo(masterlistPath, false)); + } + + TEST_P(MasterlistTest, getInfoShouldReturnRevisionAndDateStringsOfTheCorrectLengthsWhenRequestingALongId) { + Masterlist masterlist; + ASSERT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + + Masterlist::Info info = masterlist.GetInfo(masterlistPath, false); + EXPECT_EQ(40, info.revision.length()); + EXPECT_EQ(10, info.date.length()); + } + + TEST_P(MasterlistTest, getInfoShouldReturnRevisionAndDateStringsOfTheCorrectLengthsWhenRequestingAShortId) { + Masterlist masterlist; + ASSERT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + + Masterlist::Info info = masterlist.GetInfo(masterlistPath, true); + EXPECT_GE((unsigned)40, info.revision.length()); + EXPECT_LE((unsigned)7, info.revision.length()); + EXPECT_EQ(10, info.date.length()); + } + + TEST_P(MasterlistTest, getInfoShouldAppendSuffixesToReturnedStringsIfTheMasterlistHasBeenEdited) { + Masterlist masterlist; + ASSERT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + boost::filesystem::ofstream out(masterlistPath); + out.close(); + + Masterlist::Info info = masterlist.GetInfo(masterlistPath, false); + EXPECT_EQ(49, info.revision.length()); + EXPECT_EQ(" (edited)", info.revision.substr(40)); + EXPECT_EQ(19, info.date.length()); + EXPECT_EQ(" (edited)", info.date.substr(10)); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/condition_grammar_test.h b/src/tests/backend/metadata/condition_grammar_test.h new file mode 100644 index 00000000..c2ae7398 --- /dev/null +++ b/src/tests/backend/metadata/condition_grammar_test.h @@ -0,0 +1,585 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_CONDITION_GRAMMAR +#define LOOT_TEST_BACKEND_METADATA_CONDITION_GRAMMAR + +#include "backend/error.h" +#include "backend/metadata/condition_grammar.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class ConditionGrammarTest : public BaseGameTest { + protected: + ConditionGrammarTest() : + resourcePath(dataPath / "resource" / "detail" / "resource.txt"), + game(Game(GetParam()).SetGamePath(dataPath.parent_path())), + result(false), + success(false) {} + + inline void SetUp() { + BaseGameTest::SetUp(); + + // Write out an empty resource file. + ASSERT_NO_THROW(boost::filesystem::create_directories(resourcePath.parent_path())); + boost::filesystem::ofstream out(resourcePath); + out.close(); + ASSERT_TRUE(boost::filesystem::exists(resourcePath)); + } + + inline void TearDown() { + BaseGameTest::TearDown(); + + ASSERT_NO_THROW(boost::filesystem::remove(resourcePath)); + } + + typedef ConditionGrammar Grammar; + + const boost::filesystem::path resourcePath; + + Game game; + boost::spirit::qi::space_type skipper; + bool result; + bool success; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + ConditionGrammarTest, + ::testing::Values( + GameSettings::tes4, + GameSettings::tes5, + GameSettings::fo3, + GameSettings::fonv, + GameSettings::fo4)); + + TEST_P(ConditionGrammarTest, parsingInvalidSyntaxShouldThrow) { + Grammar grammar(nullptr); + std::string condition("file(foo)"); + + EXPECT_THROW(boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result), error); + } + + TEST_P(ConditionGrammarTest, evaluatingInvalidSyntaxShouldThrow) { + Grammar grammar(&game); + std::string condition("file(foo)"); + + EXPECT_THROW(boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result), error); + } + + TEST_P(ConditionGrammarTest, parsingAnEmptyConditionShouldThrow) { + Grammar grammar(nullptr); + std::string condition(""); + + EXPECT_THROW(boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result), error); + } + + TEST_P(ConditionGrammarTest, evaluatingAnEmptyConditionShouldThrow) { + Grammar grammar(&game); + std::string condition(""); + + EXPECT_THROW(boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result), error); + } + + TEST_P(ConditionGrammarTest, aFileConditionWithAPluginThatExistsShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("file(\"" + blankEsm + "\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aFileConditionWithAPluginThatDoesNotExistShouldEvaluateToFalse) { + Grammar grammar(&game); + std::string condition("file(\"" + missingEsp + "\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, evaluatingAFileConditionForAnUnsafePathShouldThrow) { + Grammar grammar(&game); + std::string condition("file(\"../../" + blankEsm + "\")"); + + EXPECT_THROW(boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result), error); + } + + TEST_P(ConditionGrammarTest, aRegexConditionWithAnInvalidRegexShouldThrow) { + Grammar grammar(&game); + std::string condition("regex(\"RagnvaldBook(Farengar(+Ragnvald)?)?\\.esp\")"); + + EXPECT_THROW(boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result), error); + } + + TEST_P(ConditionGrammarTest, aRegexConditionWithARegexMatchingAPluginThatExistsShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("regex(\"Blank.+\\.esm\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aRegexConditionWithARegexMatchingAPluginThatDoesNotExistShouldEvaluateToFalse) { + Grammar grammar(&game); + std::string condition("regex(\"Blank\\.m.+\\.esm\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aRegexConditionWithARegexMatchingAFileInASubfolderThatExistsShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("regex(\"resource\\\\detail\\\\resource\\.txt\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aManyConditionWithARegexMatchingMoreThanOnePluginShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("many(\"Blank.+\\.esm\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aManyConditionWithARegexMatchingOnlyOnePluginShouldEvaluateToFalse) { + Grammar grammar(&game); + std::string condition("many(\"Blank\\.esm\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aChecksumConditionWithACrcThatMatchesTheActualPluginCrcShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("checksum(\"" + blankEsm + "\", " + IntToHexString(blankEsmCrc) + ")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aChecksumConditionWithACrcThatDoesNotMatchTheActualPluginCrcShouldEvaluateToFalse) { + Grammar grammar(&game); + std::string condition("checksum(\"" + blankEsm + "\", DEADBEEF)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aVersionEqualityConditionWithAVersionThatEqualsTheActualPluginVersionShouldEvaluateToTrue) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"5.0\", ==)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aVersionEqualityConditionWithAVersionThatDoesNotEqualTheActualPluginVersionShouldEvaluateToFalse) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"6.0\", ==)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aVersionInequalityConditionWithAVersionThatDoesNotEqualTheActualPluginVersionShouldEvaluateToTrue) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"6.0\", !=)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aVersionInequalityConditionWithAVersionThatEqualsTheActualPluginVersionShouldEvaluateToFalse) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"5.0\", !=)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aVersionLessThanConditionWithAnActualPluginVersionLessThanTheGivenVersionShouldEvaluateToTrue) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"6.0\", <)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aVersionLessThanConditionWithAnActualPluginVersionEqualToTheGivenVersionShouldEvaluateToFalse) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"5.0\", <)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aVersionGreaterThanConditionWithAnActualPluginVersionGreaterThanTheGivenVersionShouldEvaluateToTrue) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"4.0\", >)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aVersionGreaterThanConditionWithAnActualPluginVersionEqualToTheGivenVersionShouldEvaluateToFalse) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"5.0\", >)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aVersionLessThanOrEqualToConditionWithAnActualPluginVersionEqualToTheGivenVersionShouldEvaluateToTrue) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"5.0\", <=)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aVersionLessThanOrEqualToConditionWithAnActualPluginVersionGreaterThanTheGivenVersionShouldEvaluateToFalse) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"4.0\", <=)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aVersionGreaterThanOrEqualToConditionWithAnActualPluginVersionEqualToTheGivenVersionShouldEvaluateToTrue) { + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"5.0\", >=)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aVersionGreaterThanOrEqualToConditionWithAnActualPluginVersionLessThanTheGivenVersionShouldEvaluateToFalse) { + ASSERT_NO_THROW(game.LoadPlugins(true)); + + Grammar grammar(&game); + std::string condition("version(\"" + blankEsm + "\", \"6.0\", >=)"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, anActiveConditionWithAPluginThatIsActiveShouldEvaluateToTrue) { + ASSERT_NO_THROW(game.Init(false, localPath)); + + Grammar grammar(&game); + std::string condition("active(\"" + blankEsm + "\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, anActiveConditionWithAPluginThatIsNotActiveShouldEvaluateToFalse) { + ASSERT_NO_THROW(game.Init(false, localPath)); + + Grammar grammar(&game); + std::string condition("active(\"" + blankEsp + "\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aFalseConditionPrecededByANegatorShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("not file(\"" + missingEsp + "\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aTrueConditionPrecededByANegatorShouldEvaluateToFalse) { + Grammar grammar(&game); + std::string condition("not file(\"" + blankEsm + "\")"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(condition), + std::cend(condition), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, twoTrueConditionsJoinedByAnAndShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("file(\"" + blankEsm + "\")"); + std::string compound(condition + " and " + condition); + + success = boost::spirit::qi::phrase_parse(std::cbegin(compound), + std::cend(compound), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, aTrueAndAFalseConditionJoinedByAnAndShouldEvaluateToFalse) { + Grammar grammar(&game); + std::string condition("file(\"" + blankEsm + "\")"); + std::string compound(condition + " and not " + condition); + + success = boost::spirit::qi::phrase_parse(std::cbegin(compound), + std::cend(compound), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, aFalseAndATrueConditionJoinedByAnOrShouldEvaluateToTrue) { + Grammar grammar(&game); + std::string condition("file(\"" + blankEsm + "\")"); + std::string compound("not " + condition + " or " + condition); + + success = boost::spirit::qi::phrase_parse(std::cbegin(compound), + std::cend(compound), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, twoFalseConditionsJoinedByAnOrShouldEvaluateToFalse) { + Grammar grammar(&game); + std::string condition("file(\"" + blankEsm + "\")"); + std::string compound("not " + condition + " or not " + condition); + + success = boost::spirit::qi::phrase_parse(std::cbegin(compound), + std::cend(compound), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + + TEST_P(ConditionGrammarTest, andOperatorsShouldTakePrecedenceOverOrOperators) { + Grammar grammar(&game); + std::string condition("file(\"" + blankEsm + "\")"); + std::string compound("not " + condition + " and " + condition + " or " + condition); + + success = boost::spirit::qi::phrase_parse(std::cbegin(compound), + std::cend(compound), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_TRUE(result); + } + + TEST_P(ConditionGrammarTest, parenthesesShouldTakePrecedenceOverAndOperators) { + Grammar grammar(&game); + std::string condition("file(\"" + blankEsm + "\")"); + std::string compound("not " + condition + " and ( " + condition + " or " + condition + " )"); + + success = boost::spirit::qi::phrase_parse(std::cbegin(compound), + std::cend(compound), + grammar, + skipper, + result); + EXPECT_TRUE(success); + EXPECT_FALSE(result); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/conditional_metadata_test.h b/src/tests/backend/metadata/conditional_metadata_test.h new file mode 100644 index 00000000..d718934c --- /dev/null +++ b/src/tests/backend/metadata/conditional_metadata_test.h @@ -0,0 +1,122 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_CONDITIONAL_METADATA +#define LOOT_TEST_BACKEND_METADATA_CONDITIONAL_METADATA + +#include "backend/error.h" +#include "backend/metadata/conditional_metadata.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class ConditionalMetadataTest : public BaseGameTest { + protected: + ConditionalMetadata conditionalMetadata; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + ConditionalMetadataTest, + ::testing::Values( + GameSettings::tes4, + GameSettings::tes5, + GameSettings::fo3, + GameSettings::fonv, + GameSettings::fo4)); + + TEST_P(ConditionalMetadataTest, defaultConstructorShouldSetEmptyConditionString) { + EXPECT_TRUE(conditionalMetadata.Condition().empty()); + } + + TEST_P(ConditionalMetadataTest, stringConstructorShouldSetConditionToGivenString) { + std::string condition("condition"); + conditionalMetadata = ConditionalMetadata(condition); + + EXPECT_EQ(condition, conditionalMetadata.Condition()); + } + + TEST_P(ConditionalMetadataTest, isConditionalShouldBeFalseForAnEmptyConditionString) { + EXPECT_FALSE(conditionalMetadata.IsConditional()); + } + + TEST_P(ConditionalMetadataTest, isConditionalShouldBeTrueForANonEmptyConditionString) { + conditionalMetadata = ConditionalMetadata("condition"); + EXPECT_TRUE(conditionalMetadata.IsConditional()); + } + + TEST_P(ConditionalMetadataTest, evalConditionShouldReturnTrueForAnEmptyCondition) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_TRUE(conditionalMetadata.EvalCondition(game)); + } + + TEST_P(ConditionalMetadataTest, evalConditionShouldThrowForAnInvalidCondition) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + conditionalMetadata = ConditionalMetadata("condition"); + EXPECT_THROW(conditionalMetadata.EvalCondition(game), error); + } + + TEST_P(ConditionalMetadataTest, evalConditionShouldReturnTrueForAConditionThatIsTrue) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + conditionalMetadata = ConditionalMetadata("file(\"" + blankEsm + "\")"); + EXPECT_TRUE(conditionalMetadata.EvalCondition(game)); + } + + TEST_P(ConditionalMetadataTest, evalConditionShouldReturnFalseForAConditionThatIsFalse) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + conditionalMetadata = ConditionalMetadata("file(\"" + missingEsp + "\")"); + EXPECT_FALSE(conditionalMetadata.EvalCondition(game)); + } + + TEST_P(ConditionalMetadataTest, parseConditionShouldNotThrowForAnEmptyCondition) { + EXPECT_NO_THROW(conditionalMetadata.ParseCondition()); + } + + TEST_P(ConditionalMetadataTest, parseConditionShouldThrowForAnInvalidCondition) { + conditionalMetadata = ConditionalMetadata("condition"); + EXPECT_THROW(conditionalMetadata.ParseCondition(), error); + } + + TEST_P(ConditionalMetadataTest, parseConditionShouldNotThrowForATrueCondition) { + conditionalMetadata = ConditionalMetadata("file(\"" + blankEsm + "\")"); + EXPECT_NO_THROW(conditionalMetadata.ParseCondition()); + } + + TEST_P(ConditionalMetadataTest, parseConditionShouldNotThrowForAFalseCondition) { + conditionalMetadata = ConditionalMetadata("file(\"" + missingEsp + "\")"); + EXPECT_NO_THROW(conditionalMetadata.ParseCondition()); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/file_test.h b/src/tests/backend/metadata/file_test.h new file mode 100644 index 00000000..0b54013e --- /dev/null +++ b/src/tests/backend/metadata/file_test.h @@ -0,0 +1,186 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_FILE +#define LOOT_TEST_BACKEND_METADATA_FILE + +#include "backend/metadata/file.h" + +#include + +namespace loot { + namespace test { + TEST(File, defaultConstructorShouldInitialiseEmptyStrings) { + File file; + + EXPECT_EQ("", file.Name()); + EXPECT_EQ("", file.DisplayName()); + EXPECT_EQ("", file.Condition()); + } + + TEST(File, stringsConstructorShouldStoreGivenStrings) { + File file("name", "display", "condition"); + + EXPECT_EQ("name", file.Name()); + EXPECT_EQ("display", file.DisplayName()); + EXPECT_EQ("condition", file.Condition()); + } + + TEST(File, filesWithCaseInsensitiveEqualNameStringsShouldBeEqual) { + File file1("name", "display1", "condition1"); + File file2("Name", "display2", "condition2"); + + EXPECT_TRUE(file1 == file2); + } + + TEST(File, filesWithDifferentNamesShouldBeUnequal) { + File file1("name1"); + File file2("name2"); + + EXPECT_FALSE(file1 == file2); + } + + TEST(File, lessThanOperatorShouldUseCaseInsensitiveLexicographicalNameComparison) { + File file1("name", "display1", "condition1"); + File file2("Name", "display2", "condition2"); + + EXPECT_FALSE(file1 < file2); + EXPECT_FALSE(file2 < file1); + + file1 = File("name1"); + file2 = File("name2"); + + EXPECT_TRUE(file1 < file2); + EXPECT_FALSE(file2 < file1); + } + + TEST(File, emittingAsYamlShouldSingleQuoteValues) { + File file("name1", "display1", "condition1"); + YAML::Emitter emitter; + emitter << file; + std::string expected = "name: '" + file.Name() + + "'\ncondition: '" + file.Condition() + + "'\ndisplay: '" + file.DisplayName() + "'"; + + EXPECT_EQ(expected, emitter.c_str()); + } + + TEST(File, emittingAsYamlShouldOutputAsAScalarIfOnlyTheNameStringIsNotEmpty) { + File file("name1"); + YAML::Emitter emitter; + emitter << file; + + EXPECT_EQ("'" + file.Name() + "'", emitter.c_str()); + } + + TEST(File, emittingAsYamlShouldOmitDisplayFieldIfItMatchesTheNameField) { + File file("name1", "name1"); + YAML::Emitter emitter; + emitter << file; + + EXPECT_EQ("'" + file.Name() + "'", emitter.c_str()); + } + + TEST(File, emittingAsYamlShouldOmitAnEmptyConditionString) { + File file("name1", "display1"); + YAML::Emitter emitter; + emitter << file; + std::string expected = "name: '" + file.Name() + + "'\ndisplay: '" + file.DisplayName() + "'"; + + EXPECT_EQ(expected, emitter.c_str()); + } + + TEST(File, encodingAsYamlShouldStoreDataCorrectly) { + File file("name1", "display1", "condition1"); + YAML::Node node; + node = file; + + EXPECT_EQ(file.Name(), node["name"].as()); + EXPECT_EQ(file.DisplayName(), node["display"].as()); + EXPECT_EQ(file.Condition(), node["condition"].as()); + } + + TEST(File, encodingAsYamlShouldOmitEmptyFields) { + File file("name1"); + YAML::Node node; + node = file; + + EXPECT_EQ(file.Name(), node["name"].as()); + EXPECT_FALSE(node["display"]); + EXPECT_FALSE(node["condition"]); + } + + TEST(File, encodingAsYamlShouldOmitDisplayFieldIfItMatchesTheNameField) { + File file("name1", "name1"); + YAML::Node node; + node = file; + + EXPECT_EQ(file.Name(), node["name"].as()); + EXPECT_FALSE(node["display"]); + EXPECT_FALSE(node["condition"]); + } + + TEST(File, decodingFromYamlShouldSetDataCorrectly) { + YAML::Node node = YAML::Load("{name: name1, display: display1, condition: 'file(\"Foo.esp\")'}"); + File file = node.as(); + + EXPECT_EQ(node["name"].as(), file.Name()); + EXPECT_EQ(node["display"].as(), file.DisplayName()); + EXPECT_EQ(node["condition"].as(), file.Condition()); + } + + TEST(File, decodingFromYamlWithMissingConditionFieldShouldLeaveConditionStringEmpty) { + YAML::Node node = YAML::Load("{name: name1, display: display1}"); + File file = node.as(); + + EXPECT_EQ(node["name"].as(), file.Name()); + EXPECT_EQ(node["display"].as(), file.DisplayName()); + EXPECT_TRUE(file.Condition().empty()); + } + + TEST(File, decodingFromYamlScalarShouldUseNameValueForDisplayNameAndLeaveConditionEmpty) { + YAML::Node node = YAML::Load("name1"); + File file = node.as(); + + EXPECT_EQ(node.as(), file.Name()); + EXPECT_EQ(node.as(), file.DisplayName()); + EXPECT_TRUE(file.Condition().empty()); + } + + TEST(File, decodingFromYamlShouldThrowIfAnInvalidMapIsGiven) { + YAML::Node node = YAML::Load("{name: name1, condition: invalid}"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST(File, decodingFromYamlShouldThrowIfAListIsGiven) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_ANY_THROW(node.as()); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/location_test.h b/src/tests/backend/metadata/location_test.h new file mode 100644 index 00000000..7fc6d6e9 --- /dev/null +++ b/src/tests/backend/metadata/location_test.h @@ -0,0 +1,134 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_LOCATION +#define LOOT_TEST_BACKEND_METADATA_LOCATION + +#include "backend/metadata/location.h" + +#include + +namespace loot { + namespace test { + TEST(Location, defaultConstructorShouldInitialiseEmptyStrings) { + Location location; + + EXPECT_EQ("", location.URL()); + EXPECT_EQ("", location.Name()); + } + + TEST(Location, stringsConstructorShouldStoreGivenStrings) { + Location location("http://www.example.com", "example"); + + EXPECT_EQ("http://www.example.com", location.URL()); + EXPECT_EQ("example", location.Name()); + } + + TEST(Location, locationsWithCaseInsensitiveEqualUrlsShouldBeEqual) { + Location location1("http://www.example.com", "example1"); + Location location2("HTTP://WWW.EXAMPLE.COM", "example2"); + + EXPECT_TRUE(location1 == location2); + } + + TEST(Location, locationsWithDifferentUrlsShouldBeUnequal) { + Location location1("http://www.example1.com"); + Location location2("http://www.example2.com"); + + EXPECT_FALSE(location1 == location2); + } + + TEST(Location, lessThanOperatorShouldUseCaseInsensitiveLexicographicalUrlComparison) { + Location location1("http://www.example.com", "example1"); + Location location2("HTTP://WWW.EXAMPLE.COM", "example2"); + + EXPECT_FALSE(location1 < location2); + EXPECT_FALSE(location2 < location1); + + location1 = Location("http://www.example1.com"); + location2 = Location("http://www.example2.com"); + + EXPECT_TRUE(location1 < location2); + EXPECT_FALSE(location2 < location1); + } + + TEST(Location, emittingAsYamlShouldOutputAScalarIfTheNameStringIsEmpty) { + Location location("http://www.example.com"); + YAML::Emitter emitter; + emitter << location; + + EXPECT_EQ("'" + location.URL() + "'", emitter.c_str()); + } + + TEST(Location, emittingAsYamlShouldOutputAMapIfTheNameStringIsNotEmpty) { + Location location("http://www.example.com", "example"); + YAML::Emitter emitter; + emitter << location; + + EXPECT_EQ("link: '" + location.URL() + "'\nname: '" + location.Name() + "'", emitter.c_str()); + } + + TEST(Location, encodingAsYamlShouldStoreDataCorrectly) { + Location location("http://www.example.com", "example"); + YAML::Node node; + node = location; + + EXPECT_EQ(location.URL(), node["link"].as()); + EXPECT_EQ(location.Name(), node["name"].as()); + } + + TEST(Location, encodingAsYamlShouldOmitEmptyFields) { + Location location("http://www.example.com"); + YAML::Node node; + node = location; + + EXPECT_EQ(location.URL(), node["link"].as()); + EXPECT_FALSE(node["name"]); + } + + TEST(Location, decodingFromYamlShouldSetDataCorrectly) { + YAML::Node node = YAML::Load("{link: http://www.example.com, name: example}"); + Location location = node.as(); + + EXPECT_EQ(node["link"].as(), location.URL()); + EXPECT_EQ(node["name"].as(), location.Name()); + } + + TEST(Location, decodingFromYamlScalarShouldSetUrlToScalarValueAndLeaveNameEmpty) { + YAML::Node node = YAML::Load("http://www.example.com"); + Location location = node.as(); + + EXPECT_EQ(node.as(), location.URL()); + EXPECT_TRUE(location.Name().empty()); + } + + TEST(Location, decodingFromYamlShouldThrowIfAListIsGiven) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_ANY_THROW(node.as()); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/message_content_test.h b/src/tests/backend/metadata/message_content_test.h new file mode 100644 index 00000000..3b6bc4fc --- /dev/null +++ b/src/tests/backend/metadata/message_content_test.h @@ -0,0 +1,116 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_MESSAGE_CONTENT +#define LOOT_TEST_BACKEND_METADATA_MESSAGE_CONTENT + +#include "backend/metadata/message_content.h" + +#include + +namespace loot { + namespace test { + TEST(MessageContent, defaultConstructorShouldSetEmptyEnglishLanguageString) { + MessageContent content; + + EXPECT_TRUE(content.Str().empty()); + EXPECT_EQ(Language::english, content.Language()); + } + + TEST(MessageContent, contentConstructorShouldStoreGivenStringAndLanguage) { + MessageContent content("content", Language::french); + + EXPECT_EQ("content", content.Str()); + EXPECT_EQ(Language::french, content.Language()); + } + + TEST(MessageContent, contentShouldBeEqualIfStringsAreCaseInsensitivelyEqual) { + MessageContent content1("content", Language::english); + MessageContent content2("Content", Language::french); + + EXPECT_TRUE(content1 == content2); + } + + TEST(MessageContent, contentShouldBeUnequalIfStringsAreNotCaseInsensitivelyEqual) { + MessageContent content1("content1", Language::french); + MessageContent content2("content2", Language::french); + + EXPECT_FALSE(content1 == content2); + } + + TEST(MessageContent, LessThanOperatorShouldUseCaseInsensitiveLexicographicalComparison) { + MessageContent content1("content", Language::english); + MessageContent content2("Content", Language::french); + + EXPECT_FALSE(content1 < content2); + EXPECT_FALSE(content2 < content1); + + content1 = MessageContent("content1", Language::french); + content2 = MessageContent("content2", Language::english); + + EXPECT_TRUE(content1 < content2); + EXPECT_FALSE(content2 < content1); + } + + TEST(MessageContent, emittingAsYamlShouldOutputDataCorrectly) { + MessageContent content("content", Language::french); + YAML::Emitter emitter; + emitter << content; + + EXPECT_EQ("lang: " + Language(content.Language()).Locale() + + "\nstr: '" + content.Str() + "'", emitter.c_str()); + } + + TEST(MessageContent, encodingAsYamlShouldOutputDataCorrectly) { + MessageContent content("content", Language::french); + YAML::Node node; + node = content; + + EXPECT_EQ(content.Str(), node["str"].as()); + EXPECT_EQ(Language(Language::french).Locale(), node["lang"].as()); + } + + TEST(MessageContent, decodingFromYamlShouldSetDataCorrectly) { + YAML::Node node = YAML::Load("{str: content, lang: de}"); + MessageContent content = node.as(); + + EXPECT_EQ("content", content.Str()); + EXPECT_EQ(Language::german, content.Language()); + } + + TEST(MessageContent, decodingFromYamlScalarShouldThrow) { + YAML::Node node = YAML::Load("scalar"); + + EXPECT_ANY_THROW(node.as()); + } + + TEST(MessageContent, decodingFromYamlListShouldThrow) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_ANY_THROW(node.as()); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/message_test.h b/src/tests/backend/metadata/message_test.h new file mode 100644 index 00000000..1c6e2c3a --- /dev/null +++ b/src/tests/backend/metadata/message_test.h @@ -0,0 +1,439 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_MESSAGE +#define LOOT_TEST_BACKEND_METADATA_MESSAGE + +#include "backend/game/game.h" +#include "backend/metadata/message.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class MessageTest : public BaseGameTest { + protected: + + typedef std::vector MessageContents; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + MessageTest, + ::testing::Values( + GameSettings::tes4)); + + TEST_P(MessageTest, defaultConstructorShouldCreateNoteWithNoContent) { + Message message; + EXPECT_EQ(Message::say, message.Type()); + EXPECT_EQ(MessageContents(), message.Content()); + } + + TEST_P(MessageTest, scalarContentConstructorShouldCreateAMessageWithASingleContentString) { + MessageContent content = MessageContent("content1", Language::english); + Message message(Message::warn, content.Str(), "condition1"); + + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ(MessageContents({content}), message.Content()); + EXPECT_EQ("condition1", message.Condition()); + } + + TEST_P(MessageTest, vectorContentConstructorShouldCreateAMessageWithGivenContentStrings) { + MessageContents contents({ + MessageContent("content1", Language::english), + MessageContent("content2", Language::french), + }); + Message message(Message::error, contents, "condition1"); + + EXPECT_EQ(Message::error, message.Type()); + EXPECT_EQ(contents, message.Content()); + EXPECT_EQ("condition1", message.Condition()); + } + + TEST_P(MessageTest, vectorContentConstructorShouldThrowIfMultipleContentStringsAreGivenAndNoneAreEnglish) { + MessageContents contents({ + MessageContent("content1", Language::german), + MessageContent("content2", Language::french), + }); + EXPECT_ANY_THROW(Message(Message::error, contents, "condition1")); + } + + TEST_P(MessageTest, messagesWithDifferentContentStringsShouldBeUnequal) { + Message message1(Message::say, "content1", "condition1"); + Message message2(Message::say, "content2", "condition1"); + + EXPECT_FALSE(message1 == message2); + } + + TEST_P(MessageTest, messagesWithEqualContentStringsShouldBeEqual) { + Message message1(Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); + Message message2(Message::warn, MessageContents({MessageContent("content1", Language::french)}), "condition2"); + + EXPECT_TRUE(message1 == message2); + } + + TEST_P(MessageTest, LessThanOperatorShouldUseCaseInsensitiveLexicographicalContentStringComparison) { + Message message1(Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); + Message message2(Message::warn, MessageContents({MessageContent("content1", Language::french)}), "condition2"); + EXPECT_FALSE(message1 < message2); + EXPECT_FALSE(message2 < message1); + + message1 = Message(Message::say, "content1", "condition1"); + message2 = Message(Message::say, "content2", "condition1"); + EXPECT_TRUE(message1 < message2); + EXPECT_FALSE(message2 < message1); + } + + TEST_P(MessageTest, evalConditionShouldCreateADefaultContentObjectIfNoneExists) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + + Message message; + EXPECT_TRUE(message.EvalCondition(game, Language::english)); + EXPECT_EQ(MessageContents({MessageContent()}), message.Content()); + } + + TEST_P(MessageTest, evalConditionShouldPickOneContentStringIfMoreThanOneExists) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + + Message message(Message::say, MessageContents({ + MessageContent("content1", Language::german), + MessageContent("content2", Language::english), + MessageContent("content3", Language::french), + })); + + EXPECT_TRUE(message.EvalCondition(game, Language::french)); + EXPECT_EQ(1, message.Content().size()); + EXPECT_EQ(MessageContent("content3", Language::french), message.Content()[0]); + } + + TEST_P(MessageTest, chooseContentShouldCreateADefaultContentObjectIfNoneExists) { + EXPECT_EQ(MessageContent(), Message().ChooseContent(Language::english)); + } + + TEST_P(MessageTest, chooseContentShouldLeaveTheContentUnchangedIfOnlyOneStringExists) { + MessageContent content("content1", Language::english); + Message message(Message::say, MessageContents({content})); + + EXPECT_EQ(content, message.ChooseContent(Language::french)); + EXPECT_EQ(content, message.ChooseContent(Language::english)); + } + + TEST_P(MessageTest, chooseContentShouldSelectTheEnglishStringIfNoStringExistsForTheGivenLanguage) { + MessageContent content("content1", Language::english); + Message message(Message::say, MessageContents({ + content, + MessageContent("content1", Language::german), + })); + EXPECT_EQ(content, message.ChooseContent(Language::french)); + } + + TEST_P(MessageTest, chooseContentShouldSelectTheStringForTheGivenLanguageIfOneExists) { + MessageContent french("content3", Language::french); + Message message(Message::say, MessageContents({ + MessageContent("content1", Language::german), + MessageContent("content2", Language::english), + french, + })); + + EXPECT_EQ(french, message.ChooseContent(Language::french)); + } + + TEST_P(MessageTest, emittingAsYamlShouldOutputNoteMessageTypeCorrectly) { + Message message(Message::say, "content1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ("type: say\n" + "content: 'content1'", emitter.c_str()); + } + + TEST_P(MessageTest, emittingAsYamlShouldOutputWarnMessageTypeCorrectly) { + Message message(Message::warn, "content1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ("type: warn\n" + "content: 'content1'", emitter.c_str()); + } + + TEST_P(MessageTest, emittingAsYamlShouldOutputErrorMessageTypeCorrectly) { + Message message(Message::error, "content1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ("type: error\n" + "content: 'content1'", emitter.c_str()); + } + + TEST_P(MessageTest, emittingAsYamlShouldOutputConditionIfItIsNotEmpty) { + Message message(Message::say, "content1", "condition1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ("type: say\n" + "content: 'content1'\n" + "condition: 'condition1'", emitter.c_str()); + } + + TEST_P(MessageTest, emittingAsYamlShouldOutputMultipleContentStringsAsAList) { + Message message(Message::say, MessageContents({ + MessageContent("content1", Language::english), + MessageContent("content2", Language::german) + })); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ("type: say\n" + "content:\n" + " - lang: en\n" + " str: 'content1'\n" + " - lang: de\n" + " str: 'content2'", emitter.c_str()); + } + + TEST_P(MessageTest, encodingAsYamlShouldStoreNoteMessageTypeCorrectly) { + Message message(Message::say, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ("say", node["type"].as()); + } + + TEST_P(MessageTest, encodingAsYamlShouldStoreWarningMessageTypeCorrectly) { + Message message(Message::warn, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ("warn", node["type"].as()); + } + + TEST_P(MessageTest, encodingAsYamlShouldStoreErrorMessageTypeCorrectly) { + Message message(Message::error, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ("error", node["type"].as()); + } + + TEST_P(MessageTest, encodingAsYamlShouldOmitConditionFieldIfItIsEmpty) { + Message message(Message::say, "content1"); + YAML::Node node; + node = message; + + EXPECT_FALSE(node["condition"]); + } + + TEST_P(MessageTest, encodingAsYamlShouldStoreConditionFieldIfItIsNotEmpty) { + Message message(Message::say, "content1", "condition1"); + YAML::Node node; + node = message; + + EXPECT_EQ("condition1", node["condition"].as()); + } + + TEST_P(MessageTest, encodingAsYamlShouldStoreASingleContentStringInAVector) { + Message message(Message::say, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ(message.Content(), node["content"].as()); + } + + TEST_P(MessageTest, encodingAsYamlShouldMultipleContentStringsInAVector) { + MessageContents contents({ + MessageContent("content1", Language::english), + MessageContent("content2", Language::french), + }); + Message message(Message::say, contents); + YAML::Node node; + node = message; + + EXPECT_EQ(contents, node["content"].as()); + } + + TEST_P(MessageTest, decodingFromYamlShouldSetNoteTypeCorrectly) { + YAML::Node node = YAML::Load("type: say\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(Message::say, message.Type()); + } + + TEST_P(MessageTest, decodingFromYamlShouldSetWarningTypeCorrectly) { + YAML::Node node = YAML::Load("type: warn\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(Message::warn, message.Type()); + } + + TEST_P(MessageTest, decodingFromYamlShouldSetErrorTypeCorrectly) { + YAML::Node node = YAML::Load("type: error\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(Message::error, message.Type()); + } + + TEST_P(MessageTest, decodingFromYamlShouldHandleAnUnrecognisedTypeAsANote) { + YAML::Node node = YAML::Load("type: invalid\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(Message::say, message.Type()); + } + + TEST_P(MessageTest, decodingFromYamlShouldLeaveTheConditionEmptyIfNoneIsPresent) { + YAML::Node node = YAML::Load("type: say\n" + "content: content1"); + Message message = node.as(); + + EXPECT_TRUE(message.Condition().empty()); + } + + TEST_P(MessageTest, decodingFromYamlShouldStoreANonEmptyConditionField) { + YAML::Node node = YAML::Load("type: say\n" + "content: content1\n" + "condition: 'file(\"Foo.esp\")'"); + Message message = node.as(); + + EXPECT_EQ("file(\"Foo.esp\")", message.Condition()); + } + + TEST_P(MessageTest, decodingFromYamlShouldStoreAScalarContentValueCorrectly) { + YAML::Node node = YAML::Load("type: say\n" + "content: content1\n"); + Message message = node.as(); + MessageContents expectedContent({MessageContent("content1", Language::english)}); + + EXPECT_EQ(expectedContent, message.Content()); + } + + TEST_P(MessageTest, decodingFromYamlShouldStoreAListOfContentStringsCorrectly) { + YAML::Node node = YAML::Load("type: say\n" + "content:\n" + " - lang: en\n" + " str: content1\n" + " - lang: de\n" + " str: content2"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({ + MessageContent("content1", Language::english), + MessageContent("content2", Language::german), + }), message.Content()); + } + + TEST_P(MessageTest, decodingFromYamlShouldNotThrowIfTheOnlyContentStringIsNotEnglish) { + YAML::Node node = YAML::Load("type: say\n" + "content:\n" + " - lang: fr\n" + " str: content1"); + + EXPECT_NO_THROW(Message message = node.as()); + } + + TEST_P(MessageTest, decodingFromYamlShouldThrowIfMultipleContentStringsAreGivenAndNoneAreEnglish) { + YAML::Node node = YAML::Load("type: say\n" + "content:\n" + " - lang: de\n" + " str: content1\n" + " - lang: fr\n" + " str: content2"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST_P(MessageTest, decodingFromYamlShouldApplySubstitutionsWhenThereIsOnlyOneContentString) { + YAML::Node node = YAML::Load("type: say\n" + "content: con%1%tent1\n" + "subs:\n" + " - sub1"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({MessageContent("consub1tent1", Language::english)}), message.Content()); + } + + TEST_P(MessageTest, decodingFromYamlShouldApplySubstitutionsToAllContentStrings) { + YAML::Node node = YAML::Load("type: say\n" + "content:\n" + " - lang: en\n" + " str: content1 %1%\n" + " - lang: de\n" + " str: content2 %1%\n" + "subs:\n" + " - sub"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({ + MessageContent("content1 sub", Language::english), + MessageContent("content2 sub", Language::german), + }), message.Content()); + } + + TEST_P(MessageTest, decodingFromYamlShouldThrowIfTheContentStringExpectsMoreSubstitutionsThanExist) { + YAML::Node node = YAML::Load("type: say\n" + "content: '%1% %2%'\n" + "subs:\n" + " - sub1"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + // Don't throw because no subs are given, so none are expected in the content string. + TEST_P(MessageTest, decodingFromYamlShouldIgnoreSubstitutionSyntaxIfNoSubstitutionsExist) { + YAML::Node node = YAML::Load("type: say\n" + "content: con%1%tent1\n"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({MessageContent("con%1%tent1", Language::english)}), message.Content()); + } + + TEST_P(MessageTest, decodingFromYamlShouldThrowIfAnInvalidConditionIsGiven) { + YAML::Node node = YAML::Load("type: say\n" + "content: content1\n" + "condition: invalid"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST_P(MessageTest, decodingFromYamlShouldThrowIfAScalarIsGiven) { + YAML::Node node = YAML::Load("scalar"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST_P(MessageTest, decodingFromYamlShouldThrowIfAListIsGiven) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/plugin_dirty_info_test.h b/src/tests/backend/metadata/plugin_dirty_info_test.h new file mode 100644 index 00000000..fca0b811 --- /dev/null +++ b/src/tests/backend/metadata/plugin_dirty_info_test.h @@ -0,0 +1,216 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_PLUGIN_DIRTY_INFO +#define LOOT_TEST_BACKEND_METADATA_PLUGIN_DIRTY_INFO + +#include "backend/metadata/plugin_dirty_info.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class PluginDirtyInfoTest : public BaseGameTest {}; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + PluginDirtyInfoTest, + ::testing::Values( + GameSettings::tes4)); + + TEST_P(PluginDirtyInfoTest, defaultConstructorShouldLeaveAllCountsAtZeroAndTheUtilityStringEmpty) { + PluginDirtyInfo info; + EXPECT_EQ(0, info.CRC()); + EXPECT_EQ(0, info.ITMs()); + EXPECT_EQ(0, info.DeletedRefs()); + EXPECT_EQ(0, info.DeletedNavmeshes()); + EXPECT_TRUE(info.CleaningUtility().empty()); + } + + TEST_P(PluginDirtyInfoTest, contentConstructorShouldStoreAllGivenData) { + PluginDirtyInfo info(0x12345678, 2, 10, 30, "cleaner"); + EXPECT_EQ(0x12345678, info.CRC()); + EXPECT_EQ(2, info.ITMs()); + EXPECT_EQ(10, info.DeletedRefs()); + EXPECT_EQ(30, info.DeletedNavmeshes()); + EXPECT_EQ("cleaner", info.CleaningUtility()); + } + + TEST_P(PluginDirtyInfoTest, asMessageShouldOutputAllNonZeroCounts) { + Message message = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Contains 2 ITM records, 10 deleted references and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::english).Str()); + + message = PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Clean with cleaner.", message.ChooseContent(Language::english).Str()); + + message = PluginDirtyInfo(0x12345678, 0, 10, 30, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Contains 10 deleted references and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::english).Str()); + + message = PluginDirtyInfo(0x12345678, 0, 0, 30, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Contains 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::english).Str()); + + message = PluginDirtyInfo(0x12345678, 0, 10, 0, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Contains 10 deleted references. Clean with cleaner.", message.ChooseContent(Language::english).Str()); + + message = PluginDirtyInfo(0x12345678, 2, 0, 30, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Contains 2 ITM records and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::english).Str()); + + message = PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Contains 2 ITM records. Clean with cleaner.", message.ChooseContent(Language::english).Str()); + + message = PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner").AsMessage(); + EXPECT_EQ(Message::warn, message.Type()); + EXPECT_EQ("Contains 2 ITM records and 10 deleted references. Clean with cleaner.", message.ChooseContent(Language::english).Str()); + } + + TEST_P(PluginDirtyInfoTest, dirtyInfoShouldBeEqualIfCrcValuesAreEqual) { + PluginDirtyInfo info1(0x12345678, 2, 10, 30, "cleaner1"); + PluginDirtyInfo info2(0x12345678, 4, 20, 60, "cleaner2"); + EXPECT_TRUE(info1 == info2); + + info1 = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner"); + info2 = PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner"); + EXPECT_FALSE(info1 == info2); + } + + TEST_P(PluginDirtyInfoTest, LessThanOperatorShouldCompareCrcValues) { + PluginDirtyInfo info1(0x12345678, 2, 10, 30, "cleaner1"); + PluginDirtyInfo info2(0x12345678, 4, 20, 60, "cleaner2"); + EXPECT_FALSE(info1 < info2); + EXPECT_FALSE(info2 < info1); + + info1 = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner"); + info2 = PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner"); + EXPECT_TRUE(info1 < info2); + EXPECT_FALSE(info2 < info1); + } + + TEST_P(PluginDirtyInfoTest, evalConditionShouldBeTrueIfTheCrcGivenMatchesTheRealPluginCrc) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + PluginDirtyInfo dirtyInfo(blankEsmCrc, 2, 10, 30, "cleaner"); + EXPECT_TRUE(dirtyInfo.EvalCondition(game, blankEsm)); + } + + TEST_P(PluginDirtyInfoTest, evalConditionShouldBeFalseIfTheCrcGivenDoesNotMatchTheRealPluginCrc) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + PluginDirtyInfo dirtyInfo(0xDEADBEEF, 2, 10, 30, "cleaner"); + EXPECT_FALSE(dirtyInfo.EvalCondition(game, blankEsm)); + } + + TEST_P(PluginDirtyInfoTest, evalConditionShouldBeFalseIfAnEmptyPluginFilenameIsGiven) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + PluginDirtyInfo dirtyInfo; + EXPECT_FALSE(dirtyInfo.EvalCondition(game, "")); + } + + TEST_P(PluginDirtyInfoTest, emittingAsYamlShouldOutputAllNonZeroCounts) { + PluginDirtyInfo info(0x12345678, 2, 10, 30, "cleaner"); + YAML::Emitter emitter; + emitter << info; + + EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\nitm: 2\nudr: 10\nnav: 30", emitter.c_str()); + } + + TEST_P(PluginDirtyInfoTest, emittingAsYamlShouldOmitAllZeroCounts) { + PluginDirtyInfo info(0x12345678, 0, 0, 0, "cleaner"); + YAML::Emitter emitter; + emitter << info; + + EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'", emitter.c_str()); + } + + TEST_P(PluginDirtyInfoTest, encodingAsYamlShouldOmitAllZeroCountFields) { + PluginDirtyInfo info(0x12345678, 0, 0, 0, "cleaner"); + YAML::Node node; + node = info; + + EXPECT_EQ(0x12345678, node["crc"].as()); + EXPECT_EQ("cleaner", node["util"].as()); + EXPECT_FALSE(node["itm"]); + EXPECT_FALSE(node["udr"]); + EXPECT_FALSE(node["nav"]); + } + + TEST_P(PluginDirtyInfoTest, encodingAsYamlShouldOutputAllNonZeroCountFields) { + PluginDirtyInfo info(0x12345678, 2, 10, 30, "cleaner"); + YAML::Node node; + node = info; + + EXPECT_EQ(0x12345678, node["crc"].as()); + EXPECT_EQ("cleaner", node["util"].as()); + EXPECT_EQ(2, node["itm"].as()); + EXPECT_EQ(10, node["udr"].as()); + EXPECT_EQ(30, node["nav"].as()); + } + + TEST_P(PluginDirtyInfoTest, decodingFromYamlShouldLeaveMissingFieldsWithZeroValues) { + YAML::Node node = YAML::Load("{crc: 0x12345678, util: cleaner}"); + PluginDirtyInfo info = node.as(); + + EXPECT_EQ(0x12345678, info.CRC()); + EXPECT_EQ(0, info.ITMs()); + EXPECT_EQ(0, info.DeletedRefs()); + EXPECT_EQ(0, info.DeletedNavmeshes()); + EXPECT_EQ("cleaner", info.CleaningUtility()); + } + + TEST_P(PluginDirtyInfoTest, decodingFromYamlShouldStoreAllNonZeroCounts) { + YAML::Node node = YAML::Load("{crc: 0x12345678, util: cleaner, itm: 2, udr: 10, nav: 30}"); + PluginDirtyInfo info = node.as(); + + EXPECT_EQ(0x12345678, info.CRC()); + EXPECT_EQ(2, info.ITMs()); + EXPECT_EQ(10, info.DeletedRefs()); + EXPECT_EQ(30, info.DeletedNavmeshes()); + EXPECT_EQ("cleaner", info.CleaningUtility()); + } + + TEST_P(PluginDirtyInfoTest, decodingFromYamlScalarShouldThrow) { + YAML::Node node = YAML::Load("scalar"); + + EXPECT_ANY_THROW(node.as()); + } + + TEST_P(PluginDirtyInfoTest, decodingFromYamlListShouldThrow) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_ANY_THROW(node.as()); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/plugin_metadata_test.h b/src/tests/backend/metadata/plugin_metadata_test.h new file mode 100644 index 00000000..4c7e1d69 --- /dev/null +++ b/src/tests/backend/metadata/plugin_metadata_test.h @@ -0,0 +1,1084 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_F_BACKEND_METADATA_PLUGIN_METADATA +#define LOOT_TEST_F_BACKEND_METADATA_PLUGIN_METADATA + +#include "backend/metadata/plugin_metadata.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class PluginMetadataTest : public BaseGameTest {}; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + PluginMetadataTest, + ::testing::Values( + GameSettings::tes5)); + + TEST_P(PluginMetadataTest, defaultConstructorShouldLeaveNameEmptyAndEnableMetadataAndLeaveAllOtherFieldsAtTheirDefaults) { + PluginMetadata plugin; + + EXPECT_TRUE(plugin.Name().empty()); + EXPECT_TRUE(plugin.Enabled()); + EXPECT_FALSE(plugin.IsPriorityExplicit()); + EXPECT_FALSE(plugin.IsPriorityGlobal()); + EXPECT_EQ(0, plugin.Priority()); + } + + TEST_P(PluginMetadataTest, stringConstructorShouldSetNameToGivenStringAndEnableMetadataAndLeaveAllOtherFieldsAtTheirDefaults) { + PluginMetadata plugin(blankEsm); + + EXPECT_EQ(blankEsm, plugin.Name()); + EXPECT_TRUE(plugin.Enabled()); + EXPECT_FALSE(plugin.IsPriorityExplicit()); + EXPECT_FALSE(plugin.IsPriorityGlobal()); + EXPECT_EQ(0, plugin.Priority()); + } + + TEST_P(PluginMetadataTest, equalityOperatorShouldUseCaseInsensitiveNameComparisonForNonRegexNames) { + PluginMetadata plugin1(blankEsm); + PluginMetadata plugin2(boost::to_lower_copy(blankEsm)); + EXPECT_TRUE(plugin1 == plugin2); + + plugin1 = PluginMetadata(blankEsm); + plugin2 = PluginMetadata(blankDifferentEsm); + EXPECT_FALSE(plugin1 == plugin2); + } + + TEST_P(PluginMetadataTest, equalityOperatorShouldUseCaseInsensitiveNameComparisonForTwoRegexNames) { + PluginMetadata plugin1("Blan.\\.esm"); + PluginMetadata plugin2("blan.\\.esm"); + EXPECT_TRUE(plugin1 == plugin2); + EXPECT_TRUE(plugin2 == plugin1); + + plugin1 = PluginMetadata("Blan(k|p).esm"); + plugin2 = PluginMetadata("Blan.\\.esm"); + EXPECT_FALSE(plugin1 == plugin2); + EXPECT_FALSE(plugin2 == plugin1); + } + + TEST_P(PluginMetadataTest, equalityOperatorShouldUseRegexMatchingForARegexNameAndANonRegexName) { + PluginMetadata plugin1("Blank.esm"); + PluginMetadata plugin2("Blan.\\.esm"); + EXPECT_TRUE(plugin1 == plugin2); + EXPECT_TRUE(plugin2 == plugin1); + + plugin1 = PluginMetadata("Blan.esm"); + plugin2 = PluginMetadata("Blan.\\.esm"); + EXPECT_FALSE(plugin1 == plugin2); + EXPECT_FALSE(plugin2 == plugin1); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldNotChangeName) { + PluginMetadata plugin1(blankEsm); + PluginMetadata plugin2(blankDifferentEsm); + + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(blankEsm, plugin1.Name()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldNotUseMergedEnabledStateIfMergedMetadataIsEmpty) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.Enabled(false); + ASSERT_TRUE(plugin2.HasNameOnly()); + plugin1.MergeMetadata(plugin2); + + EXPECT_TRUE(plugin1.Enabled()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldUseMergedEnabledStateIfMergedMetadataIsNotEmpty) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.Enabled(false); + plugin2.SetPriorityExplicit(true); + ASSERT_FALSE(plugin2.HasNameOnly()); + plugin1.MergeMetadata(plugin2); + + EXPECT_FALSE(plugin1.Enabled()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldUseMergedNonZeroPriorityValue) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.Priority(5); + plugin2.Priority(3); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(3, plugin1.Priority()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeAnExplicitPriorityValueOfZero) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.Priority(5); + plugin2.SetPriorityExplicit(true); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(0, plugin1.Priority()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldNotMergeNonExplicitGlobalPriorityState) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.SetPriorityGlobal(true); + plugin1.MergeMetadata(plugin2); + + EXPECT_FALSE(plugin1.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeExplicitGlobalPriorityState) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.SetPriorityExplicit(true); + plugin2.SetPriorityGlobal(true); + plugin1.MergeMetadata(plugin2); + + EXPECT_TRUE(plugin1.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeTrueExplicitPriorityState) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.SetPriorityExplicit(true); + plugin1.MergeMetadata(plugin2); + + EXPECT_TRUE(plugin1.IsPriorityExplicit()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldNotMergeFalseExplicitPriorityState) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.SetPriorityExplicit(true); + plugin1.MergeMetadata(plugin2); + + EXPECT_TRUE(plugin1.IsPriorityExplicit()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeLoadAfterData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + + plugin1.LoadAfter({file1}); + plugin2.LoadAfter({file1, file2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::set({file1, file2}), plugin1.LoadAfter()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeRequirementData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + + plugin1.Reqs({file1}); + plugin2.Reqs({file1, file2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::set({file1, file2}), plugin1.Reqs()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeIncompatibilityData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + + plugin1.Incs({file1}); + plugin2.Incs({file1, file2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::set({file1, file2}), plugin1.Incs()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeMessages) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Message message(Message::say, "content"); + + plugin1.Messages({message}); + plugin2.Messages({message}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::list({message, message}), plugin1.Messages()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeTags) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Tag tag1("Relev"); + Tag tag2("Relev", false); + Tag tag3("Delev"); + + plugin1.Tags({tag1}); + plugin2.Tags({tag1, tag2, tag3}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::set({tag1, tag2, tag3}), plugin1.Tags()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeDirtyInfoData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + PluginDirtyInfo info1(0x5, 1, 2, 3, "utility"); + PluginDirtyInfo info2(0xA, 1, 2, 3, "utility"); + + plugin1.DirtyInfo({info1}); + plugin2.DirtyInfo({info1, info2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::set({info1, info2}), plugin1.DirtyInfo()); + } + + TEST_P(PluginMetadataTest, mergeMetadataShouldMergeLocationData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Location location1("http://www.example.com/1"); + Location location2("http://www.example.com/2"); + + plugin1.Locations({location1}); + plugin2.Locations({location1, location2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::set({location1, location2}), plugin1.Locations()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldUseSourcePluginName) { + PluginMetadata plugin1(blankEsm); + PluginMetadata plugin2(blankDifferentEsm); + + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(blankEsm, diff.Name()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldUseSourcePluginEnabledState) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.Enabled(false); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_TRUE(diff.Enabled()); + + plugin1.Enabled(false); + diff = plugin1.DiffMetadata(plugin2); + + EXPECT_FALSE(diff.Enabled()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldUseSourcePluginPriorityDataIfItDiffersFromTheTargetPluginPriorityData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.SetPriorityGlobal(true); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(0, diff.Priority()); + EXPECT_FALSE(diff.IsPriorityExplicit()); + EXPECT_TRUE(diff.IsPriorityGlobal()); + + plugin1.Priority(5); + plugin1.SetPriorityGlobal(false); + diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(5, diff.Priority()); + EXPECT_TRUE(diff.IsPriorityExplicit()); + EXPECT_FALSE(diff.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputDefaultPriorityDataIfTheSourceAndTargetPluginPriorityDataMatch) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.Priority(5); + plugin1.SetPriorityGlobal(true); + plugin2.Priority(5); + plugin2.SetPriorityGlobal(true); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(0, diff.Priority()); + EXPECT_FALSE(diff.IsPriorityExplicit()); + EXPECT_FALSE(diff.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputLoadAfterDataThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + File file3(blankEsp); + + plugin1.LoadAfter({file1, file2}); + plugin2.LoadAfter({file1, file3}); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(std::set({file2, file3}), diff.LoadAfter()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputRequirementsDataThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + File file3(blankEsp); + + plugin1.Reqs({file1, file2}); + plugin2.Reqs({file1, file3}); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(std::set({file2, file3}), diff.Reqs()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputIncompatibilityDataThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + File file3(blankEsp); + + plugin1.Incs({file1, file2}); + plugin2.Incs({file1, file3}); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(std::set({file2, file3}), diff.Incs()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputMessagesThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Message message1(Message::say, "content1"); + Message message2(Message::say, "content2"); + Message message3(Message::say, "content3"); + + plugin1.Messages({message1, message2}); + plugin2.Messages({message1, message3}); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(std::list({message2, message3}), diff.Messages()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputTagsThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Tag tag1("Relev"); + Tag tag2("Relev", false); + Tag tag3("Delev"); + + plugin1.Tags({tag1, tag2}); + plugin2.Tags({tag1, tag3}); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(std::set({tag2, tag3}), diff.Tags()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputDirtyInfoObjectsThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + PluginDirtyInfo info1(0x5, 1, 2, 3, "utility"); + PluginDirtyInfo info2(0xA, 1, 2, 3, "utility"); + PluginDirtyInfo info3(0x1, 1, 2, 3, "utility"); + + plugin1.DirtyInfo({info1, info2}); + plugin2.DirtyInfo({info1, info3}); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(std::set({info2, info3}), diff.DirtyInfo()); + } + + TEST_P(PluginMetadataTest, diffMetadataShouldOutputLocationsThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Location location1("http://www.example.com/1"); + Location location2("http://www.example.com/2"); + Location location3("http://www.example.com/3"); + + plugin1.Locations({location1, location2}); + plugin2.Locations({location1, location3}); + PluginMetadata diff = plugin1.DiffMetadata(plugin2); + + EXPECT_EQ(std::set({location2, location3}), diff.Locations()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldUseSourcePluginName) { + PluginMetadata plugin1(blankEsm); + PluginMetadata plugin2(blankDifferentEsm); + + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(blankEsm, newMetadata.Name()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldUseSourcePluginEnabledState) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.Enabled(false); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_TRUE(newMetadata.Enabled()); + + plugin1.Enabled(false); + newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_FALSE(newMetadata.Enabled()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldUseSourcePluginPriorityData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.Priority(5); + plugin1.SetPriorityGlobal(true); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(5, newMetadata.Priority()); + EXPECT_TRUE(newMetadata.IsPriorityExplicit()); + EXPECT_TRUE(newMetadata.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldOutputLoadAfterDataThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + File file3(blankEsp); + + plugin1.LoadAfter({file1, file2}); + plugin2.LoadAfter({file1, file3}); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(std::set({file2}), newMetadata.LoadAfter()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldOutputRequirementsDataThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + File file3(blankEsp); + + plugin1.Reqs({file1, file2}); + plugin2.Reqs({file1, file3}); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(std::set({file2}), newMetadata.Reqs()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldOutputIncompatibilityDataThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + File file3(blankEsp); + + plugin1.Incs({file1, file2}); + plugin2.Incs({file1, file3}); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(std::set({file2}), newMetadata.Incs()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldOutputMessagesThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Message message1(Message::say, "content1"); + Message message2(Message::say, "content2"); + Message message3(Message::say, "content3"); + + plugin1.Messages({message1, message2}); + plugin2.Messages({message1, message3}); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(std::list({message2}), newMetadata.Messages()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldOutputTagsThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Tag tag1("Relev"); + Tag tag2("Relev", false); + Tag tag3("Delev"); + + plugin1.Tags({tag1, tag2}); + plugin2.Tags({tag1, tag3}); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(std::set({tag2}), newMetadata.Tags()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldOutputDirtyInfoObjectsThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + PluginDirtyInfo info1(0x5, 1, 2, 3, "utility"); + PluginDirtyInfo info2(0xA, 1, 2, 3, "utility"); + PluginDirtyInfo info3(0x1, 1, 2, 3, "utility"); + + plugin1.DirtyInfo({info1, info2}); + plugin2.DirtyInfo({info1, info3}); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(std::set({info2}), newMetadata.DirtyInfo()); + } + + TEST_P(PluginMetadataTest, newMetadataShouldOutputLocationsThatAreNotCommonToBothInputPlugins) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Location location1("http://www.example.com/1"); + Location location2("http://www.example.com/2"); + Location location3("http://www.example.com/3"); + + plugin1.Locations({location1, location2}); + plugin2.Locations({location1, location3}); + PluginMetadata newMetadata = plugin1.NewMetadata(plugin2); + + EXPECT_EQ(std::set({location2}), newMetadata.Locations()); + } + + TEST_P(PluginMetadataTest, settingPriorityWithAbsoluteValueGreaterOrEqualToGlobalPriorityDivisorShouldThrow) { + PluginMetadata plugin; + EXPECT_ANY_THROW(plugin.Priority(yamlGlobalPriorityDivisor)); + EXPECT_ANY_THROW(plugin.Priority(yamlGlobalPriorityDivisor + 1)); + EXPECT_ANY_THROW(plugin.Priority(-yamlGlobalPriorityDivisor)); + EXPECT_ANY_THROW(plugin.Priority(-yamlGlobalPriorityDivisor - 1)); + } + + TEST_P(PluginMetadataTest, settingPriorityAsGlobalShouldSucceed) { + PluginMetadata plugin; + ASSERT_FALSE(plugin.IsPriorityGlobal()); + plugin.SetPriorityGlobal(true); + EXPECT_TRUE(plugin.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, settingPriorityAsNotGlobalShouldSucceed) { + PluginMetadata plugin; + plugin.SetPriorityGlobal(true); + ASSERT_TRUE(plugin.IsPriorityGlobal()); + plugin.SetPriorityGlobal(false); + EXPECT_FALSE(plugin.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, gettingYamlPriorityValueForAGlobalPriorityShouldReturnValueWithGlobalFlagSet) { + PluginMetadata plugin; + plugin.Priority(10); + plugin.SetPriorityGlobal(true); + EXPECT_EQ(1000010, plugin.GetYamlPriorityValue()); + + plugin.Priority(-20); + EXPECT_EQ(-1000020, plugin.GetYamlPriorityValue()); + } + + TEST_P(PluginMetadataTest, gettingYamlPriorityValueForANonGlobalPriorityShouldReturnValueWithGlobalFlagNotSet) { + PluginMetadata plugin; + plugin.Priority(10); + EXPECT_EQ(10, plugin.GetYamlPriorityValue()); + + plugin.Priority(-20); + EXPECT_EQ(-20, plugin.GetYamlPriorityValue()); + } + + TEST_P(PluginMetadataTest, evalAllConditionsShouldEvaluateAllMetadataConditions) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + + PluginMetadata plugin(blankEsm); + + File file1(blankEsp); + File file2(blankDifferentEsm, "", "file(\"" + missingEsp + "\")"); + plugin.LoadAfter({file1, file2}); + plugin.Reqs({file1, file2}); + plugin.Incs({file1, file2}); + + Message message1(Message::say, "content"); + Message message2(Message::say, "content", "file(\"" + missingEsp + "\")"); + plugin.Messages({message1, message2}); + + Tag tag1("Relev"); + Tag tag2("Relev", true, "file(\"" + missingEsp + "\")"); + plugin.Tags({tag1, tag2}); + + PluginDirtyInfo info1(blankEsmCrc, 1, 2, 3, "utility"); + PluginDirtyInfo info2(0xDEADBEEF, 1, 2, 3, "utility"); + plugin.DirtyInfo({info1, info2}); + + EXPECT_NO_THROW(plugin.EvalAllConditions(game, Language::english)); + + std::set expectedFiles({file1}); + EXPECT_EQ(expectedFiles, plugin.LoadAfter()); + EXPECT_EQ(expectedFiles, plugin.Reqs()); + EXPECT_EQ(expectedFiles, plugin.Incs()); + EXPECT_EQ(std::list({message1}), plugin.Messages()); + EXPECT_EQ(std::set({tag1}), plugin.Tags()); + EXPECT_EQ(std::set({info1}), plugin.DirtyInfo()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeTrueForADefaultConstructedPluginMetadataObject) { + PluginMetadata plugin; + + EXPECT_TRUE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeTrueForAPluginMetadataObjectConstructedWithAName) { + PluginMetadata plugin(blankEsp); + + EXPECT_TRUE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeTrueIfThePluginMetadataIsDisabled) { + PluginMetadata plugin(blankEsp); + plugin.Enabled(false); + + EXPECT_TRUE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfThePriorityValueIsExplicit) { + PluginMetadata plugin(blankEsp); + plugin.SetPriorityExplicit(true); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfLoadAfterMetadataExists) { + PluginMetadata plugin(blankEsp); + plugin.LoadAfter({File(blankEsm)}); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfRequirementMetadataExists) { + PluginMetadata plugin(blankEsp); + plugin.Reqs({File(blankEsm)}); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfIncompatibilityMetadataExists) { + PluginMetadata plugin(blankEsp); + plugin.Incs({File(blankEsm)}); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfMessagesExist) { + PluginMetadata plugin(blankEsp); + plugin.Messages({Message(Message::say, "content")}); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfTagsExist) { + PluginMetadata plugin(blankEsp); + plugin.Tags({Tag("Relev")}); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfDirtyInfoExists) { + PluginMetadata plugin(blankEsp); + plugin.DirtyInfo({PluginDirtyInfo(5, 0, 1, 2, "utility")}); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, hasNameOnlyShouldBeFalseIfLocationsExist) { + PluginMetadata plugin(blankEsp); + plugin.Locations({Location("http://www.example.com")}); + + EXPECT_FALSE(plugin.HasNameOnly()); + } + + TEST_P(PluginMetadataTest, isRegexPluginShouldBeFalseForAnEmptyPluginName) { + PluginMetadata plugin; + + EXPECT_FALSE(plugin.IsRegexPlugin()); + } + + TEST_P(PluginMetadataTest, isRegexPluginShouldBeFalseForAnExactPluginFilename) { + PluginMetadata plugin(blankEsm); + + EXPECT_FALSE(plugin.IsRegexPlugin()); + } + + TEST_P(PluginMetadataTest, isRegexPluginShouldBeTrueIfThePluginNameContainsAColon) { + PluginMetadata plugin("Blank:.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); + } + + TEST_P(PluginMetadataTest, isRegexPluginShouldBeTrueIfThePluginNameContainsABackslash) { + PluginMetadata plugin("Blank\\.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); + } + + TEST_P(PluginMetadataTest, isRegexPluginShouldBeTrueIfThePluginNameContainsAnAsterisk) { + PluginMetadata plugin("Blank*.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); + } + + TEST_P(PluginMetadataTest, isRegexPluginShouldBeTrueIfThePluginNameContainsAQuestionMark) { + PluginMetadata plugin("Blank?.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); + } + + TEST_P(PluginMetadataTest, isRegexPluginShouldBeTrueIfThePluginNameContainsAVerticalBar) { + PluginMetadata plugin("Blank|.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithNoMetadataAsABlankString) { + PluginMetadata plugin(blankEsm); + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithAnExplicitPriorityCorrectly) { + PluginMetadata plugin(blankEsm); + plugin.SetPriorityExplicit(true); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esm'\n" + "priority: 0", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithAnExplicitPriorityThatIsDisabledCorrectly) { + PluginMetadata plugin(blankEsm); + plugin.SetPriorityExplicit(true); + plugin.Enabled(false); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esm'\n" + "priority: 0\n" + "enabled: false", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithLoadAfterMetadataCorrectly) { + PluginMetadata plugin(blankEsp); + plugin.LoadAfter({File(blankEsm)}); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esp'\n" + "after:\n" + " - 'Blank.esm'", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithRequirementsCorrectly) { + PluginMetadata plugin(blankEsp); + plugin.Reqs({File(blankEsm)}); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esp'\n" + "req:\n" + " - 'Blank.esm'", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithIncompatibilitiesCorrectly) { + PluginMetadata plugin(blankEsp); + plugin.Incs({File(blankEsm)}); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esp'\n" + "inc:\n" + " - 'Blank.esm'", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithMessagesCorrectly) { + PluginMetadata plugin(blankEsp); + plugin.Messages({Message(Message::say, "content")}); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esp'\n" + "msg:\n" + " - type: say\n" + " content: 'content'", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithTagsCorrectly) { + PluginMetadata plugin(blankEsp); + plugin.Tags({Tag("Relev")}); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esp'\n" + "tag:\n" + " - Relev", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithDirtyInfoCorrectly) { + PluginMetadata plugin(blankEsp); + plugin.DirtyInfo({PluginDirtyInfo(5, 0, 1, 2, "utility")}); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esp'\n" + "dirty:\n" + " - crc: 0x5\n" + " util: 'utility'\n" + " udr: 1\n" + " nav: 2", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithLocationsCorrectly) { + PluginMetadata plugin(blankEsp); + plugin.Locations({Location("http://www.example.com")}); + + YAML::Emitter emitter; + emitter << plugin; + + EXPECT_STREQ("name: 'Blank.esp'\n" + "url:\n" + " - 'http://www.example.com'", emitter.c_str()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldOmitAllUnsetFields) { + PluginMetadata plugin(blankEsp); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.Name(), node["name"].as()); + EXPECT_FALSE(node["enabled"]); + EXPECT_FALSE(node["priority"]); + EXPECT_FALSE(node["after"]); + EXPECT_FALSE(node["req"]); + EXPECT_FALSE(node["inc"]); + EXPECT_FALSE(node["msg"]); + EXPECT_FALSE(node["tag"]); + EXPECT_FALSE(node["dirty"]); + EXPECT_FALSE(node["url"]); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetPriorityFieldIfPriorityIsExplicit) { + PluginMetadata plugin(blankEsp); + plugin.SetPriorityExplicit(true); + YAML::Node node; + node = plugin; + + EXPECT_EQ(0, node["priority"].as()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetEnabledFieldIfItIsFalse) { + PluginMetadata plugin(blankEsp); + plugin.Enabled(false); + YAML::Node node; + node = plugin; + + EXPECT_FALSE(node["enabled"].as()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetAfterFieldIfLoadAfterMetadataExists) { + PluginMetadata plugin(blankEsp); + plugin.LoadAfter({File(blankEsm)}); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.LoadAfter(), node["after"].as>()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetReqFieldIfRequirementsExist) { + PluginMetadata plugin(blankEsp); + plugin.Reqs({File(blankEsm)}); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.Reqs(), node["req"].as>()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetIncFieldIfIncompatibilitiesExist) { + PluginMetadata plugin(blankEsp); + plugin.Incs({File(blankEsm)}); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.Incs(), node["inc"].as>()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetMsgFieldIfMessagesExist) { + PluginMetadata plugin(blankEsp); + plugin.Messages({Message(Message::say, "content")}); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.Messages(), node["msg"].as>()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetTagFieldIfTagsExist) { + PluginMetadata plugin(blankEsp); + plugin.Tags({Tag("Relev")}); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.Tags(), node["tag"].as>()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetDirtyFieldIfDirtyInfoExists) { + PluginMetadata plugin(blankEsp); + plugin.DirtyInfo({PluginDirtyInfo(5, 0, 1, 2, "utility")}); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.DirtyInfo(), node["dirty"].as>()); + } + + TEST_P(PluginMetadataTest, encodingAsYamlShouldSetUrlFieldIfLocationsExist) { + PluginMetadata plugin(blankEsp); + plugin.Locations({Location("http://www.example.com")}); + YAML::Node node; + node = plugin; + + EXPECT_EQ(plugin.Locations(), node["url"].as>()); + } + + TEST_P(PluginMetadataTest, decodingFromYamlShouldSetDefaultPriorityValuesIfNoneAreSpecified) { + YAML::Node node = YAML::Load("name: " + blankEsp); + PluginMetadata plugin = node.as(); + + EXPECT_EQ(blankEsp, plugin.Name()); + EXPECT_EQ(0, plugin.Priority()); + EXPECT_FALSE(plugin.IsPriorityExplicit()); + EXPECT_FALSE(plugin.IsPriorityGlobal()); + } + + TEST_P(PluginMetadataTest, decodingFromYamlShouldStoreAllGivenData) { + YAML::Node node = YAML::Load("name: 'Blank.esp'\n" + "priority: 5\n" + "enabled: false\n" + "after:\n" + " - 'Blank.esm'\n" + "req:\n" + " - 'Blank.esm'\n" + "inc:\n" + " - 'Blank.esm'\n" + "msg:\n" + " - type: say\n" + " content: 'content'\n" + "tag:\n" + " - Relev\n" + "dirty:\n" + " - crc: 0x5\n" + " util: 'utility'\n" + " udr: 1\n" + " nav: 2\n" + "url:\n" + " - 'http://www.example.com'"); + PluginMetadata plugin = node.as(); + + EXPECT_EQ("Blank.esp", plugin.Name()); + EXPECT_EQ(5, plugin.Priority()); + EXPECT_TRUE(plugin.IsPriorityExplicit()); + EXPECT_FALSE(plugin.IsPriorityGlobal()); + EXPECT_FALSE(plugin.Enabled()); + EXPECT_EQ(std::set({ + File("Blank.esm") + }), plugin.LoadAfter()); + EXPECT_EQ(std::set({ + File("Blank.esm") + }), plugin.Reqs()); + EXPECT_EQ(std::set({ + File("Blank.esm") + }), plugin.Incs()); + EXPECT_EQ(std::list({ + Message(Message::say, "content") + }), plugin.Messages()); + EXPECT_EQ(std::set({ + Tag("Relev") + }), plugin.Tags()); + EXPECT_EQ(std::set({ + PluginDirtyInfo(5, 0, 1, 2, "utility") + }), plugin.DirtyInfo()); + EXPECT_EQ(std::set({ + Location("http://www.example.com") + }), plugin.Locations()); + } + + TEST_P(PluginMetadataTest, decodingFromYamlWithDirtyInfoInARegexPluginMetadataObjectShouldThrow) { + YAML::Node node = YAML::Load("name: 'Blank\\.esp'\n" + "dirty:\n" + " - crc: 0x5\n" + " util: 'utility'\n" + " udr: 1\n" + " nav: 2"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST_P(PluginMetadataTest, decodingFromYamlWithAnInvalidRegexNameShouldThrow) { + YAML::Node node = YAML::Load("name: 'RagnvaldBook(Farengar(+Ragnvald)?)?\\.esp'\n" + "dirty:\n" + " - crc: 0x5\n" + " util: 'utility'\n" + " udr: 1\n" + " nav: 2"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST_P(PluginMetadataTest, decodingFromAYamlScalarShouldThrow) { + YAML::Node node = YAML::Load("scalar"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST_P(PluginMetadataTest, decodingFromAYamlListShouldThrow) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/tag_test.h b/src/tests/backend/metadata/tag_test.h new file mode 100644 index 00000000..a140fafd --- /dev/null +++ b/src/tests/backend/metadata/tag_test.h @@ -0,0 +1,191 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_TAG +#define LOOT_TEST_BACKEND_METADATA_TAG + +#include "backend/metadata/tag.h" + +#include + +namespace loot { + namespace test { + TEST(Tag, defaultConstructorShouldSetEmptyNameAndConditionStringsForATagAddition) { + Tag tag; + + EXPECT_TRUE(tag.Name().empty()); + EXPECT_TRUE(tag.IsAddition()); + EXPECT_TRUE(tag.Condition().empty()); + } + + TEST(Tag, dataConstructorShouldSetFieldsToGivenValues) { + Tag tag("name", false, "condition"); + + EXPECT_EQ("name", tag.Name()); + EXPECT_FALSE(tag.IsAddition()); + EXPECT_EQ("condition", tag.Condition()); + } + + TEST(Tag, tagsWithCaseInsensitiveEqualNamesAndEqualAdditionStatesShouldBeEqual) { + Tag tag1("Name", true, "condition1"); + Tag tag2("name", true, "condition2"); + + EXPECT_TRUE(tag1 == tag2); + } + + TEST(Tags, tagsWithUnequalNamesShouldNotBeEqual) { + Tag tag1("name1"); + Tag tag2("name2"); + + EXPECT_FALSE(tag1 == tag2); + } + + TEST(Tag, tagsWithUnequalAdditionStatesShouldNotBeEqual) { + Tag tag1("Name", true); + Tag tag2("name", false); + + EXPECT_FALSE(tag1 == tag2); + } + + TEST(Tag, lessThanOperatorShouldCaseInsensitivelyLexicographicallyCompareNameStrings) { + Tag tag1("Name"); + Tag tag2("name"); + + EXPECT_FALSE(tag1 < tag2); + EXPECT_FALSE(tag2 < tag1); + + tag1 = Tag("name1"); + tag2 = Tag("name2"); + + EXPECT_TRUE(tag1 < tag2); + EXPECT_FALSE(tag2 < tag1); + } + + TEST(Tag, lessThanOperatorShouldTreatTagAdditionsAsBeingLessThanRemovals) { + Tag tag1("name", true); + Tag tag2("name", false); + + EXPECT_TRUE(tag1 < tag2); + EXPECT_FALSE(tag2 < tag1); + } + + TEST(Tag, emittingAsYamlShouldOutputOnlyTheNameStringIfTheTagIsAnAdditionWithNoCondition) { + Tag tag("name1"); + YAML::Emitter emitter; + emitter << tag; + + EXPECT_EQ(tag.Name(), emitter.c_str()); + } + + TEST(Tag, emittingAsYamlShouldOutputOnlyTheNameStringPrefixedWithAHyphenIfTheTagIsARemovalWithNoCondition) { + Tag tag("name1", false); + YAML::Emitter emitter; + emitter << tag; + + EXPECT_EQ("-" + tag.Name(), emitter.c_str()); + } + + TEST(Tag, emittingAsYamlShouldOutputAMapIfTheTagHasACondition) { + Tag tag("name1", false, "condition1"); + YAML::Emitter emitter; + emitter << tag; + + EXPECT_STREQ("name: -name1\ncondition: 'condition1'", emitter.c_str()); + } + + TEST(Tag, encodingAsYamlShouldOmitTheConditionFieldIfTheConditionStringIsEmpty) { + Tag tag; + YAML::Node node; + node = tag; + + EXPECT_FALSE(node["condition"]); + } + + TEST(Tag, encodingAsYamlShouldOutputTheNameFieldCorrectly) { + Tag tag("name1"); + YAML::Node node; + node = tag; + + EXPECT_EQ(tag.Name(), node["name"].as()); + } + + TEST(Tag, encodingAsYamlShouldOutputTheNameFieldWithAHyphenPrefixIfTheTagIsARemoval) { + Tag tag("name1", false); + YAML::Node node; + node = tag; + + EXPECT_EQ("-" + tag.Name(), node["name"].as()); + } + + TEST(Tag, encodingAsYamlShouldOutputTheConditionFieldIfTheConditionStringIsNotEmpty) { + Tag tag("name1", true, "condition1"); + YAML::Node node; + node = tag; + + EXPECT_EQ(tag.Name(), node["name"].as()); + EXPECT_EQ(tag.Condition(), node["condition"].as()); + } + + TEST(Tag, decodingFromYamlScalarShouldSetNameCorrectly) { + YAML::Node node = YAML::Load("name1"); + Tag tag = node.as(); + + EXPECT_EQ("name1", tag.Name()); + EXPECT_TRUE(tag.IsAddition()); + EXPECT_EQ("", tag.Condition()); + } + + TEST(Tag, decodingFromYamlScalarShouldSetAdditionStateCorrectly) { + YAML::Node node = YAML::Load("-name1"); + Tag tag = node.as(); + + EXPECT_EQ("name1", tag.Name()); + EXPECT_FALSE(tag.IsAddition()); + EXPECT_EQ("", tag.Condition()); + } + + TEST(Tag, decodingFromYamlMapShouldSetDataCorrectly) { + YAML::Node node = YAML::Load("{name: name1, condition: 'file(\"Foo.esp\")'}"); + Tag tag = node.as(); + + EXPECT_EQ("name1", tag.Name()); + EXPECT_TRUE(tag.IsAddition()); + EXPECT_EQ("file(\"Foo.esp\")", tag.Condition()); + } + + TEST(Tag, decodingFromYamlShouldThrowIfAnInvalidConditionIsGiven) { + YAML::Node node = YAML::Load("{name: name1, condition: invalid}"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + + TEST(Tag, decodingFromYamlListShouldThrow) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); + } + } +} + +#endif diff --git a/src/tests/backend/metadata/test_condition_grammar.h b/src/tests/backend/metadata/test_condition_grammar.h deleted file mode 100644 index 876eaab4..00000000 --- a/src/tests/backend/metadata/test_condition_grammar.h +++ /dev/null @@ -1,660 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_CONDITION_GRAMMAR -#define LOOT_TEST_BACKEND_METADATA_CONDITION_GRAMMAR - -#include "backend/error.h" -#include "backend/metadata/condition_grammar.h" -#include "tests/fixtures.h" - -class ConditionGrammar : public SkyrimTest {}; - -typedef loot::ConditionGrammar Grammar; - -TEST_F(ConditionGrammar, Constructor) { - EXPECT_NO_THROW(Grammar cg(nullptr)); - - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - EXPECT_NO_THROW(Grammar cg(&game)); -} - -TEST_F(ConditionGrammar, InvalidSyntax) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("file(foo)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval), loot::error); -} - -TEST_F(ConditionGrammar, EmptyCondition) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition(""); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval), loot::error); -} - -TEST_F(ConditionGrammar, FileConditionTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"Blank.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, FileConditionFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"Blank.missing.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, UnsafePath) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"../../Blank.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval), loot::error); -} - -TEST_F(ConditionGrammar, RegexConditionTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("regex(\"Blank.+\\.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, RegexConditionFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("regex(\"Blank\\.m.+\\.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, RegexCondition_Subfolder) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("regex(\"resource\\\\detail\\\\resource\\.txt\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, ManyConditionTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("many(\"Blank.+\\.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, ManyConditionFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("many(\"Blank\\.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, ChecksumConditionTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("checksum(\"Blank.esp\", 24F0E2A1)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, ChecksumConditionFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("checksum(\"Blank.esp\", DEADBEEF)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionEqualTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"5.0\", ==)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionEqualFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"6.0\", ==)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionNotEqualTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"6.0\", !=)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionNotEqualFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"5.0\", !=)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionLessThanTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"6.0\", <)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionLessThanFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"5.0\", <)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionGreaterThanTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"4.0\", >)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionGreaterThanFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"5.0\", >)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionLETrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"5.0\", <=)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionLEFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"4.0\", <=)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionGETrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"5.0\", >=)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, VersionConditionGEFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.LoadPlugins(true)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("version(\"Blank.esm\", \"6.0\", >=)"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, ActiveConditionTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("active(\"Blank.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, ActiveConditionFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("active(\"Blank.esp\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, NegatorTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = false; - bool r = false; - Grammar cg(&game); - - std::string condition("not file(\"Blank.missing.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, NegatorFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("not file(\"Blank.esm\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, CompoundAndTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"Blank.esm\") and file(\"Blank.esp\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, CompoundAndFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"Blank.esm\") and file(\"Blank.missing.esp\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, CompoundOrTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"Blank.missing.esm\") or file(\"Blank.esp\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -TEST_F(ConditionGrammar, CompoundOrFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"Blank.missing.esm\") or file(\"Blank.missing.esp\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_FALSE(eval); -} - -TEST_F(ConditionGrammar, OrderOfEvaluation) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - - boost::spirit::qi::space_type skipper; - bool eval = true; - bool r = false; - Grammar cg(&game); - - std::string condition("file(\"Blank.esm\") and ( not file(\"Blank.esm\") or file(\"Blank.esp\") ) or file(\"Blank.missing.esp\")"); - std::string::const_iterator begin = condition.begin(); - std::string::const_iterator end = condition.end(); - - EXPECT_NO_THROW(r = boost::spirit::qi::phrase_parse(begin, end, cg, skipper, eval)); - EXPECT_TRUE(r); - EXPECT_TRUE(eval); -} - -#endif diff --git a/src/tests/backend/metadata/test_conditional_metadata.h b/src/tests/backend/metadata/test_conditional_metadata.h deleted file mode 100644 index 2d9ad8ce..00000000 --- a/src/tests/backend/metadata/test_conditional_metadata.h +++ /dev/null @@ -1,86 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_CONDITIONAL_METADATA -#define LOOT_TEST_BACKEND_METADATA_CONDITION_GRAMMAR - -#include "backend/error.h" -#include "backend/metadata/conditional_metadata.h" -#include "tests/fixtures.h" - -class ConditionalMetadata : public SkyrimTest {}; - -TEST_F(ConditionalMetadata, ConstructorAndDataAccess) { - loot::ConditionalMetadata cm; - EXPECT_EQ("", cm.Condition()); - - cm = loot::ConditionalMetadata("condition"); - EXPECT_EQ("condition", cm.Condition()); -} - -TEST_F(ConditionalMetadata, IsConditional) { - loot::ConditionalMetadata cm; - EXPECT_FALSE(cm.IsConditional()); - - cm = loot::ConditionalMetadata("condition"); - EXPECT_TRUE(cm.IsConditional()); -} - -TEST_F(ConditionalMetadata, EvalCondition) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - loot::ConditionalMetadata cm; - EXPECT_TRUE(cm.EvalCondition(game)); - - cm = loot::ConditionalMetadata("condition"); - EXPECT_THROW(cm.EvalCondition(game), loot::error); - - cm = loot::ConditionalMetadata("file(\"Blank.esm\")"); - EXPECT_TRUE(cm.EvalCondition(game)); - - cm = loot::ConditionalMetadata("file(\"Blank.missing.esm\")"); - EXPECT_FALSE(cm.EvalCondition(game)); -} - -TEST_F(ConditionalMetadata, ParseCondition) { - loot::ConditionalMetadata cm; - EXPECT_NO_THROW(cm.ParseCondition()); - - cm = loot::ConditionalMetadata("condition"); - EXPECT_THROW(cm.ParseCondition(), loot::error); - - // Check that invalid regex also throws. - cm = loot::ConditionalMetadata("regex(\"RagnvaldBook(Farengar(+Ragnvald)?)?\\.esp\")"); - EXPECT_THROW(cm.ParseCondition(), loot::error); - - cm = loot::ConditionalMetadata("file(\"Blank.esm\")"); - EXPECT_NO_THROW(cm.ParseCondition()); - - cm = loot::ConditionalMetadata("file(\"Blank.missing.esm\")"); - EXPECT_NO_THROW(cm.ParseCondition()); -} - -#endif diff --git a/src/tests/backend/metadata/test_file.h b/src/tests/backend/metadata/test_file.h deleted file mode 100644 index 65ede729..00000000 --- a/src/tests/backend/metadata/test_file.h +++ /dev/null @@ -1,178 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_FILE -#define LOOT_TEST_BACKEND_METADATA_FILE - -#include "backend/metadata/file.h" -#include "tests/fixtures.h" - -using loot::File; - -TEST(File, ConstructorsAndDataAccess) { - File file; - EXPECT_EQ("", file.Name()); - EXPECT_EQ("", file.DisplayName()); - EXPECT_EQ("", file.Condition()); - - file = File("name"); - EXPECT_EQ("name", file.Name()); - EXPECT_EQ("name", file.DisplayName()); - EXPECT_EQ("", file.Condition()); - - file = File("name", "display"); - EXPECT_EQ("name", file.Name()); - EXPECT_EQ("display", file.DisplayName()); - EXPECT_EQ("", file.Condition()); - - // Not a valid condition, but not evaluating it in this test. - file = File("name", "display", "condition"); - EXPECT_EQ("name", file.Name()); - EXPECT_EQ("display", file.DisplayName()); - EXPECT_EQ("condition", file.Condition()); -} - -TEST(File, EqualityOperator) { - File file1, file2; - EXPECT_TRUE(file1 == file2); - - // Not valid conditions, but not evaluating them in this test. - file1 = File("name", "display1", "condition1"); - file2 = File("name", "display2", "condition2"); - EXPECT_TRUE(file1 == file2); - - file1 = File("name1"); - file2 = File("name2"); - EXPECT_FALSE(file1 == file2); -} - -TEST(File, LessThanOperator) { - File file1, file2; - EXPECT_FALSE(file1 < file2); - EXPECT_FALSE(file2 < file1); - - file1 = File("name", "display1", "condition1"); - file2 = File("name", "display2", "condition2"); - EXPECT_FALSE(file1 < file2); - EXPECT_FALSE(file2 < file1); - - file1 = File("name1"); - file2 = File("name2"); - EXPECT_TRUE(file1 < file2); - EXPECT_FALSE(file2 < file1); -} - -TEST(File, YamlEmitter) { - File file("name1", "display1", "condition1"); - - YAML::Emitter e1; - e1 << file; - EXPECT_STREQ("name: 'name1'\ncondition: 'condition1'\ndisplay: 'display1'", e1.c_str()); - - file = File("name1"); - YAML::Emitter e2; - e2 << file; - EXPECT_STREQ("'name1'", e2.c_str()); - - file = File("name1", "", "condition1"); - YAML::Emitter e3; - e3 << file; - EXPECT_STREQ("name: 'name1'\ncondition: 'condition1'", e3.c_str()); - - file = File("name1", "display1"); - YAML::Emitter e4; - e4 << file; - EXPECT_STREQ("name: 'name1'\ndisplay: 'display1'", e4.c_str()); - - file = File("name1", "name1"); - YAML::Emitter e5; - e5 << file; - EXPECT_STREQ("'name1'", e5.c_str()); - - file = File("name1", "name1", "condition1"); - YAML::Emitter e6; - e6 << file; - EXPECT_STREQ("name: 'name1'\ncondition: 'condition1'", e6.c_str()); -} - -TEST(File, YamlEncode) { - File file("name1", "display1", "condition1"); - YAML::Node node; - node = file; - EXPECT_EQ("name1", node["name"].as()); - EXPECT_EQ("display1", node["display"].as()); - EXPECT_EQ("condition1", node["condition"].as()); - - file = File("name1"); - node = file; - EXPECT_EQ("name1", node["name"].as()); - EXPECT_FALSE(node["display"]); - EXPECT_FALSE(node["condition"]); - - file = File("name1", "name1"); - node = file; - EXPECT_EQ("name1", node["name"].as()); - EXPECT_FALSE(node["display"]); - EXPECT_FALSE(node["condition"]); - - file = File("name1", "display1"); - node = file; - EXPECT_EQ("name1", node["name"].as()); - EXPECT_EQ("display1", node["display"].as()); - EXPECT_FALSE(node["condition"]); -} - -TEST(File, YamlDecode) { - YAML::Node node = YAML::Load("{name: name1, display: display1, condition: 'file(\"Foo.esp\")'}"); - File file = node.as(); - EXPECT_EQ("name1", file.Name()); - EXPECT_EQ("display1", file.DisplayName()); - EXPECT_EQ("file(\"Foo.esp\")", file.Condition()); - - node = YAML::Load("name1"); - file = node.as(); - EXPECT_EQ("name1", file.Name()); - EXPECT_EQ("name1", file.DisplayName()); - EXPECT_EQ("", file.Condition()); - - node = YAML::Load("{name: name1, display: display1}"); - file = node.as(); - EXPECT_EQ("name1", file.Name()); - EXPECT_EQ("display1", file.DisplayName()); - EXPECT_EQ("", file.Condition()); - - node = YAML::Load("{name: name1, condition: 'file(\"Foo.esp\")'}"); - file = node.as(); - EXPECT_EQ("name1", file.Name()); - EXPECT_EQ("name1", file.DisplayName()); - EXPECT_EQ("file(\"Foo.esp\")", file.Condition()); - - node = YAML::Load("{name: name1, condition: invalid}"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_ANY_THROW(node.as()); -} - -#endif diff --git a/src/tests/backend/metadata/test_location.h b/src/tests/backend/metadata/test_location.h deleted file mode 100644 index 2a25d5d0..00000000 --- a/src/tests/backend/metadata/test_location.h +++ /dev/null @@ -1,127 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_LOCATION -#define LOOT_TEST_BACKEND_METADATA_LOCATION - -#include "backend/metadata/location.h" -#include "tests/fixtures.h" - -using loot::Location; - -TEST(Location, ConstructorsAndDataAccess) { - Location loc; - EXPECT_EQ("", loc.URL()); - - loc = Location("http://www.example.com"); - EXPECT_EQ("http://www.example.com", loc.URL()); - - loc = Location("http://www.example.com", "example"); - EXPECT_EQ("http://www.example.com", loc.URL()); - EXPECT_EQ("example", loc.Name()); -} - -TEST(Location, EqualityOperator) { - Location loc1, loc2; - EXPECT_TRUE(loc1 == loc2); - - loc1 = Location("http://www.example.com"); - loc2 = Location("HTTP://WWW.EXAMPLE.COM"); - EXPECT_TRUE(loc1 == loc2); - - loc1 = Location("http://www.example.com", "example1"); - loc2 = Location("http://www.example.com", "example2"); - EXPECT_TRUE(loc1 == loc2); - - loc1 = Location("http://www.example1.com"); - loc2 = Location("http://www.example2.com"); - EXPECT_FALSE(loc1 == loc2); -} - -TEST(Location, LessThanOperator) { - Location loc1, loc2; - EXPECT_FALSE(loc1 < loc2); - EXPECT_FALSE(loc2 < loc1); - - loc1 = Location("http://www.example.com"); - loc2 = Location("HTTP://WWW.EXAMPLE.COM"); - EXPECT_FALSE(loc1 < loc2); - EXPECT_FALSE(loc2 < loc1); - - loc1 = Location("http://www.example.com", "example1"); - loc2 = Location("http://www.example.com", "example2"); - EXPECT_FALSE(loc1 < loc2); - EXPECT_FALSE(loc2 < loc1); - - loc1 = Location("http://www.example1.com"); - loc2 = Location("http://www.example2.com"); - EXPECT_TRUE(loc1 < loc2); - EXPECT_FALSE(loc2 < loc1); -} - -TEST(Location, YamlEmitter) { - Location loc("http://www.example.com"); - YAML::Emitter e1; - e1 << loc; - EXPECT_STREQ("'http://www.example.com'", e1.c_str()); - - loc = Location("http://www.example.com", "example"); - YAML::Emitter e2; - e2 << loc; - EXPECT_STREQ("link: 'http://www.example.com'\nname: 'example'", e2.c_str()); -} - -TEST(Location, YamlEncode) { - YAML::Node node; - - Location loc("http://www.example.com"); - node = loc; - EXPECT_EQ("http://www.example.com", node["link"].as()); - EXPECT_FALSE(node["name"]); - - loc = Location("http://www.example.com", "example"); - node = loc; - EXPECT_EQ("http://www.example.com", node["link"].as()); - EXPECT_EQ("example", node["name"].as()); -} - -TEST(Location, YamlDecode) { - YAML::Node node; - Location loc; - - node = YAML::Load("http://www.example.com"); - loc = node.as(); - EXPECT_EQ("http://www.example.com", loc.URL()); - EXPECT_EQ("", loc.Name()); - - node = YAML::Load("{link: http://www.example.com, name: example}"); - loc = node.as(); - EXPECT_EQ("http://www.example.com", loc.URL()); - EXPECT_EQ("example", loc.Name()); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_ANY_THROW(node.as()); -} - -#endif diff --git a/src/tests/backend/metadata/test_message.h b/src/tests/backend/metadata/test_message.h deleted file mode 100644 index 7d379c0a..00000000 --- a/src/tests/backend/metadata/test_message.h +++ /dev/null @@ -1,420 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_MESSAGE -#define LOOT_TEST_BACKEND_METADATA_MESSAGE - -#include "backend/metadata/message.h" -#include "tests/fixtures.h" - -class Message : public SkyrimTest {}; - -using loot::MessageContent; -using loot::Language; - -typedef std::vector MessageContents; - -TEST_F(Message, ConstructorsAndDataAccess) { - loot::Message message; - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents(), message.Content()); - - message = loot::Message(loot::Message::say, "content1", "condition1"); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({ - MessageContent("content1", Language::english) - }), message.Content()); - EXPECT_EQ("condition1", message.Condition()); - - MessageContents mc({MessageContent("content1", Language::english)}); - message = loot::Message(loot::Message::say, mc, "condition1"); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(mc, message.Content()); - EXPECT_EQ("condition1", message.Condition()); -} - -TEST_F(Message, EqualityOperator) { - loot::Message message1, message2; - EXPECT_TRUE(message1 == message2); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, "content1", "condition2"); - EXPECT_TRUE(message1 == message2); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, "content2", "condition1"); - EXPECT_FALSE(message1 == message2); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::warn, "content1", "condition1"); - EXPECT_TRUE(message1 == message2); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - EXPECT_TRUE(message1 == message2); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content2", Language::english)}), "condition1"); - EXPECT_FALSE(message1 == message2); - - message1 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - EXPECT_TRUE(message1 == message2); - - message1 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content2", Language::english)}), "condition1"); - EXPECT_FALSE(message1 == message2); - - message1 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::french)}), "condition1"); - EXPECT_TRUE(message1 == message2); -} - -TEST_F(Message, LessThanOperator) { - loot::Message message1, message2; - EXPECT_FALSE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, "content1", "condition1"); - EXPECT_FALSE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, "content1", "condition2"); - EXPECT_FALSE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::warn, "content1", "condition1"); - EXPECT_FALSE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, "", "condition1"); - message2 = loot::Message(loot::Message::say, "content1", "condition1"); - EXPECT_TRUE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, "", "condition1"); - EXPECT_FALSE(message1 < message2); - EXPECT_TRUE(message2 < message1); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - EXPECT_FALSE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, "content1", "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content2", Language::english)}), "condition1"); - EXPECT_TRUE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - EXPECT_FALSE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content2", Language::english)}), "condition1"); - EXPECT_TRUE(message1 < message2); - EXPECT_FALSE(message2 < message1); - - message1 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::english)}), "condition1"); - message2 = loot::Message(loot::Message::say, MessageContents({MessageContent("content1", Language::french)}), "condition1"); - EXPECT_FALSE(message1 < message2); - EXPECT_FALSE(message2 < message1); -} - -TEST_F(Message, EvalCondition) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - loot::Message message; - EXPECT_TRUE(message.EvalCondition(game, Language::any)); - EXPECT_EQ(1, message.Content().size()); - - message = loot::Message(loot::Message::say, MessageContents({ - MessageContent("content1", Language::german), - MessageContent("content1", Language::english), - MessageContent("content1", Language::french), - })); - EXPECT_TRUE(message.EvalCondition(game, Language::french)); - EXPECT_EQ(1, message.Content().size()); -} - -TEST_F(Message, ChooseContent) { - MessageContent mc; - loot::Message message; - EXPECT_EQ(mc, message.ChooseContent(Language::any)); - EXPECT_EQ(mc, message.ChooseContent(Language::french)); - EXPECT_EQ(mc, message.ChooseContent(Language::english)); - - mc = MessageContent("content1", Language::english); - message = loot::Message(loot::Message::say, "content1"); - EXPECT_EQ(mc, message.ChooseContent(Language::any)); - EXPECT_EQ(mc, message.ChooseContent(Language::french)); - EXPECT_EQ(mc, message.ChooseContent(Language::english)); - - mc = MessageContent("content1", Language::english); - message = loot::Message(loot::Message::say, MessageContents({mc})); - EXPECT_EQ(mc, message.ChooseContent(Language::any)); - EXPECT_EQ(mc, message.ChooseContent(Language::french)); - EXPECT_EQ(mc, message.ChooseContent(Language::english)); - - mc = MessageContent("content1", Language::english); - message = loot::Message(loot::Message::say, MessageContents({ - MessageContent("content1", Language::english), - MessageContent("content1", Language::german), - })); - EXPECT_EQ(mc, message.ChooseContent(Language::any)); - EXPECT_EQ(mc, message.ChooseContent(Language::french)); - EXPECT_EQ(mc, message.ChooseContent(Language::english)); - - message = loot::Message(loot::Message::say, MessageContents({ - MessageContent("content1", Language::german), - MessageContent("content1", Language::english), - MessageContent("content1", Language::french), - })); - EXPECT_EQ(MessageContent("content1", Language::german), message.ChooseContent(Language::any)); - EXPECT_EQ(MessageContent("content1", Language::french), message.ChooseContent(Language::french)); - EXPECT_EQ(MessageContent("content1", Language::english), message.ChooseContent(Language::english)); - - mc = MessageContent("content1", Language::german); - message = loot::Message(loot::Message::say, MessageContents({mc})); - EXPECT_EQ(mc, message.ChooseContent(Language::any)); - EXPECT_EQ(mc, message.ChooseContent(Language::french)); -} - -TEST_F(Message, YamlEmitter) { - loot::Message message(loot::Message::say, "content1"); - YAML::Emitter e1; - e1 << message; - EXPECT_STREQ("type: say\n" - "content: 'content1'", e1.c_str()); - - message = loot::Message(loot::Message::warn, "content1"); - YAML::Emitter e2; - e2 << message; - EXPECT_STREQ("type: warn\n" - "content: 'content1'", e2.c_str()); - - message = loot::Message(loot::Message::error, "content1"); - YAML::Emitter e3; - e3 << message; - EXPECT_STREQ("type: error\n" - "content: 'content1'", e3.c_str()); - - message = loot::Message(loot::Message::say, "content1", "condition1"); - YAML::Emitter e4; - e4 << message; - EXPECT_STREQ("type: say\n" - "content: 'content1'\n" - "condition: 'condition1'", e4.c_str()); - - message = loot::Message(loot::Message::say, MessageContents({ - MessageContent("content1", Language::english), - })); - YAML::Emitter e5; - e5 << message; - EXPECT_STREQ("type: say\n" - "content: 'content1'", e5.c_str()); - - message = loot::Message(loot::Message::say, MessageContents({ - MessageContent("content1", Language::english), - MessageContent("content2", Language::german) - })); - YAML::Emitter e6; - e6 << message; - EXPECT_STREQ("type: say\n" - "content:\n" - " - lang: en\n" - " str: 'content1'\n" - " - lang: de\n" - " str: 'content2'", e6.c_str()); -} - -TEST_F(Message, YamlEncode) { - YAML::Node node; - - MessageContents mcs({MessageContent("content1", Language::english)}); - loot::Message message(loot::Message::say, "content1"); - node = message; - EXPECT_EQ("say", node["type"].as()); - EXPECT_EQ(mcs, node["content"].as()); - EXPECT_FALSE(node["condition"]); - - message = loot::Message(loot::Message::warn, "content1"); - node = message; - EXPECT_EQ("warn", node["type"].as()); - EXPECT_EQ(mcs, node["content"].as()); - EXPECT_FALSE(node["condition"]); - - message = loot::Message(loot::Message::error, "content1"); - node = message; - EXPECT_EQ("error", node["type"].as()); - EXPECT_EQ(mcs, node["content"].as()); - EXPECT_FALSE(node["condition"]); - - message = loot::Message(loot::Message::say, "content1", "condition1"); - node = message; - EXPECT_EQ("say", node["type"].as()); - EXPECT_EQ(mcs, node["content"].as()); - EXPECT_EQ("condition1", node["condition"].as()); - - mcs = MessageContents({ - MessageContent("content1", Language::english), - MessageContent("content2", Language::french), - }); - message = loot::Message(loot::Message::say, mcs); - node = message; - EXPECT_EQ("say", node["type"].as()); - EXPECT_EQ(mcs, node["content"].as()); - EXPECT_FALSE(node["condition"]); -} - -TEST_F(Message, YamlDecode) { - YAML::Node node = YAML::Load("type: say\n" - "content: content1"); - loot::Message message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("content1", Language::english)}), message.Content()); - EXPECT_EQ("", message.Condition()); - - node = YAML::Load("type: warn\n" - "content: content1"); - message = node.as(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("content1", Language::english)}), message.Content()); - EXPECT_EQ("", message.Condition()); - - node = YAML::Load("type: error\n" - "content: content1"); - message = node.as(); - EXPECT_EQ(loot::Message::error, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("content1", Language::english)}), message.Content()); - EXPECT_EQ("", message.Condition()); - - node = YAML::Load("type: invalid\n" - "content: content1"); - message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("content1", Language::english)}), message.Content()); - EXPECT_EQ("", message.Condition()); - - node = YAML::Load("type: say\n" - "content: content1\n" - "condition: 'file(\"Foo.esp\")'"); - message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("content1", Language::english)}), message.Content()); - EXPECT_EQ("file(\"Foo.esp\")", message.Condition()); - - node = YAML::Load("type: say\n" - "content:\n" - " - lang: en\n" - " str: content1\n" - " - lang: de\n" - " str: content2"); - message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({ - MessageContent("content1", Language::english), - MessageContent("content2", Language::german), - }), message.Content()); - EXPECT_EQ("", message.Condition()); - - node = YAML::Load("type: say\n" - "content:\n" - " - lang: fr\n" - " str: content1"); - message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("content1", Language::french)}), message.Content()); - EXPECT_EQ("", message.Condition()); - - // Throw because no English string is given in a multilingual message. - node = YAML::Load("type: say\n" - "content:\n" - " - lang: de\n" - " str: content1\n" - " - lang: fr\n" - " str: content2"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - node = YAML::Load("type: say\n" - "content: con%1%tent1\n" - "subs:\n" - " - sub1"); - message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("consub1tent1", Language::english)}), message.Content()); - EXPECT_EQ("", message.Condition()); - - // Check that subs apply to all languages of a multilingual message. - node = YAML::Load("type: say\n" - "content:\n" - " - lang: en\n" - " str: content1 %1%\n" - " - lang: de\n" - " str: content2 %1%\n" - "subs:\n" - " - sub"); - message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({ - MessageContent("content1 sub", Language::english), - MessageContent("content2 sub", Language::german), - }), message.Content()); - EXPECT_EQ("", message.Condition()); - - // Throw because there aren't the same number of subs as referred to in the content string. - node = YAML::Load("type: say\n" - "content: '%1% %2%'\n" - "subs:\n" - " - sub1"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - // Don't throw because no subs are given, so none are expected in the content string. - node = YAML::Load("type: say\n" - "content: con%1%tent1\n"); - message = node.as(); - EXPECT_EQ(loot::Message::say, message.Type()); - EXPECT_EQ(MessageContents({MessageContent("con%1%tent1", Language::english)}), message.Content()); - EXPECT_EQ("", message.Condition()); - - node = YAML::Load("type: say\n" - "content: content1\n" - "condition: invalid"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - node = YAML::Load("scalar"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -#endif diff --git a/src/tests/backend/metadata/test_message_content.h b/src/tests/backend/metadata/test_message_content.h deleted file mode 100644 index dba1ff40..00000000 --- a/src/tests/backend/metadata/test_message_content.h +++ /dev/null @@ -1,111 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_MESSAGE_CONTENT -#define LOOT_TEST_BACKEND_METADATA_MESSAGE_CONTENT - -#include "backend/metadata/message_content.h" -#include "tests/fixtures.h" - -using loot::Language; -using loot::MessageContent; - -TEST(MessageContent, ConstructorsAndDataAccess) { - MessageContent mc; - EXPECT_EQ("", mc.Str()); - EXPECT_EQ(Language::english, mc.Language()); - - mc = MessageContent("content", Language::french); - EXPECT_EQ("content", mc.Str()); - EXPECT_EQ(Language::french, mc.Language()); -} - -TEST(MessageContent, EqualityOperator) { - MessageContent mc1, mc2; - EXPECT_TRUE(mc1 == mc2); - - mc1 = MessageContent("content", Language::french); - mc2 = MessageContent("Content", Language::french); - EXPECT_TRUE(mc1 == mc2); - - mc1 = MessageContent("content1", Language::french); - mc2 = MessageContent("content2", Language::french); - EXPECT_FALSE(mc1 == mc2); - - mc1 = MessageContent("content", Language::english); - mc2 = MessageContent("Content", Language::french); - EXPECT_TRUE(mc1 == mc2); -} - -TEST(MessageContent, LessThanOperator) { - MessageContent mc1, mc2; - EXPECT_FALSE(mc1 < mc2); - EXPECT_FALSE(mc2 < mc1); - - mc1 = MessageContent("content", Language::french); - mc2 = MessageContent("Content", Language::french); - EXPECT_FALSE(mc1 < mc2); - EXPECT_FALSE(mc2 < mc1); - - mc1 = MessageContent("content", Language::english); - mc2 = MessageContent("content", Language::french); - EXPECT_FALSE(mc1 < mc2); - EXPECT_FALSE(mc2 < mc1); - - mc1 = MessageContent("content1", Language::english); - mc2 = MessageContent("content2", Language::english); - EXPECT_TRUE(mc1 < mc2); - EXPECT_FALSE(mc2 < mc1); -} - -TEST(MessageContent, YamlEmitter) { - MessageContent mc("content", Language::french); - YAML::Emitter e1; - e1 << mc; - EXPECT_STREQ("lang: fr\nstr: 'content'", e1.c_str()); -} - -TEST(MessageContent, YamlEncode) { - YAML::Node node; - - MessageContent mc("content", Language::french); - node = mc; - EXPECT_EQ("content", node["str"].as()); - EXPECT_EQ("fr", node["lang"].as()); -} - -TEST(MessageContent, YamlDecode) { - YAML::Node node = YAML::Load("{str: content, lang: de}"); - MessageContent mc = node.as(); - EXPECT_EQ("content", mc.Str()); - EXPECT_EQ(Language::german, mc.Language()); - - node = YAML::Load("scalar"); - EXPECT_ANY_THROW(node.as()); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_ANY_THROW(node.as()); -} - -#endif diff --git a/src/tests/backend/metadata/test_plugin_dirty_info.h b/src/tests/backend/metadata/test_plugin_dirty_info.h deleted file mode 100644 index 3cbd248e..00000000 --- a/src/tests/backend/metadata/test_plugin_dirty_info.h +++ /dev/null @@ -1,239 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_PLUGIN_DIRTY_INFO -#define LOOT_TEST_BACKEND_METADATA_PLUGIN_DIRTY_INFO - -#include "backend/metadata/plugin_dirty_info.h" -#include "tests/fixtures.h" - -class PluginDirtyInfo : public SkyrimTest {}; - -TEST_F(PluginDirtyInfo, ConstructorsAndDataAccess) { - loot::PluginDirtyInfo info; - EXPECT_EQ(0, info.CRC()); - EXPECT_EQ(0, info.ITMs()); - EXPECT_EQ(0, info.DeletedRefs()); - EXPECT_EQ(0, info.DeletedNavmeshes()); - EXPECT_EQ("", info.CleaningUtility()); - - info = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner"); - EXPECT_EQ(0x12345678, info.CRC()); - EXPECT_EQ(2, info.ITMs()); - EXPECT_EQ(10, info.DeletedRefs()); - EXPECT_EQ(30, info.DeletedNavmeshes()); - EXPECT_EQ("cleaner", info.CleaningUtility()); -} - -TEST_F(PluginDirtyInfo, MessageOutput) { - loot::Message message; - - message = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Contains 2 ITM records, 10 deleted references and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str()); - - message = loot::PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Clean with cleaner.", message.ChooseContent(Language::any).Str()); - - message = loot::PluginDirtyInfo(0x12345678, 0, 10, 30, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Contains 10 deleted references and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str()); - - message = loot::PluginDirtyInfo(0x12345678, 0, 0, 30, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Contains 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str()); - - message = loot::PluginDirtyInfo(0x12345678, 0, 10, 0, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Contains 10 deleted references. Clean with cleaner.", message.ChooseContent(Language::any).Str()); - - message = loot::PluginDirtyInfo(0x12345678, 2, 0, 30, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Contains 2 ITM records and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str()); - - message = loot::PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Contains 2 ITM records. Clean with cleaner.", message.ChooseContent(Language::any).Str()); - - message = loot::PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner").AsMessage(); - EXPECT_EQ(loot::Message::warn, message.Type()); - EXPECT_EQ("Contains 2 ITM records and 10 deleted references. Clean with cleaner.", message.ChooseContent(Language::any).Str()); -} - -TEST_F(PluginDirtyInfo, EqualityOperator) { - loot::PluginDirtyInfo info1, info2; - EXPECT_TRUE(info1 == info2); - - info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner1"); - info2 = loot::PluginDirtyInfo(0x12345678, 4, 20, 60, "cleaner2"); - EXPECT_TRUE(info1 == info2); - - info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner"); - info2 = loot::PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner"); - EXPECT_FALSE(info1 == info2); -} - -TEST_F(PluginDirtyInfo, LessThanOperator) { - loot::PluginDirtyInfo info1, info2; - EXPECT_FALSE(info1 < info2); - EXPECT_FALSE(info2 < info1); - - info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner1"); - info2 = loot::PluginDirtyInfo(0x12345678, 4, 20, 60, "cleaner2"); - EXPECT_FALSE(info1 < info2); - EXPECT_FALSE(info2 < info1); - - info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner"); - info2 = loot::PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner"); - EXPECT_TRUE(info1 < info2); - EXPECT_FALSE(info2 < info1); -} - -TEST_F(PluginDirtyInfo, EvalConditionTrue) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - loot::PluginDirtyInfo dirtyInfo = loot::PluginDirtyInfo(0x24F0E2A1, 2, 10, 30, "cleaner"); - EXPECT_TRUE(dirtyInfo.EvalCondition(game, "Blank.esp")); -} - -TEST_F(PluginDirtyInfo, EvalConditionFalse) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - loot::PluginDirtyInfo dirtyInfo; - EXPECT_FALSE(dirtyInfo.EvalCondition(game, "")); - - dirtyInfo = loot::PluginDirtyInfo(0xDEADBEEF, 2, 10, 30, "cleaner"); - EXPECT_FALSE(dirtyInfo.EvalCondition(game, "Blank.esp")); -} - -TEST_F(PluginDirtyInfo, YamlEmitter) { - loot::PluginDirtyInfo info; - - info = loot::PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner"); - YAML::Emitter e1; - e1 << info; - EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'", e1.c_str()); - - info = loot::PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner"); - YAML::Emitter e2; - e2 << info; - EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\nitm: 2", e2.c_str()); - - info = loot::PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner"); - YAML::Emitter e3; - e3 << info; - EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\nitm: 2\nudr: 10", e3.c_str()); - - info = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner"); - YAML::Emitter e4; - e4 << info; - EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\nitm: 2\nudr: 10\nnav: 30", e4.c_str()); -} - -TEST_F(PluginDirtyInfo, YamlEncode) { - YAML::Node node; - loot::PluginDirtyInfo info; - - info = loot::PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner"); - node = info; - EXPECT_EQ(0x12345678, node["crc"].as()); - EXPECT_EQ("cleaner", node["util"].as()); - EXPECT_FALSE(node["itm"]); - EXPECT_FALSE(node["udr"]); - EXPECT_FALSE(node["nav"]); - - info = loot::PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner"); - node = info; - EXPECT_EQ(0x12345678, node["crc"].as()); - EXPECT_EQ("cleaner", node["util"].as()); - EXPECT_EQ(2, node["itm"].as()); - EXPECT_FALSE(node["udr"]); - EXPECT_FALSE(node["nav"]); - - info = loot::PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner"); - node = info; - EXPECT_EQ(0x12345678, node["crc"].as()); - EXPECT_EQ("cleaner", node["util"].as()); - EXPECT_EQ(2, node["itm"].as()); - EXPECT_EQ(10, node["udr"].as()); - EXPECT_FALSE(node["nav"]); - - info = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner"); - node = info; - EXPECT_EQ(0x12345678, node["crc"].as()); - EXPECT_EQ("cleaner", node["util"].as()); - EXPECT_EQ(2, node["itm"].as()); - EXPECT_EQ(10, node["udr"].as()); - EXPECT_EQ(30, node["nav"].as()); -} - -TEST_F(PluginDirtyInfo, YamlDecode) { - YAML::Node node; - loot::PluginDirtyInfo info; - - node = YAML::Load("{crc: 0x12345678, util: cleaner}"); - info = node.as(); - EXPECT_EQ(0x12345678, info.CRC()); - EXPECT_EQ(0, info.ITMs()); - EXPECT_EQ(0, info.DeletedRefs()); - EXPECT_EQ(0, info.DeletedNavmeshes()); - EXPECT_EQ("cleaner", info.CleaningUtility()); - - node = YAML::Load("{crc: 0x12345678, util: cleaner, itm: 2}"); - info = node.as(); - EXPECT_EQ(0x12345678, info.CRC()); - EXPECT_EQ(2, info.ITMs()); - EXPECT_EQ(0, info.DeletedRefs()); - EXPECT_EQ(0, info.DeletedNavmeshes()); - EXPECT_EQ("cleaner", info.CleaningUtility()); - - node = YAML::Load("{crc: 0x12345678, util: cleaner, itm: 2, udr: 10}"); - info = node.as(); - EXPECT_EQ(0x12345678, info.CRC()); - EXPECT_EQ(2, info.ITMs()); - EXPECT_EQ(10, info.DeletedRefs()); - EXPECT_EQ(0, info.DeletedNavmeshes()); - EXPECT_EQ("cleaner", info.CleaningUtility()); - - node = YAML::Load("{crc: 0x12345678, util: cleaner, itm: 2, udr: 10, nav: 30}"); - info = node.as(); - EXPECT_EQ(0x12345678, info.CRC()); - EXPECT_EQ(2, info.ITMs()); - EXPECT_EQ(10, info.DeletedRefs()); - EXPECT_EQ(30, info.DeletedNavmeshes()); - EXPECT_EQ("cleaner", info.CleaningUtility()); - - node = YAML::Load("scalar"); - EXPECT_ANY_THROW(node.as()); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_ANY_THROW(node.as()); -} - -#endif diff --git a/src/tests/backend/metadata/test_plugin_metadata.h b/src/tests/backend/metadata/test_plugin_metadata.h deleted file mode 100644 index 8353e2de..00000000 --- a/src/tests/backend/metadata/test_plugin_metadata.h +++ /dev/null @@ -1,949 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_F_BACKEND_METADATA_PLUGIN_METADATA -#define LOOT_TEST_F_BACKEND_METADATA_PLUGIN_METADATA - -#include "backend/metadata/plugin_metadata.h" -#include "tests/fixtures.h" - -class PluginMetadata : public SkyrimTest {}; - -TEST_F(PluginMetadata, Constructors) { - loot::PluginMetadata pm; - EXPECT_TRUE(pm.Enabled()); - EXPECT_FALSE(pm.IsPriorityExplicit()); - EXPECT_FALSE(pm.IsPriorityGlobal()); - EXPECT_EQ(0, pm.Priority()); - - pm = loot::PluginMetadata("Blank.esm"); - EXPECT_EQ("Blank.esm", pm.Name()); - EXPECT_TRUE(pm.Enabled()); - EXPECT_FALSE(pm.IsPriorityExplicit()); - EXPECT_FALSE(pm.IsPriorityGlobal()); - EXPECT_EQ(0, pm.Priority()); -} - -TEST_F(PluginMetadata, EqualityOperator) { - loot::PluginMetadata pm1, pm2; - EXPECT_TRUE(pm1 == pm2); - - pm1 = loot::PluginMetadata("Blank.esm"); - pm2 = loot::PluginMetadata("blank.esm"); - EXPECT_TRUE(pm1 == pm2); - - pm1 = loot::PluginMetadata("Blank.esm"); - pm2 = loot::PluginMetadata("Blan.\\.esm"); - EXPECT_TRUE(pm1 == pm2); - EXPECT_TRUE(pm2 == pm1); - - pm1 = loot::PluginMetadata("Blan.esm"); - pm2 = loot::PluginMetadata("Blan.\\.esm"); - EXPECT_FALSE(pm1 == pm2); - EXPECT_FALSE(pm2 == pm1); - - pm1 = loot::PluginMetadata("Blan.\\.esm"); - pm2 = loot::PluginMetadata("Blan.\\.esm"); - EXPECT_TRUE(pm1 == pm2); - EXPECT_TRUE(pm2 == pm1); - - pm1 = loot::PluginMetadata("Blan(k|p).esm"); - pm2 = loot::PluginMetadata("Blan.\\.esm"); - EXPECT_FALSE(pm1 == pm2); - EXPECT_FALSE(pm2 == pm1); -} - -TEST_F(PluginMetadata, MergeMetadata) { - loot::PluginMetadata pm1(YAML::Load( - "name: 'Blank.esp'\n" - "enabled: false\n" - "priority: 5\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - "tag:\n" - " - Relev\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'" - ).as()); - - loot::PluginMetadata pm2(YAML::Load( - "name: 'Blank - Different.esp'\n" - "after:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "req:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "inc:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - "tag:\n" - " - Relev\n" - " - -Relev\n" - " - Delev\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - " - crc: 0x9\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'\n" - " - 'http://www.example2.com'" - ).as()); - - EXPECT_NO_THROW(pm1.MergeMetadata(pm2)); - EXPECT_EQ("Blank.esp", pm1.Name()); - EXPECT_TRUE(pm1.Enabled()); - EXPECT_EQ(5, pm1.Priority()); - EXPECT_TRUE(pm1.IsPriorityExplicit()); - EXPECT_FALSE(pm1.IsPriorityGlobal()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm"), - loot::File("Blank.esp"), - }), pm1.LoadAfter()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm"), - loot::File("Blank.esp"), - }), pm1.Reqs()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm"), - loot::File("Blank.esp"), - }), pm1.Incs()); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "content"), - loot::Message(loot::Message::say, "content"), - }), pm1.Messages()); - EXPECT_EQ(std::set({ - loot::Tag("Relev"), - loot::Tag("Relev", false), - loot::Tag("Delev"), - }), pm1.Tags()); - EXPECT_EQ(std::set({ - loot::PluginDirtyInfo(5, 0, 1, 2, "utility"), - loot::PluginDirtyInfo(9, 0, 1, 2, "utility"), - }), pm1.DirtyInfo()); - EXPECT_EQ(std::set({ - loot::Location("http://www.example.com"), - loot::Location("http://www.example2.com"), - }), pm1.Locations()); - - pm2.SetPriorityExplicit(true); - EXPECT_NO_THROW(pm1.MergeMetadata(pm2)); - EXPECT_EQ(0, pm1.Priority()); - EXPECT_TRUE(pm1.IsPriorityExplicit()); - EXPECT_FALSE(pm1.IsPriorityGlobal()); -} - -TEST_F(PluginMetadata, DiffMetadata) { - loot::PluginMetadata pm1(YAML::Load( - "name: 'Blank.esp'\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - " - 'Blank - Different.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - " - 'Blank - Different.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - " - 'Blank - Different.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - " - type: say\n" - " content: 'content2'\n" - "tag:\n" - " - Relev\n" - " - NoMerge\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - " - crc: 0x1\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'\n" - " - 'http://www.other-example.com'" - ).as()); - - loot::PluginMetadata pm2(YAML::Load( - "name: 'Blank - Different.esp'\n" - "after:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "req:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "inc:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - " - type: say\n" - " content: 'content3'\n" - "tag:\n" - " - Relev\n" - " - -Relev\n" - " - Delev\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - " - crc: 0x9\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'\n" - " - 'http://www.example2.com'" - ).as()); - - loot::PluginMetadata result = pm1.DiffMetadata(pm2); - EXPECT_EQ("Blank.esp", result.Name()); - EXPECT_FALSE(result.Enabled()); - EXPECT_EQ(0, result.Priority()); - EXPECT_FALSE(result.IsPriorityExplicit()); - EXPECT_FALSE(result.IsPriorityGlobal()); - EXPECT_EQ(std::set({ - loot::File("Blank.esp"), - loot::File("Blank - Different.esm"), - }), result.LoadAfter()); - EXPECT_EQ(std::set({ - loot::File("Blank.esp"), - loot::File("Blank - Different.esm"), - }), result.Reqs()); - EXPECT_EQ(std::set({ - loot::File("Blank.esp"), - loot::File("Blank - Different.esm"), - }), result.Incs()); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "content2"), - loot::Message(loot::Message::say, "content3"), - }), result.Messages()); - EXPECT_EQ(std::set({ - loot::Tag("Relev", false), - loot::Tag("Delev"), - loot::Tag("NoMerge"), - }), result.Tags()); - EXPECT_EQ(std::set({ - loot::PluginDirtyInfo(9, 0, 1, 2, "utility"), - loot::PluginDirtyInfo(1, 0, 1, 2, "utility"), - }), result.DirtyInfo()); - EXPECT_EQ(std::set({ - loot::Location("http://www.example2.com"), - loot::Location("http://www.other-example.com"), - }), result.Locations()); - - pm1.Priority(5); - result = pm1.DiffMetadata(pm2); - - EXPECT_EQ(5, result.Priority()); - EXPECT_TRUE(result.IsPriorityExplicit()); - EXPECT_FALSE(result.IsPriorityGlobal()); -} - -TEST_F(PluginMetadata, NewMetadata) { - loot::PluginMetadata pm1(YAML::Load( - "name: 'Blank.esp'\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - " - 'Blank - Different.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - " - 'Blank - Different.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - " - 'Blank - Different.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - " - type: say\n" - " content: 'content2'\n" - "tag:\n" - " - Relev\n" - " - NoMerge\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - " - crc: 0x1\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'\n" - " - 'http://www.other-example.com'" - ).as()); - - loot::PluginMetadata pm2(YAML::Load( - "name: 'Blank - Different.esp'\n" - "after:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "req:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "inc:\n" - " - 'Blank.esm'\n" - " - 'Blank.esp'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - " - type: say\n" - " content: 'content3'\n" - "tag:\n" - " - Relev\n" - " - -Relev\n" - " - Delev\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - " - crc: 0x9\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'\n" - " - 'http://www.example2.com'" - ).as()); - - loot::PluginMetadata result = pm2.NewMetadata(pm1); - EXPECT_EQ("Blank - Different.esp", result.Name()); - EXPECT_TRUE(result.Enabled()); - EXPECT_EQ(0, result.Priority()); - EXPECT_FALSE(result.IsPriorityExplicit()); - EXPECT_FALSE(result.IsPriorityGlobal()); - EXPECT_EQ(std::set({ - loot::File("Blank.esp") - }), result.LoadAfter()); - EXPECT_EQ(std::set({ - loot::File("Blank.esp") - }), result.Reqs()); - EXPECT_EQ(std::set({ - loot::File("Blank.esp") - }), result.Incs()); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "content3"), - }), result.Messages()); - EXPECT_EQ(std::set({ - loot::Tag("Relev", false), - loot::Tag("Delev"), - }), result.Tags()); - EXPECT_EQ(std::set({ - loot::PluginDirtyInfo(9, 0, 1, 2, "utility") - }), result.DirtyInfo()); - EXPECT_EQ(std::set({ - loot::Location("http://www.example2.com") - }), result.Locations()); - - pm1.Priority(5); - result = pm2.NewMetadata(pm1); - - EXPECT_EQ(0, result.Priority()); - EXPECT_FALSE(result.IsPriorityExplicit()); - EXPECT_FALSE(result.IsPriorityGlobal()); -} - -TEST_F(PluginMetadata, Enabled) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.Enabled()); - pm.Enabled(false); - EXPECT_FALSE(pm.Enabled()); -} - -TEST_F(PluginMetadata, SetPriorityExplicit) { - loot::PluginMetadata pm; - ASSERT_FALSE(pm.IsPriorityExplicit()); - pm.SetPriorityExplicit(true); - EXPECT_TRUE(pm.IsPriorityExplicit()); -} - -TEST_F(PluginMetadata, Priority) { - loot::PluginMetadata pm; - ASSERT_NE(10, pm.Priority()); - pm.Priority(10); - EXPECT_EQ(10, pm.Priority()); -} - -TEST_F(PluginMetadata, settingPriorityWithAbsoluteValueGreaterOrEqualToGlobalPriorityDivisorShouldThrow) { - loot::PluginMetadata pm; - EXPECT_ANY_THROW(pm.Priority(loot::yamlGlobalPriorityDivisor)); - EXPECT_ANY_THROW(pm.Priority(loot::yamlGlobalPriorityDivisor + 1)); - EXPECT_ANY_THROW(pm.Priority(-loot::yamlGlobalPriorityDivisor)); - EXPECT_ANY_THROW(pm.Priority(-loot::yamlGlobalPriorityDivisor - 1)); -} - -TEST_F(PluginMetadata, settingPriorityAsGlobalShouldSucceed) { - loot::PluginMetadata pm; - ASSERT_FALSE(pm.IsPriorityGlobal()); - pm.SetPriorityGlobal(true); - EXPECT_TRUE(pm.IsPriorityGlobal()); -} - -TEST_F(PluginMetadata, settingPriorityAsNotGlobalShouldSucceed) { - loot::PluginMetadata pm; - pm.SetPriorityGlobal(true); - ASSERT_TRUE(pm.IsPriorityGlobal()); - pm.SetPriorityGlobal(false); - EXPECT_FALSE(pm.IsPriorityGlobal()); -} - -TEST_F(PluginMetadata, gettingYamlPriorityValueForAGlobalPriorityShouldReturnValueWithGlobalFlagSet) { - loot::PluginMetadata pm; - pm.Priority(10); - pm.SetPriorityGlobal(true); - EXPECT_EQ(1000010, pm.GetYamlPriorityValue()); - - pm.Priority(-20); - EXPECT_EQ(-1000020, pm.GetYamlPriorityValue()); -} - -TEST_F(PluginMetadata, gettingYamlPriorityValueForANonGlobalPriorityShouldReturnValueWithGlobalFlagNotSet) { - loot::PluginMetadata pm; - pm.Priority(10); - EXPECT_EQ(10, pm.GetYamlPriorityValue()); - - pm.Priority(-20); - EXPECT_EQ(-20, pm.GetYamlPriorityValue()); -} - -TEST_F(PluginMetadata, LoadAfter) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.LoadAfter().empty()); - pm.LoadAfter({ - loot::File("Blank.esm") - }); - EXPECT_EQ(std::set({ - loot::File("Blank.esm") - }), pm.LoadAfter()); -} - -TEST_F(PluginMetadata, Reqs) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.Reqs().empty()); - pm.Reqs({ - loot::File("Blank.esm") - }); - EXPECT_EQ(std::set({ - loot::File("Blank.esm") - }), pm.Reqs()); -} - -TEST_F(PluginMetadata, Incs) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.Incs().empty()); - pm.Incs({ - loot::File("Blank.esm") - }); - EXPECT_EQ(std::set({ - loot::File("Blank.esm") - }), pm.Incs()); -} - -TEST_F(PluginMetadata, Messages) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.Messages().empty()); - pm.Messages({ - loot::Message(loot::Message::say, "content") - }); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "content") - }), pm.Messages()); -} - -TEST_F(PluginMetadata, Tags) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.Tags().empty()); - pm.Tags({ - loot::Tag("Relev") - }); - EXPECT_EQ(std::set({ - loot::Tag("Relev") - }), pm.Tags()); -} - -TEST_F(PluginMetadata, DirtyInfo) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.DirtyInfo().empty()); - pm.DirtyInfo({ - loot::PluginDirtyInfo(5, 0, 1, 2, "utility") - }); - EXPECT_EQ(std::set({ - loot::PluginDirtyInfo(5, 0, 1, 2, "utility") - }), pm.DirtyInfo()); -} - -TEST_F(PluginMetadata, Locations) { - loot::PluginMetadata pm; - ASSERT_TRUE(pm.Locations().empty()); - pm.Locations({ - loot::Location("http://www.example.com") - }); - EXPECT_EQ(std::set({ - loot::Location("http://www.example.com") - }), pm.Locations()); -} - -TEST_F(PluginMetadata, EvalAllConditions) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - loot::PluginMetadata pm(YAML::Load( - "name: 'Blank.esp'\n" - "after:\n" - " - name: 'Blank.esm'\n" - " condition: 'file(\"Blank.esm\")'\n" - "req:\n" - " - name: 'Blank.esm'\n" - " condition: 'file(\"Blank.missing.esm\")'\n" - "inc:\n" - " - name: 'Blank.esm'\n" - " condition: 'file(\"Blank.esm\")'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - "tag:\n" - " - name: Relev\n" - " condition: 'file(\"Blank.missing.esm\")'\n" - "dirty:\n" - " - crc: 0x24F0E2A1\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - " - crc: 0xDEADBEEF\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2" - ).as()); - - pm.Messages({loot::Message(loot::Message::say, "content")}); - EXPECT_NO_THROW(pm.EvalAllConditions(game, loot::Language::english)); - EXPECT_EQ(std::set({ - loot::File("Blank.esm", "", "file(\"Blank.esm\")") - }), pm.LoadAfter()); - EXPECT_TRUE(pm.Reqs().empty()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm", "", "file(\"Blank.esm\")") - }), pm.Incs()); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "content") - }), pm.Messages()); - EXPECT_TRUE(pm.Tags().empty()); - EXPECT_EQ(std::set({ - loot::PluginDirtyInfo(0x24F0E2A1, 0, 1, 2, "utility") - }), pm.DirtyInfo()); -} - -TEST_F(PluginMetadata, HasNameOnly) { - loot::PluginMetadata pm; - EXPECT_TRUE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - EXPECT_TRUE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.Enabled(false); - EXPECT_TRUE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.SetPriorityExplicit(true); - EXPECT_FALSE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.LoadAfter({loot::File("Blank.esm")}); - EXPECT_FALSE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.Reqs({loot::File("Blank.esm")}); - EXPECT_FALSE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.Incs({loot::File("Blank.esm")}); - EXPECT_FALSE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.Messages({loot::Message(loot::Message::say, "content")}); - EXPECT_FALSE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.Tags({loot::Tag("Relev")}); - EXPECT_FALSE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.DirtyInfo({loot::PluginDirtyInfo(5, 0, 1, 2, "utility")}); - EXPECT_FALSE(pm.HasNameOnly()); - - pm = loot::PluginMetadata("Blank.esp"); - pm.Locations({loot::Location("http://www.example.com")}); - EXPECT_FALSE(pm.HasNameOnly()); -} - -TEST_F(PluginMetadata, IsRegexPlugin) { - loot::PluginMetadata pm; - EXPECT_FALSE(pm.IsRegexPlugin()); - - pm = loot::PluginMetadata("Blank.esm"); - EXPECT_FALSE(pm.IsRegexPlugin()); - - pm = loot::PluginMetadata("Blank[[:blank:]]- Different.esm"); - EXPECT_TRUE(pm.IsRegexPlugin()); - - pm = loot::PluginMetadata("Blank\\.esm"); - EXPECT_TRUE(pm.IsRegexPlugin()); - - pm = loot::PluginMetadata("Blank - (Different )*Master Dependent.esm"); - EXPECT_TRUE(pm.IsRegexPlugin()); - - pm = loot::PluginMetadata("Blank - (Different )?Master Dependent.esm"); - EXPECT_TRUE(pm.IsRegexPlugin()); - - pm = loot::PluginMetadata("Blank.es(p|m)"); - EXPECT_TRUE(pm.IsRegexPlugin()); -} - -TEST_F(PluginMetadata, YamlEmitter) { - loot::PluginMetadata pm("Blank.esp"); - YAML::Emitter e1; - e1 << pm; - EXPECT_STREQ("", e1.c_str()); - - pm.SetPriorityExplicit(true); - YAML::Emitter e2; - e2 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0", e2.c_str()); - - pm.Enabled(false); - YAML::Emitter e3; - e3 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false", e3.c_str()); - - pm.LoadAfter({loot::File("Blank.esm")}); - YAML::Emitter e4; - e4 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'", e4.c_str()); - - pm.Reqs({loot::File("Blank.esm")}); - YAML::Emitter e5; - e5 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'", e5.c_str()); - - pm.Incs({loot::File("Blank.esm")}); - YAML::Emitter e6; - e6 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - "inc:\n" - " - 'Blank.esm'", e6.c_str()); - - pm.Messages({loot::Message(loot::Message::say, "content")}); - YAML::Emitter e7; - e7 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'", e7.c_str()); - - pm.Tags({loot::Tag("Relev")}); - YAML::Emitter e8; - e8 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - "tag:\n" - " - Relev", e8.c_str()); - - pm.DirtyInfo({loot::PluginDirtyInfo(5, 0, 1, 2, "utility")}); - YAML::Emitter e9; - e9 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - "tag:\n" - " - Relev\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2", e9.c_str()); - - pm.Locations({loot::Location("http://www.example.com")}); - YAML::Emitter e10; - e10 << pm; - EXPECT_STREQ("name: 'Blank.esp'\n" - "priority: 0\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - "tag:\n" - " - Relev\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'", e10.c_str()); -} - -TEST_F(PluginMetadata, YamlEncode) { - YAML::Node node; - - loot::PluginMetadata pm("Blank.esp"); - node = pm; - EXPECT_EQ("Blank.esp", node["name"].as()); - EXPECT_FALSE(node["enabled"]); - EXPECT_FALSE(node["priority"]); - EXPECT_FALSE(node["after"]); - EXPECT_FALSE(node["req"]); - EXPECT_FALSE(node["inc"]); - EXPECT_FALSE(node["msg"]); - EXPECT_FALSE(node["tag"]); - EXPECT_FALSE(node["dirty"]); - EXPECT_FALSE(node["url"]); - - pm.SetPriorityExplicit(true); - node = pm; - EXPECT_EQ(0, node["priority"].as()); - - pm.Enabled(false); - node = pm; - EXPECT_FALSE(node["enabled"].as()); - - pm.LoadAfter({loot::File("Blank.esm")}); - node = pm; - EXPECT_EQ(pm.LoadAfter(), node["after"].as>()); - - pm.Reqs({loot::File("Blank.esm")}); - node = pm; - EXPECT_EQ(pm.Reqs(), node["req"].as>()); - - pm.Incs({loot::File("Blank.esm")}); - node = pm; - EXPECT_EQ(pm.Incs(), node["inc"].as>()); - - pm.Messages({loot::Message(loot::Message::say, "content")}); - node = pm; - EXPECT_EQ(pm.Messages(), node["msg"].as>()); - - pm.Tags({loot::Tag("Relev")}); - node = pm; - EXPECT_EQ(pm.Tags(), node["tag"].as>()); - - pm.DirtyInfo({loot::PluginDirtyInfo(5, 0, 1, 2, "utility")}); - node = pm; - EXPECT_EQ(pm.DirtyInfo(), node["dirty"].as>()); - - pm.Locations({loot::Location("http://www.example.com")}); - node = pm; - EXPECT_EQ(pm.Locations(), node["url"].as>()); -} - -TEST_F(PluginMetadata, YamlDecode) { - YAML::Node node; - loot::PluginMetadata pm; - - node = YAML::Load("name: Blank.esp"); - pm = node.as(); - EXPECT_EQ("Blank.esp", pm.Name()); - EXPECT_EQ(0, pm.Priority()); - EXPECT_FALSE(pm.IsPriorityExplicit()); - EXPECT_FALSE(pm.IsPriorityGlobal()); - - node = YAML::Load("name: 'Blank.esp'\n" - "priority: 5\n" - "enabled: false\n" - "after:\n" - " - 'Blank.esm'\n" - "req:\n" - " - 'Blank.esm'\n" - "inc:\n" - " - 'Blank.esm'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - "tag:\n" - " - Relev\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2\n" - "url:\n" - " - 'http://www.example.com'"); - pm = node.as(); - EXPECT_EQ("Blank.esp", pm.Name()); - EXPECT_EQ(5, pm.Priority()); - EXPECT_TRUE(pm.IsPriorityExplicit()); - EXPECT_FALSE(pm.IsPriorityGlobal()); - EXPECT_FALSE(pm.Enabled()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm") - }), pm.LoadAfter()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm") - }), pm.Reqs()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm") - }), pm.Incs()); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "content") - }), pm.Messages()); - EXPECT_EQ(std::set({ - loot::Tag("Relev") - }), pm.Tags()); - EXPECT_EQ(std::set({ - loot::PluginDirtyInfo(5, 0, 1, 2, "utility") - }), pm.DirtyInfo()); - EXPECT_EQ(std::set({ - loot::Location("http://www.example.com") - }), pm.Locations()); - - // Don't allow dirty metadata in regex entries. - node = YAML::Load("name: 'Blank\\.esp'\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - // Don't allow invalid regex. - node = YAML::Load("name: 'RagnvaldBook(Farengar(+Ragnvald)?)?\\.esp'\n" - "dirty:\n" - " - crc: 0x5\n" - " util: 'utility'\n" - " udr: 1\n" - " nav: 2"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - // Catch condition syntax errors. - node = YAML::Load( - "name: 'Blank.esp'\n" - "after:\n" - " - name: 'Blank.esm'\n" - " condition: 'file(\"Blank.esm\")'\n" - "req:\n" - " - name: 'Blank.esm'\n" - " condition: 'file(\"Blank.missing.esm\")'\n" - "inc:\n" - " - name: 'Blank.esm'\n" - " condition: 'file(\"Blank.esm\")'\n" - "msg:\n" - " - type: say\n" - " content: 'content'\n" - " condition: 'condition'\n" - "tag:\n" - " - name: Relev\n" - " condition: 'file(\"Blank.missing.esm\")'" - ); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - node = YAML::Load("scalar"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -#endif diff --git a/src/tests/backend/metadata/test_tag.h b/src/tests/backend/metadata/test_tag.h deleted file mode 100644 index 2b112997..00000000 --- a/src/tests/backend/metadata/test_tag.h +++ /dev/null @@ -1,180 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_TAG -#define LOOT_TEST_BACKEND_METADATA_TAG - -#include "backend/metadata/tag.h" -#include "tests/fixtures.h" - -using loot::Tag; - -TEST(Tag, ConstructorsAndDataAccess) { - Tag tag; - EXPECT_EQ("", tag.Name()); - EXPECT_TRUE(tag.IsAddition()); - EXPECT_EQ("", tag.Condition()); - - tag = Tag("name"); - EXPECT_EQ("name", tag.Name()); - EXPECT_TRUE(tag.IsAddition()); - EXPECT_EQ("", tag.Condition()); - - tag = Tag("name", false); - EXPECT_EQ("name", tag.Name()); - EXPECT_FALSE(tag.IsAddition()); - EXPECT_EQ("", tag.Condition()); - - // Not a valid condition, but not evaluating it in this test. - tag = Tag("name", false, "condition"); - EXPECT_EQ("name", tag.Name()); - EXPECT_FALSE(tag.IsAddition()); - EXPECT_EQ("condition", tag.Condition()); -} - -TEST(Tag, EqualityOperator) { - Tag tag1, tag2; - EXPECT_TRUE(tag1 == tag2); - - // Not valid conditions, but not evaluating them in this test. - tag1 = Tag("name", true, "condition1"); - tag2 = Tag("name", true, "condition2"); - EXPECT_TRUE(tag1 == tag2); - - tag1 = Tag("name"); - tag2 = Tag("Name"); - EXPECT_TRUE(tag1 == tag2); - - tag1 = Tag("name", true); - tag2 = Tag("name", false); - EXPECT_FALSE(tag1 == tag2); - - tag1 = Tag("name1"); - tag2 = Tag("name2"); - EXPECT_FALSE(tag1 == tag2); -} - -TEST(Tag, LessThanOperator) { - Tag tag1, tag2; - EXPECT_FALSE(tag1 < tag2); - EXPECT_FALSE(tag2 < tag1); - - tag1 = Tag("name", true, "condition1"); - tag2 = Tag("name", true, "condition2"); - EXPECT_FALSE(tag1 < tag2); - EXPECT_FALSE(tag2 < tag1); - - tag1 = Tag("name"); - tag2 = Tag("Name"); - EXPECT_FALSE(tag1 < tag2); - EXPECT_FALSE(tag2 < tag1); - - tag1 = Tag("name1"); - tag2 = Tag("name2"); - EXPECT_TRUE(tag1 < tag2); - EXPECT_FALSE(tag2 < tag1); - - tag1 = Tag("name", true); - tag2 = Tag("name", false); - EXPECT_TRUE(tag1 < tag2); - EXPECT_FALSE(tag2 < tag1); -} - -TEST(Tag, YamlEmitter) { - Tag tag("name1"); - YAML::Emitter e1; - e1 << tag; - EXPECT_STREQ("name1", e1.c_str()); - - tag = Tag("name1", false); - YAML::Emitter e2; - e2 << tag; - EXPECT_STREQ("-name1", e2.c_str()); - - tag = Tag("name1", true, "condition1"); - YAML::Emitter e3; - e3 << tag; - EXPECT_STREQ("name: name1\ncondition: 'condition1'", e3.c_str()); - - tag = Tag("name1", false, "condition1"); - YAML::Emitter e4; - e4 << tag; - EXPECT_STREQ("name: -name1\ncondition: 'condition1'", e4.c_str()); -} - -TEST(Tag, YamlEncode) { - YAML::Node node; - - Tag tag("name1"); - node = tag; - EXPECT_EQ("name1", node["name"].as()); - EXPECT_FALSE(node["condition"]); - - tag = Tag("name1", false); - node = tag; - EXPECT_EQ("-name1", node["name"].as()); - EXPECT_FALSE(node["condition"]); - - tag = Tag("name1", false, "condition1"); - node = tag; - EXPECT_EQ("-name1", node["name"].as()); - EXPECT_EQ("condition1", node["condition"].as()); -} - -TEST(Tag, YamlDecode) { - YAML::Node node; - Tag tag; - - node = YAML::Load("name1"); - tag = node.as(); - EXPECT_EQ("name1", tag.Name()); - EXPECT_TRUE(tag.IsAddition()); - EXPECT_EQ("", tag.Condition()); - - node = YAML::Load("-name1"); - tag = node.as(); - EXPECT_EQ("name1", tag.Name()); - EXPECT_FALSE(tag.IsAddition()); - EXPECT_EQ("", tag.Condition()); - - node = YAML::Load("{name: -name1}"); - tag = node.as(); - EXPECT_EQ("name1", tag.Name()); - EXPECT_FALSE(tag.IsAddition()); - EXPECT_EQ("", tag.Condition()); - - node = YAML::Load("{name: name1, condition: 'file(\"Foo.esp\")'}"); - tag = node.as(); - EXPECT_EQ("name1", tag.Name()); - EXPECT_TRUE(tag.IsAddition()); - EXPECT_EQ("file(\"Foo.esp\")", tag.Condition()); - - node = YAML::Load("{name: name1, condition: invalid}"); - EXPECT_THROW(node.as(), YAML::RepresentationException); - - node = YAML::Load("[0, 1, 2]"); - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -#endif diff --git a/src/tests/backend/metadata_list_test.h b/src/tests/backend/metadata_list_test.h new file mode 100644 index 00000000..1f66edde --- /dev/null +++ b/src/tests/backend/metadata_list_test.h @@ -0,0 +1,296 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_METADATA_LIST +#define LOOT_TEST_BACKEND_METADATA_LIST + +#include "backend/metadata_list.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class MetadataListTest : public BaseGameTest { + protected: + MetadataListTest() : + metadataPath("./testing-metadata/masterlist.yaml"), + savedMetadataPath("./testing-metadata/saved.masterlist.yaml"), + missingMetadataPath("./missing-metadata.yaml"), + invalidMetadataPaths({"./testing-metadata/invalid/non_unique.yaml"}) { + PluginMetadataToString = [](const PluginMetadata& plugin) { + return plugin.Name(); + }; + } + + inline virtual void SetUp() { + BaseGameTest::SetUp(); + + ASSERT_TRUE(boost::filesystem::exists(metadataPath)); + ASSERT_FALSE(boost::filesystem::exists(savedMetadataPath)); + + for (const auto& path : invalidMetadataPaths) { + ASSERT_TRUE(boost::filesystem::exists(path)); + } + } + + inline virtual void TearDown() { + BaseGameTest::TearDown(); + + ASSERT_TRUE(boost::filesystem::exists(metadataPath)); + ASSERT_NO_THROW(boost::filesystem::remove(savedMetadataPath)); + + for (const auto& path : invalidMetadataPaths) { + ASSERT_TRUE(boost::filesystem::exists(path)); + } + } + + const boost::filesystem::path metadataPath; + const boost::filesystem::path savedMetadataPath; + const boost::filesystem::path missingMetadataPath; + const std::vector invalidMetadataPaths; + + std::function PluginMetadataToString; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + MetadataListTest, + ::testing::Values( + GameSettings::tes4)); + + TEST_P(MetadataListTest, loadShouldLoadGlobalMessages) { + MetadataList metadataList; + + EXPECT_NO_THROW(metadataList.Load(metadataPath)); + EXPECT_EQ(std::list({ + Message(Message::say, "A global message."), + }), metadataList.Messages()); + } + + TEST_P(MetadataListTest, loadShouldLoadPluginMetadata) { + MetadataList metadataList; + + EXPECT_NO_THROW(metadataList.Load(metadataPath)); + // Non-regex plugins can be outputted in any order, and regex entries can + // match each other, so convert the list to a set of strings for + // comparison. + std::list result(metadataList.Plugins()); + std::set names; + std::transform(begin(result), + end(result), + std::insert_iterator>(names, begin(names)), + PluginMetadataToString); + + EXPECT_EQ(std::set({ + blankEsm, + blankEsp, + "Blank.+\\.esp", + "Blank.+(Different)?.*\\.esp", + }), names); + } + + TEST_P(MetadataListTest, loadShouldThrowIfAnInvalidMetadataFileIsGiven) { + MetadataList ml; + for (const auto& path : invalidMetadataPaths) { + EXPECT_ANY_THROW(ml.Load(path)); + } + } + + TEST_P(MetadataListTest, loadShouldClearExistingDataIfAnInvalidMetadataFileIsGiven) { + MetadataList metadataList; + + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + ASSERT_FALSE(metadataList.Messages().empty()); + ASSERT_FALSE(metadataList.Plugins().empty()); + + EXPECT_ANY_THROW(metadataList.Load(blankEsm)); + EXPECT_TRUE(metadataList.Messages().empty()); + EXPECT_TRUE(metadataList.Plugins().empty()); + } + + TEST_P(MetadataListTest, loadShouldClearExistingDataIfAMissingMetadataFileIsGiven) { + MetadataList metadataList; + + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + ASSERT_FALSE(metadataList.Messages().empty()); + ASSERT_FALSE(metadataList.Plugins().empty()); + + EXPECT_ANY_THROW(metadataList.Load(missingMetadataPath)); + EXPECT_TRUE(metadataList.Messages().empty()); + EXPECT_TRUE(metadataList.Plugins().empty()); + } + + TEST_P(MetadataListTest, saveShouldWriteTheLoadedMetadataToTheGivenFilePath) { + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + + EXPECT_NO_THROW(metadataList.Save(savedMetadataPath)); + + EXPECT_TRUE(boost::filesystem::exists(savedMetadataPath)); + + // Check the new file contains the same metadata. + EXPECT_NO_THROW(metadataList.Load(savedMetadataPath)); + + EXPECT_EQ(std::list({ + Message(Message::say, "A global message."), + }), metadataList.Messages()); + + // Non-regex plugins can be outputted in any order, and regex entries can + // match each other, so convert the list to a set of strings for + // comparison. + std::list result(metadataList.Plugins()); + std::set names; + std::transform(begin(result), + end(result), + std::insert_iterator>(names, begin(names)), + PluginMetadataToString); + EXPECT_EQ(std::set({ + blankEsm, + blankEsp, + "Blank.+\\.esp", + "Blank.+(Different)?.*\\.esp", + }), names); + } + + TEST_P(MetadataListTest, clearShouldClearLoadedMessagesAndPlugins) { + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + ASSERT_FALSE(metadataList.Messages().empty()); + ASSERT_FALSE(metadataList.Plugins().empty()); + + metadataList.clear(); + EXPECT_TRUE(metadataList.Messages().empty()); + EXPECT_TRUE(metadataList.Plugins().empty()); + } + + TEST_P(MetadataListTest, findPluginShouldReturnAnEmptyPluginObjectIfTheGivenPluginIsNotInTheMetadataList) { + MetadataList metadataList; + PluginMetadata plugin = metadataList.FindPlugin(PluginMetadata(blankDifferentEsm)); + + EXPECT_EQ(blankDifferentEsm, plugin.Name()); + EXPECT_TRUE(plugin.HasNameOnly()); + } + + TEST_P(MetadataListTest, findPluginShouldReturnTheMetadataObjectInTheMetadataListIfOneExistsForTheGivenPlugin) { + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + + PluginMetadata plugin = metadataList.FindPlugin(PluginMetadata(blankDifferentEsp)); + + EXPECT_EQ(blankDifferentEsp, plugin.Name()); + EXPECT_EQ(std::set({ + File(blankEsm), + }), plugin.LoadAfter()); + EXPECT_EQ(std::set({ + File(blankEsp), + }), plugin.Incs()); + } + + TEST_P(MetadataListTest, addPluginShouldStoreGivenSpecificPluginMetadata) { + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + ASSERT_TRUE(metadataList.FindPlugin(PluginMetadata(blankDifferentEsm)).HasNameOnly()); + + PluginMetadata plugin(blankDifferentEsm); + plugin.Priority(1000); + metadataList.AddPlugin(plugin); + + plugin = metadataList.FindPlugin(plugin); + + EXPECT_EQ(blankDifferentEsm, plugin.Name()); + EXPECT_EQ(1000, plugin.Priority()); + } + + TEST_P(MetadataListTest, addPluginShouldStoreGivenRegexPluginMetadata) { + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + + PluginMetadata plugin(".+Dependent\\.esp"); + plugin.Priority(-10); + metadataList.AddPlugin(plugin); + + plugin = metadataList.FindPlugin(PluginMetadata(blankPluginDependentEsp)); + + EXPECT_EQ(-10, plugin.Priority()); + } + + TEST_P(MetadataListTest, addPluginShouldThrowIfAMatchingPluginAlreadyExists) { + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + + PluginMetadata plugin = metadataList.FindPlugin(PluginMetadata(blankEsm)); + ASSERT_EQ(blankEsm, plugin.Name()); + ASSERT_FALSE(plugin.HasNameOnly()); + + ASSERT_ANY_THROW(metadataList.AddPlugin(PluginMetadata(blankEsm))); + } + + TEST_P(MetadataListTest, erasePluginShouldRemoveStoredMetadatForTheGivenPlugin) { + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + + PluginMetadata plugin = metadataList.FindPlugin(PluginMetadata(blankEsp)); + ASSERT_EQ(blankEsp, plugin.Name()); + ASSERT_FALSE(plugin.HasNameOnly()); + + metadataList.ErasePlugin(plugin); + + plugin = metadataList.FindPlugin(plugin); + EXPECT_EQ(blankEsp, plugin.Name()); + EXPECT_TRUE(plugin.HasNameOnly()); + } + + TEST_P(MetadataListTest, evalAllConditionsShouldEvaluateTheConditionsForThePluginsStoredInTeMetadataList) { + Game game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + + MetadataList metadataList; + ASSERT_NO_THROW(metadataList.Load(metadataPath)); + + PluginMetadata plugin = metadataList.FindPlugin(PluginMetadata(blankEsm)); + ASSERT_EQ(std::list({ + Message(Message::warn, "This is a warning."), + Message(Message::say, "This message should be removed when evaluating conditions."), + }), plugin.Messages()); + + plugin = metadataList.FindPlugin(PluginMetadata(blankEsp)); + ASSERT_EQ(blankEsp, plugin.Name()); + ASSERT_FALSE(plugin.HasNameOnly()); + + EXPECT_NO_THROW(metadataList.EvalAllConditions(game, Language::english)); + + plugin = metadataList.FindPlugin(PluginMetadata(blankEsm)); + EXPECT_EQ(std::list({ + Message(Message::warn, "This is a warning."), + }), plugin.Messages()); + + plugin = metadataList.FindPlugin(PluginMetadata(blankEsp)); + EXPECT_EQ(blankEsp, plugin.Name()); + EXPECT_TRUE(plugin.HasNameOnly()); + } + } +} + +#endif diff --git a/src/tests/backend/plugin/plugin_test.h b/src/tests/backend/plugin/plugin_test.h new file mode 100644 index 00000000..f29def82 --- /dev/null +++ b/src/tests/backend/plugin/plugin_test.h @@ -0,0 +1,311 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_PLUGIN +#define LOOT_TEST_BACKEND_PLUGIN + +#include "backend/plugin/plugin.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class PluginTest : public BaseGameTest { + protected: + PluginTest() : + emptyFile("EmptyFile.esm"), + nonPluginFile("NotAPlugin.esm") {} + + inline void SetUp() { + BaseGameTest::SetUp(); + + game = Game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + game.Init(false, localPath); + + // Write out an empty file. + boost::filesystem::ofstream out(dataPath / emptyFile); + out.close(); + ASSERT_TRUE(boost::filesystem::exists(dataPath / emptyFile)); + + // Write out an non-empty, non-plugin file. + out.open(dataPath / nonPluginFile); + out << "This isn't a valid plugin file."; + out.close(); + ASSERT_TRUE(boost::filesystem::exists(dataPath / nonPluginFile)); + + if (GetParam() == GameSettings::tes4 || GetParam() == GameSettings::fo4) { + // Create a dummy BSA file. + out.open(dataPath / getArchiveName()); + out.close(); + } + } + + inline void TearDown() { + BaseGameTest::TearDown(); + + boost::filesystem::remove(dataPath / emptyFile); + boost::filesystem::remove(dataPath / nonPluginFile); + + if (GetParam() == GameSettings::tes4 || GetParam() == GameSettings::fo4) + boost::filesystem::remove(dataPath / getArchiveName()); + } + + Game game; + + const std::string emptyFile; + const std::string nonPluginFile; + + private: + inline std::string getArchiveName() { + if (GetParam() == GameSettings::fo4) + return "Blank.ba2"; + else + return "Blank.bsa"; + } + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + PluginTest, + ::testing::Values( + GameSettings::tes4, + GameSettings::tes5, + GameSettings::fo3, + GameSettings::fonv, + GameSettings::fo4)); + + TEST_P(PluginTest, loadingHeaderOnlyShouldReadHeaderData) { + Plugin plugin(game, blankEsm, true); + + EXPECT_EQ(blankEsm, plugin.Name()); + EXPECT_TRUE(plugin.getMasters().empty()); + EXPECT_TRUE(plugin.isMasterFile()); + EXPECT_FALSE(plugin.IsEmpty()); + EXPECT_EQ("v5.0", plugin.getDescription()); + } + + TEST_P(PluginTest, loadingHeaderOnlyShouldNotReadFieldsOrCalculateCrc) { + Plugin plugin(game, blankEsm, true); + + EXPECT_TRUE(plugin.getFormIds().empty()); + EXPECT_EQ(0, plugin.Crc()); + } + + TEST_P(PluginTest, loadingWholePluginShouldReadHeaderData) { + Plugin plugin(game, blankEsm, true); + + EXPECT_EQ(blankEsm, plugin.Name()); + EXPECT_TRUE(plugin.getMasters().empty()); + EXPECT_TRUE(plugin.isMasterFile()); + EXPECT_FALSE(plugin.IsEmpty()); + EXPECT_EQ("v5.0", plugin.getDescription()); + } + + TEST_P(PluginTest, loadingWholePluginShouldReadFields) { + Plugin plugin(game, blankMasterDependentEsm, false); + + EXPECT_EQ(4, plugin.NumOverrideFormIDs()); + } + + TEST_P(PluginTest, loadingWholePluginShouldCalculateCrc) { + Plugin plugin(game, blankEsm, false); + + EXPECT_EQ(blankEsmCrc, plugin.Crc()); + } + + TEST_P(PluginTest, loadingANonMasterPluginShouldReadTheMasterFlagAsFalse) { + Plugin plugin(game, blankMasterDependentEsp, true); + + EXPECT_FALSE(plugin.isMasterFile()); + } + + TEST_P(PluginTest, loadingAPluginWithMastersShouldReadThemCorrectly) { + Plugin plugin(game, blankMasterDependentEsp, true); + + EXPECT_EQ(std::vector({ + blankEsm + }), plugin.getMasters()); + } + + TEST_P(PluginTest, loadsArchiveShouldReturnTrueForAPluginThatLoadsAnArchive) { + EXPECT_TRUE(Plugin(game, blankEsp, true).LoadsArchive()); + } + + TEST_P(PluginTest, loadsArchiveShouldReturnFalseForAPluginThatDoesNotLoadAnArchive) { + EXPECT_FALSE(Plugin(game, blankDifferentEsm, true).LoadsArchive()); + } + + TEST_P(PluginTest, loadsArchiveShouldReturnFalseForAPluginWithARegexFilename) { + EXPECT_FALSE(Plugin(game, "Blank\\.esp", true).LoadsArchive()); + } + + TEST_P(PluginTest, isValidShouldReturnTrueForAValidPlugin) { + EXPECT_TRUE(Plugin::IsValid(blankEsm, game)); + } + + TEST_P(PluginTest, isValidShouldReturnFalseForANonPluginFile) { + EXPECT_FALSE(Plugin::IsValid(nonPluginFile, game)); + } + + TEST_P(PluginTest, isValidShouldReturnFalseForAnEmptyFile) { + EXPECT_FALSE(Plugin::IsValid(emptyFile, game)); + } + + TEST_P(PluginTest, isActiveShouldReturnTrueForAPluginThatIsActive) { + EXPECT_TRUE(Plugin(game, blankEsm, true).IsActive()); + } + + TEST_P(PluginTest, isActiveShouldReturnFalseForAPluginThatIsNotActive) { + EXPECT_FALSE(Plugin(game, blankEsp, true).IsActive()); + } + + TEST_P(PluginTest, lessThanOperatorShouldUseCaseInsensitiveLexicographicalNameComparison) { + Plugin plugin1(game, "Blank.esp", true); + Plugin plugin2(game, "blank.esp", true); + + EXPECT_FALSE(plugin1 < plugin2); + EXPECT_FALSE(plugin2 < plugin1); + + plugin1 = Plugin(game, "blank.esm", true); + plugin2 = Plugin(game, "blank.esp", true); + + EXPECT_TRUE(plugin1 < plugin2); + EXPECT_FALSE(plugin2 < plugin1); + } + + TEST_P(PluginTest, doFormIDsOverlapShouldReturnFalseForTwoPluginsWithOnlyHeadersLoaded) { + Plugin plugin1(game, blankEsm, true); + Plugin plugin2(game, blankMasterDependentEsm, true); + + EXPECT_FALSE(plugin1.DoFormIDsOverlap(plugin2)); + EXPECT_FALSE(plugin2.DoFormIDsOverlap(plugin1)); + } + + TEST_P(PluginTest, doFormIDsOverlapShouldReturnFalseIfThePluginsHaveUnrelatedRecords) { + Plugin plugin1(game, blankEsm, false); + Plugin plugin2(game, blankEsp, false); + + EXPECT_FALSE(plugin1.DoFormIDsOverlap(plugin2)); + EXPECT_FALSE(plugin2.DoFormIDsOverlap(plugin1)); + } + + TEST_P(PluginTest, doFormIDsOverlapShouldReturnTrueIfOnePluginOverridesTheOthersRecords) { + Plugin plugin1(game, blankEsm, false); + Plugin plugin2(game, blankMasterDependentEsm, false); + + EXPECT_TRUE(plugin1.DoFormIDsOverlap(plugin2)); + EXPECT_TRUE(plugin2.DoFormIDsOverlap(plugin1)); + } + + TEST_P(PluginTest, overlapFormIDsShouldReturnAnEmptySetForTwoPluginsWithOnlyHeadersLoaded) { + Plugin plugin1(game, blankEsm, true); + Plugin plugin2(game, blankMasterDependentEsm, true); + + EXPECT_TRUE(plugin1.OverlapFormIDs(plugin2).empty()); + EXPECT_TRUE(plugin2.OverlapFormIDs(plugin1).empty()); + } + + TEST_P(PluginTest, overlapFormIDsShouldReturnAnEmptySetIfThePluginsHaveUnrelatedRecords) { + Plugin plugin1(game, blankEsm, false); + Plugin plugin2(game, blankEsp, false); + + EXPECT_TRUE(plugin1.OverlapFormIDs(plugin2).empty()); + EXPECT_TRUE(plugin2.OverlapFormIDs(plugin1).empty()); + } + + TEST_P(PluginTest, overlapFormIDsShouldReturnTheFormIDsOfRecordsAddedByOnePluginAndOverriddenByTheOther) { + Plugin plugin1(game, blankEsm, false); + Plugin plugin2(game, blankMasterDependentEsm, false); + + std::set expectedFormIds({ + libespm::FormId(blankEsm, std::vector(), 0xCF0), + libespm::FormId(blankEsm, std::vector(), 0xCF1), + libespm::FormId(blankEsm, std::vector(), 0xCF2), + libespm::FormId(blankEsm, std::vector(), 0xCF3), + }); + EXPECT_EQ(expectedFormIds, plugin1.OverlapFormIDs(plugin2)); + EXPECT_EQ(expectedFormIds, plugin2.OverlapFormIDs(plugin1)); + } + + TEST_P(PluginTest, checkInstallValidityShouldCheckThatRequirementsArePresent) { + Plugin plugin(game, blankEsm, false); + plugin.Reqs({ + File(missingEsp), + File(blankEsp), + }); + + EXPECT_FALSE(plugin.CheckInstallValidity(game)); + EXPECT_EQ(std::list({ + Message(Message::error, "This plugin requires \"" + missingEsp + "\" to be installed, but it is missing."), + }), plugin.Messages()); + } + + TEST_P(PluginTest, checkInstallValidityShouldCheckThatIncompatibilitiesAreAbsent) { + Plugin plugin(game, blankEsm, false); + plugin.Incs({ + File(missingEsp), + File(masterFile), + }); + + EXPECT_FALSE(plugin.CheckInstallValidity(game)); + EXPECT_EQ(std::list({ + Message(Message::error, "This plugin is incompatible with \"" + masterFile + "\", but both are present."), + }), plugin.Messages()); + } + + TEST_P(PluginTest, checkInstallValidityShouldGenerateMessagesFromDirtyInfo) { + Plugin plugin(game, blankEsm, false); + plugin.DirtyInfo({ + PluginDirtyInfo(blankEsmCrc, 0, 1, 2, "utility1"), + PluginDirtyInfo(0xDEADBEEF, 0, 5, 10, "utility2"), + }); + + EXPECT_TRUE(plugin.CheckInstallValidity(game)); + EXPECT_EQ(std::list({ + PluginDirtyInfo(blankEsmCrc, 0, 1, 2, "utility1").AsMessage(), + PluginDirtyInfo(0xDEADBEEF, 0, 5, 10, "utility2").AsMessage(), + }), plugin.Messages()); + } + + TEST_P(PluginTest, checkInstallValidityShouldCheckIfAPluginsMastersAreAllPresentAndActiveIfNoFilterTagIsPresent) { + Plugin plugin(game, blankDifferentMasterDependentEsp, false); + + EXPECT_FALSE(plugin.CheckInstallValidity(game)); + EXPECT_EQ(std::list({ + Message(Message::error, "This plugin requires \"" + blankDifferentEsm + "\" to be active, but it is inactive."), + }), plugin.Messages()); + } + + TEST_P(PluginTest, checkInstallValidityShouldNotCheckIfAPluginsMastersAreAllActiveIfAFilterTagIsPresent) { + Plugin plugin(game, blankDifferentMasterDependentEsp, false); + plugin.Tags({Tag("Filter")}); + + EXPECT_FALSE(plugin.CheckInstallValidity(game)); + EXPECT_TRUE(plugin.Messages().empty()); + } + } +} + +#endif diff --git a/src/tests/backend/plugin/test_plugin.h b/src/tests/backend/plugin/test_plugin.h deleted file mode 100644 index 710565d5..00000000 --- a/src/tests/backend/plugin/test_plugin.h +++ /dev/null @@ -1,254 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_PLUGIN -#define LOOT_TEST_BACKEND_PLUGIN - -#include "backend/plugin/plugin.h" -#include "tests/fixtures.h" - -class Plugin : public SkyrimTest { -protected: - inline virtual void SetUp() { - SkyrimTest::SetUp(); - - game = loot::Game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - } - - loot::Game game; -}; - -TEST_F(Plugin, ConstructorsAndDataAccess) { - loot::Plugin plugin(game, "Blank.esm", true); - EXPECT_EQ("Blank.esm", plugin.Name()); - EXPECT_TRUE(plugin.getFormIds().empty()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_EQ("v5.0", plugin.getDescription()); - EXPECT_EQ(0, plugin.Crc()); - - plugin = loot::Plugin(game, "Blank.esm", false); - EXPECT_EQ("Blank.esm", plugin.Name()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esm", std::vector(), 0xCF0), - libespm::FormId("Blank.esm", std::vector(), 0xCF1), - libespm::FormId("Blank.esm", std::vector(), 0xCF2), - libespm::FormId("Blank.esm", std::vector(), 0xCF3), - libespm::FormId("Blank.esm", std::vector(), 0xCF4), - libespm::FormId("Blank.esm", std::vector(), 0xCF5), - libespm::FormId("Blank.esm", std::vector(), 0xCF6), - libespm::FormId("Blank.esm", std::vector(), 0xCF7), - libespm::FormId("Blank.esm", std::vector(), 0xCF8), - libespm::FormId("Blank.esm", std::vector(), 0xCF9), - }), plugin.getFormIds()); - EXPECT_TRUE(plugin.getMasters().empty()); - EXPECT_TRUE(plugin.isMasterFile()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_EQ("v5.0", plugin.getDescription()); - EXPECT_EQ(0x187BE342, plugin.Crc()); - - plugin = loot::Plugin(game, "Blank - Master Dependent.esp", false); - EXPECT_EQ("Blank - Master Dependent.esp", plugin.Name()); - EXPECT_FALSE(plugin.IsEmpty()); - EXPECT_FALSE(plugin.isMasterFile()); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esm", std::vector(), 0xCF0), - libespm::FormId("Blank.esm", std::vector(), 0xCF1), - libespm::FormId("Blank - Master Dependent.esp", std::vector(), 0xCE9), - libespm::FormId("Blank - Master Dependent.esp", std::vector(), 0xCEA), - }), plugin.getFormIds()); - EXPECT_EQ(std::vector({ - "Blank.esm" - }), plugin.getMasters()); - EXPECT_EQ("", plugin.getDescription()); - EXPECT_EQ(0x832152DC, plugin.Crc()); -} - -TEST_F(Plugin, LoadsArchive) { - EXPECT_FALSE(loot::Plugin(game, "Blank - Different.esm", true).LoadsArchive()); - EXPECT_FALSE(loot::Plugin(game, "Blank\\.esm", true).LoadsArchive()); - EXPECT_TRUE(loot::Plugin(game, "Blank.esm", true).LoadsArchive()); -} - -TEST_F(Plugin, IsValid) { - EXPECT_TRUE(loot::Plugin::IsValid("Blank.esm", game)); - EXPECT_FALSE(loot::Plugin::IsValid("NotAPlugin.esm", game)); - EXPECT_FALSE(loot::Plugin::IsValid("EmptyFile.esm", game)); -} - -TEST_F(Plugin, IsActive) { - loot::Plugin plugin(game, "Blank.esm", true); - EXPECT_TRUE(plugin.IsActive()); - - plugin = loot::Plugin(game, "Blank.esp", true); - EXPECT_FALSE(plugin.IsActive()); -} - -TEST_F(Plugin, EqualityOperator) { - loot::Plugin plugin1(game, "Blank.esm", true); - loot::Plugin plugin2(game, "blank.esm", true); - EXPECT_TRUE(plugin1 == plugin2); - EXPECT_TRUE(plugin2 == plugin1); - - plugin2 = loot::Plugin(game, "Blank.esp", true); - EXPECT_FALSE(plugin1 == plugin2); - EXPECT_FALSE(plugin2 == plugin1); - - plugin2 = loot::Plugin(game, "Blan.\\.esm", true); - EXPECT_TRUE(plugin1 == plugin2); - EXPECT_TRUE(plugin2 == plugin1); - - plugin1 = loot::Plugin(game, "Blan.esm", true); - EXPECT_FALSE(plugin1 == plugin2); - EXPECT_FALSE(plugin2 == plugin1); - - plugin1 = loot::Plugin(game, "Blan.\\.esm", true); - EXPECT_TRUE(plugin1 == plugin2); - EXPECT_TRUE(plugin2 == plugin1); - - plugin1 = loot::Plugin(game, "Blan(k|p).esm", true); - EXPECT_FALSE(plugin1 == plugin2); - EXPECT_FALSE(plugin2 == plugin1); -} - -TEST_F(Plugin, InequalityOperator) { - loot::Plugin plugin1(game, "Blank.esm", true); - loot::Plugin plugin2(game, "blank.esm", true); - EXPECT_FALSE(plugin1 != plugin2); - EXPECT_FALSE(plugin2 != plugin1); - - plugin2 = loot::Plugin(game, "Blank.esp", true); - EXPECT_TRUE(plugin1 != plugin2); - EXPECT_TRUE(plugin2 != plugin1); - - plugin2 = loot::Plugin(game, "Blan.\\.esm", true); - EXPECT_FALSE(plugin1 != plugin2); - EXPECT_FALSE(plugin2 != plugin1); - - plugin1 = loot::Plugin(game, "Blan.esm", true); - EXPECT_TRUE(plugin1 != plugin2); - EXPECT_TRUE(plugin2 != plugin1); - - plugin1 = loot::Plugin(game, "Blan.\\.esm", true); - EXPECT_FALSE(plugin1 != plugin2); - EXPECT_FALSE(plugin2 != plugin1); - - plugin1 = loot::Plugin(game, "Blan(k|p).esm", true); - EXPECT_TRUE(plugin1 != plugin2); - EXPECT_TRUE(plugin2 != plugin1); -} - -TEST_F(Plugin, DoFormIDsOverlap) { - loot::Plugin plugin1(game, "Blank.esm", true); - loot::Plugin plugin2(game, "blank.esm", true); - EXPECT_FALSE(plugin1.DoFormIDsOverlap(plugin2)); - EXPECT_FALSE(plugin2.DoFormIDsOverlap(plugin1)); - - plugin1 = loot::Plugin(game, "Blank.esm", true); - plugin2 = loot::Plugin(game, "Blank - Master Dependent.esm", true); - EXPECT_FALSE(plugin1.DoFormIDsOverlap(plugin2)); - EXPECT_FALSE(plugin2.DoFormIDsOverlap(plugin1)); - - plugin1 = loot::Plugin(game, "Blank.esm", false); - plugin2 = loot::Plugin(game, "Blank.esp", false); - EXPECT_FALSE(plugin1.DoFormIDsOverlap(plugin2)); - EXPECT_FALSE(plugin2.DoFormIDsOverlap(plugin1)); - - plugin1 = loot::Plugin(game, "Blank.esm", false); - plugin2 = loot::Plugin(game, "Blank - Master Dependent.esm", false); - EXPECT_TRUE(plugin1.DoFormIDsOverlap(plugin2)); - EXPECT_TRUE(plugin2.DoFormIDsOverlap(plugin1)); -} - -TEST_F(Plugin, OverlapFormIDs) { - loot::Plugin plugin1(game, "Blank.esm", true); - loot::Plugin plugin2(game, "blank.esm", true); - EXPECT_TRUE(plugin1.OverlapFormIDs(plugin2).empty()); - EXPECT_TRUE(plugin2.OverlapFormIDs(plugin1).empty()); - - plugin1 = loot::Plugin(game, "Blank.esm", true); - plugin2 = loot::Plugin(game, "Blank - Master Dependent.esm", true); - EXPECT_TRUE(plugin1.OverlapFormIDs(plugin2).empty()); - EXPECT_TRUE(plugin2.OverlapFormIDs(plugin1).empty()); - - plugin1 = loot::Plugin(game, "Blank.esm", false); - plugin2 = loot::Plugin(game, "Blank.esp", false); - EXPECT_TRUE(plugin1.OverlapFormIDs(plugin2).empty()); - EXPECT_TRUE(plugin2.OverlapFormIDs(plugin1).empty()); - - plugin1 = loot::Plugin(game, "Blank.esm", false); - plugin2 = loot::Plugin(game, "Blank - Master Dependent.esm", false); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esm", std::vector(), 0xCF0), - libespm::FormId("Blank.esm", std::vector(), 0xCF1), - libespm::FormId("Blank.esm", std::vector(), 0xCF2), - libespm::FormId("Blank.esm", std::vector(), 0xCF3), - }), plugin1.OverlapFormIDs(plugin2)); - EXPECT_EQ(std::set({ - libespm::FormId("Blank.esm", std::vector(), 0xCF0), - libespm::FormId("Blank.esm", std::vector(), 0xCF1), - libespm::FormId("Blank.esm", std::vector(), 0xCF2), - libespm::FormId("Blank.esm", std::vector(), 0xCF3), - }), plugin2.OverlapFormIDs(plugin1)); -} - -TEST_F(Plugin, CheckInstallValidity) { - loot::Plugin plugin(game, "Blank.esm", false); - plugin.Reqs({ - loot::File("Blank.missing.esm"), - loot::File("Blank.esp"), - loot::File("Blank - Master Dependent.esm"), - }); - plugin.Incs({ - loot::File("Blank - Different.esm"), - loot::File("Skyrim.esm"), - }); - plugin.DirtyInfo({ - loot::PluginDirtyInfo(0x187BE342, 0, 1, 2, "utility1"), - loot::PluginDirtyInfo(0xDEADBEEF, 0, 5, 10, "utility2"), - }); - EXPECT_TRUE(plugin.CheckInstallValidity(game)); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::error, "This plugin requires \"Blank.missing.esm\" to be installed, but it is missing."), - loot::Message(loot::Message::error, "This plugin is incompatible with \"Skyrim.esm\", but both are present."), - loot::PluginDirtyInfo(0x187BE342, 0, 1, 2, "utility1").AsMessage(), - loot::PluginDirtyInfo(0xDEADBEEF, 0, 5, 10, "utility2").AsMessage(), - }), plugin.Messages()); - - plugin = loot::Plugin(game, "Blank - Different Master Dependent.esp", false); - EXPECT_FALSE(plugin.CheckInstallValidity(game)); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::error, "This plugin requires \"Blank - Different.esm\" to be active, but it is inactive."), - }), plugin.Messages()); - - plugin = loot::Plugin(game, "Blank - Different Master Dependent.esp", false); - plugin.Tags({loot::Tag("Filter")}); - EXPECT_FALSE(plugin.CheckInstallValidity(game)); - EXPECT_TRUE(plugin.Messages().empty()); -} - -#endif diff --git a/src/tests/backend/plugin_sorter_test.h b/src/tests/backend/plugin_sorter_test.h new file mode 100644 index 00000000..f053676e --- /dev/null +++ b/src/tests/backend/plugin_sorter_test.h @@ -0,0 +1,242 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2014-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BACKEND_PLUGIN_SORTER +#define LOOT_TEST_BACKEND_PLUGIN_SORTER + +#include "backend/plugin_sorter.h" +#include "tests/base_game_test.h" + +namespace loot { + namespace test { + class PluginSorterTest : public BaseGameTest { + protected: + inline virtual void SetUp() { + BaseGameTest::SetUp(); + + game = Game(GetParam()); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + } + + Game game; + }; + + // Pass an empty first argument, as it's a prefix for the test instantation, + // but we only have the one so no prefix is necessary. + INSTANTIATE_TEST_CASE_P(, + PluginSorterTest, + ::testing::Values( + GameSettings::tes4)); + + TEST_P(PluginSorterTest, sortingWithNoLoadedPluginsShouldReturnAnEmptyList) { + PluginSorter sorter; + std::list sorted = sorter.Sort(game, Language::english); + + EXPECT_TRUE(sorted.empty()); + } + + TEST_P(PluginSorterTest, sortingShouldNotMakeUnnecessaryChangesToAnExistingLoadOrder) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + + PluginSorter ps; + std::list expectedSortedOrder = getLoadOrder(); + + std::list sorted = ps.Sort(game, Language::english); + EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); + + // Check stability. + sorted = ps.Sort(game, Language::english); + EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); + } + + TEST_P(PluginSorterTest, sortingShouldClearExistingGameMessages) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + game.AppendMessage(Message(Message::say, "1")); + ASSERT_FALSE(game.GetMessages().empty()); + + PluginSorter ps; + std::list sorted = ps.Sort(game, Language::english); + EXPECT_TRUE(game.GetMessages().empty()); + } + + TEST_P(PluginSorterTest, failedSortShouldNotClearExistingGameMessages) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + PluginMetadata plugin(blankEsm); + plugin.LoadAfter({File(blankMasterDependentEsm)}); + game.GetUserlist().AddPlugin(plugin); + game.AppendMessage(Message(Message::say, "1")); + ASSERT_FALSE(game.GetMessages().empty()); + + PluginSorter ps; + EXPECT_ANY_THROW(ps.Sort(game, Language::english)); + EXPECT_FALSE(game.GetMessages().empty()); + } + + TEST_P(PluginSorterTest, sortingShouldEvaluateRelativePriorities) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + PluginMetadata plugin(blankDifferentMasterDependentEsp); + plugin.Priority(-100000); + plugin.SetPriorityGlobal(true); + game.GetUserlist().AddPlugin(plugin); + + PluginSorter ps; + std::list expectedSortedOrder({ + masterFile, + blankEsm, + blankDifferentEsm, + blankMasterDependentEsm, + blankDifferentMasterDependentEsm, + blankDifferentMasterDependentEsp, + blankEsp, + blankDifferentEsp, + blankMasterDependentEsp, + blankPluginDependentEsp, + blankDifferentPluginDependentEsp, + }); + + std::list sorted = ps.Sort(game, Language::english); + EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); + } + + TEST_P(PluginSorterTest, sortingWithPrioritiesShouldInheritRecursivelyRegardlessOfEvaluationOrder) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + + // Set Blank.esp's priority. + PluginMetadata plugin(blankEsp); + plugin.Priority(2); + game.GetUserlist().AddPlugin(plugin); + + // Load Blank - Master Dependent.esp after Blank.esp so that it + // inherits Blank.esp's priority. + plugin = PluginMetadata(blankMasterDependentEsp); + plugin.LoadAfter({ + File(blankEsp), + }); + game.GetUserlist().AddPlugin(plugin); + + // Load Blank - Different.esp after Blank - Master Dependent.esp, so + // that it inherits its inherited priority. + plugin = PluginMetadata(blankDifferentEsp); + plugin.LoadAfter({ + File(blankMasterDependentEsp), + }); + game.GetUserlist().AddPlugin(plugin); + + // Set Blank - Different Master Dependent.esp to have a higher priority + // than 0 but lower than Blank.esp. Need to also make it a global priority + // because it doesn't otherwise conflict with the other plugins. + plugin = PluginMetadata(blankDifferentMasterDependentEsp); + plugin.Priority(1); + plugin.SetPriorityGlobal(true); + game.GetUserlist().AddPlugin(plugin); + + PluginSorter ps; + std::list expectedSortedOrder({ + masterFile, + blankEsm, + blankDifferentEsm, + blankMasterDependentEsm, + blankDifferentMasterDependentEsm, + blankDifferentMasterDependentEsp, + blankEsp, + blankMasterDependentEsp, + blankDifferentEsp, + blankPluginDependentEsp, + blankDifferentPluginDependentEsp, + }); + + std::list sorted = ps.Sort(game, Language::english); + EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); + } + + TEST_P(PluginSorterTest, sortingShouldUseLoadAfterMetadataWhenDecidingRelativePluginPositions) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + PluginMetadata plugin(blankEsp); + plugin.LoadAfter({ + File(blankDifferentEsp), + File(blankDifferentPluginDependentEsp), + }); + game.GetUserlist().AddPlugin(plugin); + + PluginSorter ps; + std::list expectedSortedOrder({ + masterFile, + blankEsm, + blankDifferentEsm, + blankMasterDependentEsm, + blankDifferentMasterDependentEsm, + blankDifferentEsp, + blankMasterDependentEsp, + blankDifferentMasterDependentEsp, + blankDifferentPluginDependentEsp, + blankEsp, + blankPluginDependentEsp, + }); + + std::list sorted = ps.Sort(game, Language::english); + EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); + } + + TEST_P(PluginSorterTest, sortingShouldUseRequirementMetadataWhenDecidingRelativePluginPositions) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + PluginMetadata plugin(blankEsp); + plugin.Reqs({ + File(blankDifferentEsp), + File(blankDifferentPluginDependentEsp), + }); + game.GetUserlist().AddPlugin(plugin); + + PluginSorter ps; + std::list expectedSortedOrder({ + masterFile, + blankEsm, + blankDifferentEsm, + blankMasterDependentEsm, + blankDifferentMasterDependentEsm, + blankDifferentEsp, + blankMasterDependentEsp, + blankDifferentMasterDependentEsp, + blankDifferentPluginDependentEsp, + blankEsp, + blankPluginDependentEsp, + }); + + std::list sorted = ps.Sort(game, Language::english); + EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); + } + + TEST_P(PluginSorterTest, sortingShouldThrowIfACyclicInteractionIsEncountered) { + ASSERT_NO_THROW(game.LoadPlugins(false)); + PluginMetadata plugin(blankEsm); + plugin.LoadAfter({File(blankMasterDependentEsm)}); + game.GetUserlist().AddPlugin(plugin); + + PluginSorter ps; + EXPECT_ANY_THROW(ps.Sort(game, Language::english)); + } + } +} + +#endif diff --git a/src/tests/backend/test_masterlist.h b/src/tests/backend/test_masterlist.h deleted file mode 100644 index c1c4fb12..00000000 --- a/src/tests/backend/test_masterlist.h +++ /dev/null @@ -1,152 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_MASTERLIST -#define LOOT_TEST_BACKEND_MASTERLIST - -#include "backend/masterlist.h" -#include "tests/fixtures.h" - -class Masterlist : public SkyrimTest {}; - -TEST_F(Masterlist, Update_Game) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - game.SetRepoURL("https://github.com/loot/testing-metadata.git"); - game.SetRepoBranch("master"); - ASSERT_NO_THROW(game.Init(false, localPath)); - - // This may fail on Windows if a 'real' LOOT install is also present. - loot::Masterlist masterlist; - EXPECT_TRUE(masterlist.Update(game)); - EXPECT_TRUE(boost::filesystem::exists(game.MasterlistPath())); - - EXPECT_FALSE(masterlist.Update(game)); - EXPECT_TRUE(boost::filesystem::exists(game.MasterlistPath())); -} - -TEST_F(Masterlist, Update_NonGame_InvalidPath) { - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.Update(";//\?", - "https://github.com/loot/testing-metadata.git", - "master")); -} - -TEST_F(Masterlist, Update_NonGame_EmptyPath) { - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.Update("", - "https://github.com/loot/testing-metadata.git", - "master")); -} - -TEST_F(Masterlist, Update_NonGame_InvalidBranch) { - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.Update(masterlistPath, - "https://github.com/loot/testing-metadata.git", - "missing-branch")); -} - -TEST_F(Masterlist, Update_NonGame_EmptyBranch) { - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.Update(masterlistPath, - "https://github.com/loot/testing-metadata.git", - "")); -} - -TEST_F(Masterlist, Update_NonGame_InvalidUrl) { - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.Update(masterlistPath, - "https://github.com/loot/does-not-exist.git", - "master")); -} - -TEST_F(Masterlist, Update_NonGame_EmptyUrl) { - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.Update(masterlistPath, - "", - "master")); -} - -TEST_F(Masterlist, Update_NonGame) { - loot::Masterlist masterlist; - EXPECT_TRUE(masterlist.Update(masterlistPath, - "https://github.com/loot/testing-metadata.git", - "master")); - - EXPECT_FALSE(masterlist.Update(masterlistPath, - "https://github.com/loot/testing-metadata.git", - "master")); -} - -TEST_F(Masterlist, GetInfo_NoMasterlist) { - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.GetInfo(masterlistPath, false)); -} - -TEST_F(Masterlist, GetInfo_NoRepository) { - ASSERT_NO_THROW(boost::filesystem::copy("./testing-metadata/masterlist.yaml", masterlistPath)); - - loot::Masterlist masterlist; - EXPECT_ANY_THROW(masterlist.GetInfo(masterlistPath, false)); -} - -TEST_F(Masterlist, GetInfo_LongID) { - loot::Masterlist masterlist; - ASSERT_TRUE(masterlist.Update(masterlistPath, - "https://github.com/loot/testing-metadata.git", - "master")); - - loot::Masterlist::Info info = masterlist.GetInfo(masterlistPath, false); - EXPECT_EQ(40, info.revision.length()); - EXPECT_EQ(10, info.date.length()); -} - -TEST_F(Masterlist, GetInfo_ShortID) { - loot::Masterlist masterlist; - ASSERT_TRUE(masterlist.Update(masterlistPath, - "https://github.com/loot/testing-metadata.git", - "master")); - - loot::Masterlist::Info info = masterlist.GetInfo(masterlistPath, true); - EXPECT_GE((unsigned)40, info.revision.length()); - EXPECT_LE((unsigned)7, info.revision.length()); - EXPECT_EQ(10, info.date.length()); -} - -TEST_F(Masterlist, GetInfo_Edited) { - loot::Masterlist masterlist; - ASSERT_TRUE(masterlist.Update(masterlistPath, - "https://github.com/loot/testing-metadata.git", - "master")); - boost::filesystem::ofstream out(masterlistPath); - out.close(); - - loot::Masterlist::Info info = masterlist.GetInfo(masterlistPath, false); - EXPECT_EQ(49, info.revision.length()); - EXPECT_EQ(" (edited)", info.revision.substr(40)); - EXPECT_EQ(19, info.date.length()); - EXPECT_EQ(" (edited)", info.date.substr(10)); -} - -#endif diff --git a/src/tests/backend/test_metadata_list.h b/src/tests/backend/test_metadata_list.h deleted file mode 100644 index b4bfa8d7..00000000 --- a/src/tests/backend/test_metadata_list.h +++ /dev/null @@ -1,247 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_METADATA_LIST -#define LOOT_TEST_BACKEND_METADATA_LIST - -#include "backend/metadata_list.h" -#include "tests/fixtures.h" - -class MetadataList : public SkyrimTest { -protected: - MetadataList() : - metadataPath("./testing-metadata/masterlist.yaml"), - savedMetadataPath("./testing-metadata/saved.masterlist.yaml"), - invalidMetadataPaths({"./testing-metadata/invalid/non_unique.yaml"}) { - PluginMetadataToString = [](const loot::PluginMetadata& plugin) { - return plugin.Name(); - }; - } - - inline virtual void SetUp() { - SkyrimTest::SetUp(); - - ASSERT_TRUE(boost::filesystem::exists(metadataPath)); - ASSERT_FALSE(boost::filesystem::exists(savedMetadataPath)); - - for (const auto& path : invalidMetadataPaths) { - ASSERT_TRUE(boost::filesystem::exists(path)); - } - } - - inline virtual void TearDown() { - SkyrimTest::TearDown(); - - ASSERT_TRUE(boost::filesystem::exists(metadataPath)); - ASSERT_NO_THROW(boost::filesystem::remove(savedMetadataPath)); - - for (const auto& path : invalidMetadataPaths) { - ASSERT_TRUE(boost::filesystem::exists(path)); - } - } - - const boost::filesystem::path metadataPath; - const boost::filesystem::path savedMetadataPath; - const std::vector invalidMetadataPaths; - - std::function PluginMetadataToString; -}; - -TEST_F(MetadataList, Load) { - loot::MetadataList ml; - EXPECT_NO_THROW(ml.Load(metadataPath)); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "A global message."), - }), ml.Messages()); - - // Non-regex plugins can be outputted in any order, and regex entries can - // match each other, so convert the list to a set of strings for - // comparison. - std::list result(ml.Plugins()); - std::set names; - std::transform(result.begin(), - result.end(), - std::insert_iterator>(names, names.begin()), - PluginMetadataToString); - EXPECT_EQ(std::set({ - "Blank.esm", - "Blank.esp", - "Blank.+\\.esp", - "Blank.+(Different)?.*\\.esp", - }), names); - - EXPECT_ANY_THROW(ml.Load("NotAPlugin.esm")); - EXPECT_TRUE(ml.Messages().empty()); - EXPECT_TRUE(ml.Plugins().empty()); - - // Fill the list again. - ASSERT_NO_THROW(ml.Load(metadataPath)); - - EXPECT_ANY_THROW(ml.Load("Blank.missing.esm")); - EXPECT_TRUE(ml.Messages().empty()); - EXPECT_TRUE(ml.Plugins().empty()); -} - -TEST_F(MetadataList, Load_Invalid) { - loot::MetadataList ml; - for (const auto& path : invalidMetadataPaths) { - EXPECT_ANY_THROW(ml.Load(path)); - } -} - -TEST_F(MetadataList, Save) { - loot::MetadataList ml; - ASSERT_NO_THROW(ml.Load(metadataPath)); - - EXPECT_NO_THROW(ml.Save(savedMetadataPath)); - EXPECT_TRUE(boost::filesystem::exists(savedMetadataPath)); - EXPECT_NO_THROW(ml.Load(savedMetadataPath)); - - EXPECT_EQ(std::list({ - loot::Message(loot::Message::say, "A global message."), - }), ml.Messages()); - - // Non-regex plugins can be outputted in any order, and regex entries can - // match each other, so convert the list to a set of strings for - // comparison. - std::list result(ml.Plugins()); - std::set names; - std::transform(result.begin(), - result.end(), - std::insert_iterator>(names, names.begin()), - PluginMetadataToString); - EXPECT_EQ(std::set({ - "Blank.esm", - "Blank.esp", - "Blank.+\\.esp", - "Blank.+(Different)?.*\\.esp", - }), names); -} - -TEST_F(MetadataList, clear) { - loot::MetadataList ml; - ASSERT_NO_THROW(ml.Load(metadataPath)); - ASSERT_FALSE(ml.Messages().empty()); - ASSERT_FALSE(ml.Plugins().empty()); - - ml.clear(); - EXPECT_TRUE(ml.Messages().empty()); - EXPECT_TRUE(ml.Plugins().empty()); -} - -TEST_F(MetadataList, FindPlugin) { - loot::MetadataList ml; - ASSERT_NO_THROW(ml.Load(metadataPath)); - - loot::PluginMetadata pm = ml.FindPlugin(loot::PluginMetadata("Blank - Different.esm")); - EXPECT_EQ("Blank - Different.esm", pm.Name()); - EXPECT_TRUE(pm.HasNameOnly()); - - pm = ml.FindPlugin(loot::PluginMetadata("Blank - Different.esp")); - EXPECT_EQ("Blank - Different.esp", pm.Name()); - EXPECT_EQ(std::set({ - loot::File("Blank.esm"), - }), pm.LoadAfter()); - EXPECT_EQ(std::set({ - loot::File("Blank.esp"), - }), pm.Incs()); -} - -TEST_F(MetadataList, AddPlugin) { - loot::MetadataList ml; - ASSERT_NO_THROW(ml.Load(metadataPath)); - - loot::PluginMetadata pm = ml.FindPlugin(loot::PluginMetadata("Blank - Different.esm")); - ASSERT_EQ("Blank - Different.esm", pm.Name()); - ASSERT_TRUE(pm.HasNameOnly()); - - pm.Priority(1000); - ml.AddPlugin(pm); - pm = ml.FindPlugin(pm); - EXPECT_EQ("Blank - Different.esm", pm.Name()); - EXPECT_EQ(1000, pm.Priority()); - - pm = loot::PluginMetadata(".+Dependent\\.esp"); - pm.Priority(-10); - ml.AddPlugin(pm); - pm = ml.FindPlugin(loot::PluginMetadata("Blank - Plugin Dependent.esp")); - EXPECT_EQ(-10, pm.Priority()); -} - -TEST_F(MetadataList, AddPlugin_NonUnique) { - loot::MetadataList ml; - ASSERT_NO_THROW(ml.Load(metadataPath)); - - loot::PluginMetadata pm = ml.FindPlugin(loot::PluginMetadata("Blank.esm")); - ASSERT_EQ("Blank.esm", pm.Name()); - ASSERT_FALSE(pm.HasNameOnly()); - - ASSERT_ANY_THROW(ml.AddPlugin(loot::PluginMetadata("Blank.esm"))); -} - -TEST_F(MetadataList, ErasePlugin) { - loot::MetadataList ml; - ASSERT_NO_THROW(ml.Load(metadataPath)); - - loot::PluginMetadata pm = ml.FindPlugin(loot::PluginMetadata("Blank.esp")); - ASSERT_EQ("Blank.esp", pm.Name()); - ASSERT_FALSE(pm.HasNameOnly()); - - ml.ErasePlugin(pm); - pm = ml.FindPlugin(pm); - ASSERT_EQ("Blank.esp", pm.Name()); - ASSERT_TRUE(pm.HasNameOnly()); -} - -TEST_F(MetadataList, EvalAllConditions) { - loot::Game game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - - loot::MetadataList ml; - ASSERT_NO_THROW(ml.Load(metadataPath)); - - loot::PluginMetadata pm = ml.FindPlugin(loot::PluginMetadata("Blank.esm")); - ASSERT_EQ(std::list({ - loot::Message(loot::Message::warn, "This is a warning."), - loot::Message(loot::Message::say, "This message should be removed when evaluating conditions."), - }), pm.Messages()); - - pm = ml.FindPlugin(loot::PluginMetadata("Blank.esp")); - ASSERT_EQ("Blank.esp", pm.Name()); - ASSERT_FALSE(pm.HasNameOnly()); - - EXPECT_NO_THROW(ml.EvalAllConditions(game, loot::Language::english)); - - pm = ml.FindPlugin(loot::PluginMetadata("Blank.esm")); - EXPECT_EQ(std::list({ - loot::Message(loot::Message::warn, "This is a warning."), - }), pm.Messages()); - - pm = ml.FindPlugin(loot::PluginMetadata("Blank.esp")); - EXPECT_EQ("Blank.esp", pm.Name()); - EXPECT_TRUE(pm.HasNameOnly()); -} - -#endif diff --git a/src/tests/backend/test_plugin_sorter.h b/src/tests/backend/test_plugin_sorter.h deleted file mode 100644 index 06bd3be2..00000000 --- a/src/tests/backend/test_plugin_sorter.h +++ /dev/null @@ -1,268 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2014-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_BACKEND_PLUGIN_SORTER -#define LOOT_TEST_BACKEND_PLUGIN_SORTER - -#include "backend/plugin_sorter.h" -#include "tests/fixtures.h" - -class PluginSorter : public SkyrimTest { -protected: - inline virtual void SetUp() { - SkyrimTest::SetUp(); - - game = loot::Game(loot::Game::tes5); - game.SetGamePath(dataPath.parent_path()); - ASSERT_NO_THROW(game.Init(false, localPath)); - } - - inline std::list GetExpectedSortedOrder() const { - return std::list({ - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp", - }); - } - - inline static std::list GetActualSortedOrder(const std::list& sortedPlugins) { - std::list output; - std::transform(begin(sortedPlugins), - end(sortedPlugins), - std::back_inserter(output), - [](const loot::Plugin& plugin) { - return plugin.Name(); - }); - return output; - } - - loot::Game game; - std::function callback; -}; - -TEST_F(PluginSorter, Sort_NoPlugins) { - loot::PluginSorter ps; - std::list sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(sorted.empty()); -} - -TEST_F(PluginSorter, Sort) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - - loot::PluginSorter ps; - std::list expectedSortedOrder = GetExpectedSortedOrder(); - - std::list sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); - - // Check stability. - sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); -} - -TEST_F(PluginSorter, sortingShouldClearExistingGameMessages) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - game.AppendMessage(loot::Message(loot::Message::say, "1")); - ASSERT_FALSE(game.GetMessages().empty()); - - loot::PluginSorter ps; - std::list sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(game.GetMessages().empty()); -} - -TEST_F(PluginSorter, failedSortShouldNotClearExistingGameMessages) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - loot::PluginMetadata plugin("Blank.esm"); - plugin.LoadAfter({loot::File("Blank - Master Dependent.esm")}); - game.GetUserlist().AddPlugin(plugin); - game.AppendMessage(loot::Message(loot::Message::say, "1")); - ASSERT_FALSE(game.GetMessages().empty()); - - loot::PluginSorter ps; - EXPECT_ANY_THROW(ps.Sort(game, loot::Language::english)); - EXPECT_FALSE(game.GetMessages().empty()); -} - -TEST_F(PluginSorter, Sort_HeadersOnly) { - ASSERT_NO_THROW(game.LoadPlugins(true)); - - loot::PluginSorter ps; - std::list expectedSortedOrder = GetExpectedSortedOrder(); - - std::list sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); -} - -TEST_F(PluginSorter, Sort_WithPriority) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - loot::PluginMetadata plugin("Blank - Different Master Dependent.esp"); - plugin.Priority(-100000); - plugin.SetPriorityGlobal(true); - game.GetUserlist().AddPlugin(plugin); - - loot::PluginSorter ps; - std::list expectedSortedOrder({ - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank - Different Master Dependent.esp", - "Blank.esp", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp", - }); - - std::list sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); -} - -TEST_F(PluginSorter, sortingWithPrioritiesShouldInheritRecursivelyRegardlessOfEvaluationOrder) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - - // Set Blank.esp's priority. - loot::PluginMetadata plugin("Blank.esp"); - plugin.Priority(2); - game.GetUserlist().AddPlugin(plugin); - - // Load Blank - Master Dependent.esp after Blank.esp so that it - // inherits Blank.esp's priority. - plugin = loot::PluginMetadata("Blank - Master Dependent.esp"); - plugin.LoadAfter({ - loot::File("Blank.esp"), - }); - game.GetUserlist().AddPlugin(plugin); - - // Load Blank - Different.esp after Blank - Master Dependent.esp, so - // that it inherits its inherited priority. - plugin = loot::PluginMetadata("Blank - Different.esp"); - plugin.LoadAfter({ - loot::File("Blank - Master Dependent.esp"), - }); - game.GetUserlist().AddPlugin(plugin); - - // Set Blank - Different Master Dependent.esp to have a higher priority - // than 0 but lower than Blank.esp. Need to also make it a global priority - // because it doesn't otherwise conflict with the other plugins. - plugin = loot::PluginMetadata("Blank - Different Master Dependent.esp"); - plugin.Priority(1); - plugin.SetPriorityGlobal(true); - game.GetUserlist().AddPlugin(plugin); - - loot::PluginSorter ps; - std::list expectedSortedOrder({ - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank - Different Master Dependent.esp", - "Blank.esp", - "Blank - Master Dependent.esp", - "Blank - Different.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp", - }); - - std::list actualSortedOrder = GetActualSortedOrder(ps.Sort(game, loot::Language::english)); - EXPECT_EQ(expectedSortedOrder, actualSortedOrder); -} - -TEST_F(PluginSorter, Sort_WithLoadAfter) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - loot::PluginMetadata plugin("Blank.esp"); - plugin.LoadAfter({ - loot::File("Blank - Different.esp"), - loot::File("Blank - Different Plugin Dependent.esp"), - }); - game.GetUserlist().AddPlugin(plugin); - - loot::PluginSorter ps; - std::list expectedSortedOrder({ - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Different Plugin Dependent.esp", - "Blank.esp", - "Blank - Plugin Dependent.esp", - }); - - std::list sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); -} - -TEST_F(PluginSorter, Sort_WithRequirements) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - loot::PluginMetadata plugin("Blank.esp"); - plugin.Reqs({ - loot::File("Blank - Different.esp"), - loot::File("Blank - Different Plugin Dependent.esp"), - }); - game.GetUserlist().AddPlugin(plugin); - - loot::PluginSorter ps; - std::list expectedSortedOrder({ - "Skyrim.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", - "Blank - Different Master Dependent.esm", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Different Plugin Dependent.esp", - "Blank.esp", - "Blank - Plugin Dependent.esp", - }); - - std::list sorted = ps.Sort(game, loot::Language::english); - EXPECT_TRUE(std::equal(begin(sorted), end(sorted), begin(expectedSortedOrder))); -} - -TEST_F(PluginSorter, Sort_HasCycle) { - ASSERT_NO_THROW(game.LoadPlugins(false)); - loot::PluginMetadata plugin("Blank.esm"); - plugin.LoadAfter({loot::File("Blank - Master Dependent.esm")}); - game.GetUserlist().AddPlugin(plugin); - - loot::PluginSorter ps; - EXPECT_ANY_THROW(ps.Sort(game, loot::Language::english)); -} - -#endif diff --git a/src/tests/base_game_test.h b/src/tests/base_game_test.h new file mode 100644 index 00000000..eb2d9035 --- /dev/null +++ b/src/tests/base_game_test.h @@ -0,0 +1,244 @@ +/* LOOT + +A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and +Fallout: New Vegas. + +Copyright (C) 2013-2016 WrinklyNinja + +This file is part of LOOT. + +LOOT is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +LOOT is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with LOOT. If not, see +. +*/ + +#ifndef LOOT_TEST_BASE_GAME_TEST +#define LOOT_TEST_BASE_GAME_TEST + +#include "backend/game/game_settings.h" + +#include +#include +#include +#include + +#include + +namespace loot { + namespace test { + class BaseGameTest : public ::testing::TestWithParam { + protected: + BaseGameTest() : + missingPath("./missing"), + dataPath(getPluginsPath()), + localPath(getLocalPath()), + masterFile(getMasterFile()), + missingEsp("Blank.missing.esp"), + blankEsm("Blank.esm"), + blankDifferentEsm("Blank - Different.esm"), + blankMasterDependentEsm("Blank - Master Dependent.esm"), + blankDifferentMasterDependentEsm("Blank - Different Master Dependent.esm"), + blankEsp("Blank.esp"), + blankDifferentEsp("Blank - Different.esp"), + blankMasterDependentEsp("Blank - Master Dependent.esp"), + blankDifferentMasterDependentEsp("Blank - Different Master Dependent.esp"), + blankPluginDependentEsp("Blank - Plugin Dependent.esp"), + blankDifferentPluginDependentEsp("Blank - Different Plugin Dependent.esp"), + blankEsmCrc(getBlankEsmCrc()) {} + + inline virtual void SetUp() { + ASSERT_NO_THROW(boost::filesystem::create_directories(localPath)); + ASSERT_TRUE(boost::filesystem::exists(localPath)); + + ASSERT_FALSE(boost::filesystem::exists(missingPath)); + ASSERT_FALSE(boost::filesystem::exists(dataPath / missingEsp)); + + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankEsm)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentEsm)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankMasterDependentEsm)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentMasterDependentEsm)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankEsp)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentEsp)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankMasterDependentEsp)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentMasterDependentEsp)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankPluginDependentEsp)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentPluginDependentEsp)); + + // Make sure the game master file exists. + ASSERT_FALSE(boost::filesystem::exists(dataPath / masterFile)); + ASSERT_NO_THROW(boost::filesystem::copy_file(dataPath / blankEsm, dataPath / masterFile)); + ASSERT_TRUE(boost::filesystem::exists(dataPath / masterFile)); + + // Set initial load order and active plugins. + setLoadOrder(getInitialLoadOrder()); + setActivePlugins(getInitialActivePlugins()); + + // Ghost a plugin. + ASSERT_FALSE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost"))); + ASSERT_NO_THROW(boost::filesystem::rename(dataPath / blankMasterDependentEsm, dataPath / (blankMasterDependentEsm + ".ghost"))); + ASSERT_TRUE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost"))); + } + + inline virtual void TearDown() { + ASSERT_NO_THROW(boost::filesystem::remove_all(localPath)); + + ASSERT_NO_THROW(boost::filesystem::remove(dataPath / masterFile)); + + // Unghost the ghosted plugin. + ASSERT_TRUE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost"))); + ASSERT_NO_THROW(boost::filesystem::rename(dataPath / (blankMasterDependentEsm + ".ghost"), dataPath / blankMasterDependentEsm)); + ASSERT_FALSE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost"))); + } + + inline std::list getLoadOrder() { + std::list actual; + if (isLoadOrderTimestampBased(GetParam())) { + std::map loadOrder; + for (boost::filesystem::directory_iterator it(dataPath); it != boost::filesystem::directory_iterator(); ++it) { + if (boost::filesystem::is_regular_file(it->status())) { + std::string filename = it->path().filename().string(); + if (boost::ends_with(filename, ".ghost")) + filename = it->path().stem().string(); + if (boost::ends_with(filename, ".esp") || boost::ends_with(filename, ".esm")) + loadOrder.emplace(boost::filesystem::last_write_time(it->path()), filename); + } + } + for (const auto& plugin : loadOrder) + actual.push_back(plugin.second); + } + else { + boost::filesystem::ifstream in(localPath / "loadorder.txt"); + while (in) { + std::string line; + std::getline(in, line); + + if (!line.empty()) + actual.push_back(line); + } + } + + return actual; + } + + inline std::vector getInitialLoadOrder() const { + return std::vector({ + masterFile, + blankEsm, + blankDifferentEsm, + blankMasterDependentEsm, + blankDifferentMasterDependentEsm, + blankEsp, + blankDifferentEsp, + blankMasterDependentEsp, + blankDifferentMasterDependentEsp, + blankPluginDependentEsp, + blankDifferentPluginDependentEsp, + }); + } + + inline std::unordered_set getInitialActivePlugins() const { + return std::unordered_set({ + masterFile, + blankEsm, + blankDifferentMasterDependentEsp, + }); + } + + const boost::filesystem::path missingPath; + const boost::filesystem::path dataPath; + const boost::filesystem::path localPath; + + const std::string masterFile; + const std::string missingEsp; + const std::string blankEsm; + const std::string blankDifferentEsm; + const std::string blankMasterDependentEsm; + const std::string blankDifferentMasterDependentEsm; + const std::string blankEsp; + const std::string blankDifferentEsp; + const std::string blankMasterDependentEsp; + const std::string blankDifferentMasterDependentEsp; + const std::string blankPluginDependentEsp; + const std::string blankDifferentPluginDependentEsp; + + const uint32_t blankEsmCrc; + + private: + inline boost::filesystem::path getLocalPath() const { + if (GetParam() == GameSettings::tes4) + return "./local/Oblivion"; + else + return "./local/Skyrim"; + } + + inline boost::filesystem::path getPluginsPath() const { + if (GetParam() == GameSettings::tes4) + return "./Oblivion/Data"; + else + return "./Skyrim/Data"; + } + + inline std::string getMasterFile() const { + if (GetParam() == GameSettings::tes4) + return "Oblivion.esm"; + else if (GetParam() == GameSettings::tes5) + return "Skyrim.esm"; + else if (GetParam() == GameSettings::fo3) + return "Fallout3.esm"; + else if (GetParam() == GameSettings::fonv) + return "FalloutNV.esm"; + else + return "Fallout4.esm"; + } + + inline uint32_t getBlankEsmCrc() const { + if (GetParam() == GameSettings::tes4) + return 0x374E2A6F; + else + return 0x187BE342; + } + + inline void setLoadOrder(const std::vector& loadOrder) { + if (isLoadOrderTimestampBased(GetParam())) { + time_t modificationTime = time(NULL); // Current time. + for (const auto &plugin : loadOrder) { + if (boost::filesystem::exists(dataPath / boost::filesystem::path(plugin + ".ghost"))) { + boost::filesystem::last_write_time(dataPath / boost::filesystem::path(plugin + ".ghost"), modificationTime); + } + else { + boost::filesystem::last_write_time(dataPath / plugin, modificationTime); + } + modificationTime += 60; + } + } + else { + boost::filesystem::ofstream out(localPath / "loadorder.txt"); + for (const auto &plugin : loadOrder) + out << plugin << std::endl; + } + } + + inline void setActivePlugins(const std::unordered_set& activePlugins) { + boost::filesystem::ofstream out(localPath / "plugins.txt"); + for (const auto &plugin : activePlugins) + out << plugin << std::endl; + } + + inline static bool isLoadOrderTimestampBased(unsigned int gameId) { + return gameId == GameSettings::tes4 || gameId == GameSettings::fo3 || gameId == GameSettings::fonv; + } + }; + } +} + +#endif diff --git a/src/tests/fixtures.h b/src/tests/fixtures.h deleted file mode 100644 index 7073e608..00000000 --- a/src/tests/fixtures.h +++ /dev/null @@ -1,317 +0,0 @@ -/* LOOT - -A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and -Fallout: New Vegas. - -Copyright (C) 2013-2016 WrinklyNinja - -This file is part of LOOT. - -LOOT is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -LOOT is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LOOT. If not, see -. -*/ - -#ifndef LOOT_TEST_FIXTURES -#define LOOT_TEST_FIXTURES - -#include "printers.h" - -#include - -#include -#include - -class GameTest : public ::testing::Test { -protected: - GameTest(const boost::filesystem::path& gameDataPath, const boost::filesystem::path& gameLocalPath) - : dataPath(gameDataPath), - localPath(gameLocalPath), - missingPath("./missing"), - masterlistPath(localPath / "masterlist.yaml"), - userlistPath(localPath / "userlist.yaml"), - resourcePath(dataPath / "resource" / "detail" / "resource.txt"), - db(nullptr) {} - - inline virtual void SetUp() { - ASSERT_NO_THROW(boost::filesystem::create_directories(localPath)); - ASSERT_TRUE(boost::filesystem::exists(localPath)); - - ASSERT_FALSE(boost::filesystem::exists(masterlistPath)); - ASSERT_FALSE(boost::filesystem::exists(userlistPath)); - ASSERT_FALSE(boost::filesystem::exists(localPath / ".git")); - ASSERT_FALSE(boost::filesystem::exists(missingPath)); - - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank.esm")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Different.esm")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Master Dependent.esm")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Different Master Dependent.esm")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank.esp")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Different.esp")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Master Dependent.esp")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Different Master Dependent.esp")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Plugin Dependent.esp")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Different Plugin Dependent.esp")); - - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Blank.missing.esm")); - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Blank.missing.esp")); - - // Ghost a plugin. - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Blank - Master Dependent.esm.ghost")); - ASSERT_NO_THROW(boost::filesystem::rename(dataPath / "Blank - Master Dependent.esm", dataPath / "Blank - Master Dependent.esm.ghost")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Master Dependent.esm.ghost")); - - // Write out an empty file. - boost::filesystem::ofstream out(dataPath / "EmptyFile.esm"); - out.close(); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "EmptyFile.esm")); - - // Write out an empty resource file. - ASSERT_NO_THROW(boost::filesystem::create_directories(resourcePath.parent_path())); - out.open(resourcePath); - out.close(); - ASSERT_TRUE(boost::filesystem::exists(resourcePath)); - - // Write out an non-empty, non-plugin file. - out.open(dataPath / "NotAPlugin.esm"); - out << "This isn't a valid plugin file."; - out.close(); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "NotAPlugin.esm")); - } - - inline virtual void TearDown() { - // Unghost the ghosted plugin. - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank - Master Dependent.esm.ghost")); - ASSERT_NO_THROW(boost::filesystem::rename(dataPath / "Blank - Master Dependent.esm.ghost", dataPath / "Blank - Master Dependent.esm")); - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Blank - Master Dependent.esm.ghost")); - - // Delete generated files. - ASSERT_NO_THROW(boost::filesystem::remove(dataPath / "EmptyFile.esm")); - ASSERT_NO_THROW(boost::filesystem::remove(resourcePath)); - ASSERT_NO_THROW(boost::filesystem::remove(dataPath / "NotAPlugin.esm")); - ASSERT_FALSE(boost::filesystem::exists(dataPath / "EmptyFile.esm")); - ASSERT_FALSE(boost::filesystem::exists(resourcePath)); - ASSERT_FALSE(boost::filesystem::exists(dataPath / "NotAPlugin.esm")); - - // Masterlist & userlist may have been created during test, so delete them. - ASSERT_NO_THROW(boost::filesystem::remove(masterlistPath)); - ASSERT_NO_THROW(boost::filesystem::remove(userlistPath)); - - // Also remove the ".git" folder if it has been created. - ASSERT_NO_THROW(boost::filesystem::remove_all(localPath / ".git")); - - ASSERT_NO_THROW(loot_destroy_db(db)); - } - - const boost::filesystem::path dataPath; - const boost::filesystem::path localPath; - const boost::filesystem::path missingPath; - - const boost::filesystem::path masterlistPath; - const boost::filesystem::path userlistPath; - - const boost::filesystem::path resourcePath; - - loot_db * db; -}; - -class OblivionTest : public GameTest { -protected: - OblivionTest() : GameTest("./Oblivion/Data", "./local/Oblivion") {} - - inline virtual void SetUp() { - GameTest::SetUp(); - - // LOOT expects the game master file to be present, so mock it. - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Oblivion.esm")); - ASSERT_NO_THROW(boost::filesystem::copy_file(dataPath / "Blank.esm", dataPath / "Oblivion.esm")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Oblivion.esm")); - - // Oblivion's load order is decided through timestamps, so reset them to a known order before each test. - std::list loadOrder = { - "Oblivion.esm", - "Blank.esm", - "Blank - Different.esm", - "Blank - Master Dependent.esm", // Ghosted - "Blank - Different Master Dependent.esm", - "Blank.esp", - "Blank - Different.esp", - "Blank - Master Dependent.esp", - "Blank - Different Master Dependent.esp", - "Blank - Plugin Dependent.esp", - "Blank - Different Plugin Dependent.esp" - }; - time_t modificationTime = time(NULL); // Current time. - for (const auto &plugin : loadOrder) { - if (boost::filesystem::exists(dataPath / boost::filesystem::path(plugin + ".ghost"))) { - boost::filesystem::last_write_time(dataPath / boost::filesystem::path(plugin + ".ghost"), modificationTime); - } - else { - boost::filesystem::last_write_time(dataPath / plugin, modificationTime); - } - modificationTime += 60; - } - - // Set Oblivion's active plugins to a known list before running the test. - boost::filesystem::ofstream activePlugins(localPath / "plugins.txt"); - activePlugins - << "Oblivion.esm" << std::endl - << "Blank.esm" << std::endl; - activePlugins.close(); - } - - inline virtual void TearDown() { - GameTest::TearDown(); - - // Delete the mock Oblivion.esm. - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Oblivion.esm")); - ASSERT_NO_THROW(boost::filesystem::remove(dataPath / "Oblivion.esm")); - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Oblivion.esm")); - - // Delete existing plugins.txt. - ASSERT_NO_THROW(boost::filesystem::remove(localPath / "plugins.txt")); - }; - - inline void GenerateMasterlist() { - boost::filesystem::ofstream masterlist(masterlistPath); - masterlist - << "plugins:" << std::endl - << " - name: Oblivion.esm" << std::endl - << " - name: Silgrad_Tower.esm" << std::endl - << " - name: No Lights Flicker.esm" << std::endl - << " msg:" << std::endl - << " - type: say" << std::endl - << " content: Use Wrye Bash Bashed Patch tweak instead." << std::endl - << " - name: bookplacing.esm" << std::endl - << " msg:" << std::endl - << " - type: warn" << std::endl - << " content: 'Check you are using v2+. If not, Update. v1 has a severe bug with the Mystic Emporium disappearing.'" << std::endl - << " - name: EnhancedWeatherSIOnly.esm" << std::endl - << " msg:" << std::endl - << " - type: error" << std::endl - << " content: Obsolete. Remove this and install Enhanced Weather." << std::endl - << " - name: Hammerfell.esm" << std::endl - << " dirty:" << std::endl - << " - crc: 0x7d22f9df" << std::endl - << " util: TES4Edit" << std::endl - << " udr: 4" << std::endl - << " - name: nVidia Black Screen Fix.esp" << std::endl - << " msg:" << std::endl - << " - type: say" << std::endl - << " content: Use Wrye Bash Bashed Patch tweak instead." << std::endl - << " - type: say" << std::endl - << " content: 'Alternatively, remove this and use UOP v3.0.1+ instead.'" << std::endl - << " - name: Unofficial Oblivion Patch.esp" << std::endl - << " msg:" << std::endl - << " - type: say" << std::endl - << " content: 'Do not clean ITM records, they are intentional and required for the mod to function.'" << std::endl - << " tag:" << std::endl - << " - Actors.ACBS" << std::endl - << " - Actors.AIData" << std::endl - << " - Actors.AIPackages" << std::endl - << " - Actors.CombatStyle" << std::endl - << " - Actors.DeathItem" << std::endl - << " - Actors.Stats" << std::endl - << " - C.Climate" << std::endl - << " - C.Light" << std::endl - << " - C.Music" << std::endl - << " - C.Name" << std::endl - << " - C.Owner" << std::endl - << " - Creatures.Blood" << std::endl - << " - Delev" << std::endl - << " - Factions" << std::endl - << " - Invent" << std::endl - << " - Names" << std::endl - << " - NPC.Class" << std::endl - << " - Relations" << std::endl - << " - Relev" << std::endl - << " - Scripts" << std::endl - << " - Stats" << std::endl - << " - '-C.Water'" << std::endl; - - masterlist.close(); - } -}; - -class OblivionAPIOperationsTest : public OblivionTest { -protected: - inline virtual void SetUp() { - OblivionTest::SetUp(); - - ASSERT_EQ(loot_ok, loot_create_db(&db, loot_game_tes4, dataPath.parent_path().string().c_str(), localPath.string().c_str())); - } -}; - -class SkyrimTest : public GameTest { -protected: - SkyrimTest() : GameTest("./Skyrim/Data", "./local/Skyrim") {} - - inline virtual void SetUp() { - GameTest::SetUp(); - - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank.bsa")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Blank.bsl")); - - // Can't change Skyrim's main master file, so mock it. - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Skyrim.esm")); - ASSERT_NO_THROW(boost::filesystem::copy_file(dataPath / "Blank.esm", dataPath / "Skyrim.esm")); - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Skyrim.esm")); - - // Set Skyrim's load order to a known list before running the test. - boost::filesystem::ofstream loadOrder(localPath / "loadorder.txt"); - loadOrder - << "Skyrim.esm" << std::endl - << "Blank.esm" << std::endl - << "Blank - Different.esm" << std::endl - << "Blank - Master Dependent.esm" << std::endl // Ghosted - << "Blank - Different Master Dependent.esm" << std::endl - << "Blank.esp" << std::endl - << "Blank - Different.esp" << std::endl - << "Blank - Master Dependent.esp" << std::endl - << "Blank - Different Master Dependent.esp" << std::endl - << "Blank - Plugin Dependent.esp" << std::endl - << "Blank - Different Plugin Dependent.esp" << std::endl; - loadOrder.close(); - - // Set Skyrim's active plugins to a known list before running the test. - boost::filesystem::ofstream activePlugins(localPath / "plugins.txt"); - activePlugins - << "Blank.esm" << std::endl - << "Blank - Different Master Dependent.esp" << std::endl; - activePlugins.close(); - } - - inline virtual void TearDown() { - GameTest::TearDown(); - - // Delete the mock Skyrim.esm. - ASSERT_TRUE(boost::filesystem::exists(dataPath / "Skyrim.esm")); - ASSERT_NO_THROW(boost::filesystem::remove(dataPath / "Skyrim.esm")); - ASSERT_FALSE(boost::filesystem::exists(dataPath / "Skyrim.esm")); - - // Delete existing plugins.txt and loadorder.txt. - ASSERT_NO_THROW(boost::filesystem::remove(localPath / "plugins.txt")); - ASSERT_NO_THROW(boost::filesystem::remove(localPath / "loadorder.txt")); - }; -}; - -class SkyrimAPIOperationsTest : public SkyrimTest { -protected: - inline virtual void SetUp() { - SkyrimTest::SetUp(); - - ASSERT_EQ(loot_ok, loot_create_db(&db, loot_game_tes5, dataPath.parent_path().string().c_str(), localPath.string().c_str())); - } -}; - -#endif diff --git a/src/tests/gui/test_loot_settings.h b/src/tests/gui/loot_settings_test.h similarity index 87% rename from src/tests/gui/test_loot_settings.h rename to src/tests/gui/loot_settings_test.h index dfd11cb4..d9a4a44b 100644 --- a/src/tests/gui/test_loot_settings.h +++ b/src/tests/gui/loot_settings_test.h @@ -30,19 +30,19 @@ along with LOOT. If not, see namespace loot { namespace test { - class LootSettings : public ::testing::Test { + class LootSettingsTest : public ::testing::Test { protected: - LootSettings() : settingsFile("./settings.yaml") {} + LootSettingsTest() : settingsFile("./settings.yaml") {} - ~LootSettings() { + ~LootSettingsTest() { boost::filesystem::remove(settingsFile); } boost::filesystem::path settingsFile; - loot::LootSettings settings; + LootSettings settings; }; - TEST_F(LootSettings, defaultConstructorShouldSetDefaultValues) { + TEST_F(LootSettingsTest, defaultConstructorShouldSetDefaultValues) { const std::string currentVersion = std::to_string(g_version_major) + "." + std::to_string(g_version_minor) + "." + std::to_string(g_version_patch); const std::vector expectedGameSettings({ GameSettings(GameSettings::tes4), @@ -109,7 +109,7 @@ namespace loot { EXPECT_EQ(expectedGameSettings[5].RepoBranch(), actualGameSettings[5].RepoBranch()); } - TEST_F(LootSettings, loadingFromFileShouldLoadContentAsYaml) { + TEST_F(LootSettingsTest, loadingFromFileShouldLoadContentAsYaml) { boost::filesystem::ofstream out(settingsFile); out << "enableDebugLogging: true" << std::endl; out.close(); @@ -119,7 +119,7 @@ namespace loot { EXPECT_TRUE(settings.isDebugLoggingEnabled()); } - TEST_F(LootSettings, loadingFromYamlShouldStoreLoadedValues) { + TEST_F(LootSettingsTest, loadingFromYamlShouldStoreLoadedValues) { const bool enableDebugLogging = true; const bool updateMasterlist = true; const std::string game = "Oblivion"; @@ -174,12 +174,12 @@ namespace loot { EXPECT_EQ(games[0].Name(), settings.getGameSettings()[0].Name()); } - TEST_F(LootSettings, loadingFromEmptyYamlShouldNotThrow) { + TEST_F(LootSettingsTest, loadingFromEmptyYamlShouldNotThrow) { YAML::Node yaml; EXPECT_NO_THROW(settings.load(yaml)); } - TEST_F(LootSettings, loadingFromYamlShouldUpgradeFromVersion0Point6Format) { + TEST_F(LootSettingsTest, loadingFromYamlShouldUpgradeFromVersion0Point6Format) { const unsigned int DebugVerbosity = 3; const bool UpdateMasterlist = true; const std::string Game = "Oblivion"; @@ -215,7 +215,7 @@ namespace loot { EXPECT_EQ(Games[0].RepoBranch(), settings.getGameSettings()[0].RepoBranch()); } - TEST_F(LootSettings, loadingFromYamlShouldNotUpgradeVersion0Point6SettingsIfEquivalentsAlreadyExist) { + TEST_F(LootSettingsTest, loadingFromYamlShouldNotUpgradeVersion0Point6SettingsIfEquivalentsAlreadyExist) { const unsigned int DebugVerbosity = 3; const bool enableDebugLogging = false; const bool UpdateMasterlist = true; @@ -264,7 +264,7 @@ namespace loot { EXPECT_EQ(games[0].Name(), settings.getGameSettings()[0].Name()); } - TEST_F(LootSettings, loadingFromYamlShouldUpgradeOldDefaultGameRepositoryBranches) { + TEST_F(LootSettingsTest, loadingFromYamlShouldUpgradeOldDefaultGameRepositoryBranches) { const std::vector games({GameSettings(GameSettings::tes4)}); YAML::Node inputYaml; @@ -276,7 +276,7 @@ namespace loot { EXPECT_EQ(games[0].RepoBranch(), settings.getGameSettings()[0].RepoBranch()); } - TEST_F(LootSettings, loadingFromYamlShouldNotUpgradeNonDefaultGameRepositoryBranches) { + TEST_F(LootSettingsTest, loadingFromYamlShouldNotUpgradeNonDefaultGameRepositoryBranches) { const std::vector games({GameSettings(GameSettings::tes4)}); YAML::Node inputYaml; @@ -288,7 +288,7 @@ namespace loot { EXPECT_EQ("foo", settings.getGameSettings()[0].RepoBranch()); } - TEST_F(LootSettings, loadingFromYamlShouldAddMissingBaseGames) { + TEST_F(LootSettingsTest, loadingFromYamlShouldAddMissingBaseGames) { const std::vector games({GameSettings(GameSettings::tes4)}); YAML::Node inputYaml; inputYaml["games"] = games; @@ -305,7 +305,7 @@ namespace loot { EXPECT_EQ(expectedGameSettings, settings.getGameSettings()); } - TEST_F(LootSettings, loadingFromYamlShouldSkipUnrecognisedGames) { + TEST_F(LootSettingsTest, loadingFromYamlShouldSkipUnrecognisedGames) { YAML::Node inputYaml; inputYaml["games"][0] = GameSettings(GameSettings::tes4); inputYaml["games"][0]["type"] = "Foobar"; @@ -317,14 +317,14 @@ namespace loot { EXPECT_EQ("Game Name", settings.getGameSettings()[0].Name()); } - TEST_F(LootSettings, loadingFromYamlShouldRemoveTheContentFilterSetting) { + TEST_F(LootSettingsTest, loadingFromYamlShouldRemoveTheContentFilterSetting) { YAML::Node inputYaml; inputYaml["filters"]["contentFilter"] = "foo"; settings.load(inputYaml); } - TEST_F(LootSettings, saveShouldWriteSettingsAsYamlToPassedFile) { + TEST_F(LootSettingsTest, saveShouldWriteSettingsAsYamlToPassedFile) { settings.storeLastGame("Skyrim"); settings.save(settingsFile); @@ -334,7 +334,7 @@ namespace loot { EXPECT_EQ("Skyrim", settings.getLastGame()); } - TEST_F(LootSettings, getLanguageShouldReturnTheCurrentValue) { + TEST_F(LootSettingsTest, getLanguageShouldReturnTheCurrentValue) { YAML::Node inputYaml; inputYaml["language"] = "fr"; @@ -343,71 +343,71 @@ namespace loot { EXPECT_EQ("fr", settings.getLanguage().Locale()); } - TEST_F(LootSettings, isWindowPositionStoredShouldReturnFalseIfAllPositionValuesAreZero) { - loot::LootSettings::WindowPosition position; + TEST_F(LootSettingsTest, isWindowPositionStoredShouldReturnFalseIfAllPositionValuesAreZero) { + LootSettings::WindowPosition position; settings.storeWindowPosition(position); EXPECT_FALSE(settings.isWindowPositionStored()); } - TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfTopPositionValueIsNonZero) { - loot::LootSettings::WindowPosition position; + TEST_F(LootSettingsTest, isWindowPositionStoredShouldReturnTrueIfTopPositionValueIsNonZero) { + LootSettings::WindowPosition position; position.top = 1; settings.storeWindowPosition(position); EXPECT_TRUE(settings.isWindowPositionStored()); } - TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfBottomPositionValueIsNonZero) { - loot::LootSettings::WindowPosition position; + TEST_F(LootSettingsTest, isWindowPositionStoredShouldReturnTrueIfBottomPositionValueIsNonZero) { + LootSettings::WindowPosition position; position.bottom = 1; settings.storeWindowPosition(position); EXPECT_TRUE(settings.isWindowPositionStored()); } - TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfLeftPositionValueIsNonZero) { - loot::LootSettings::WindowPosition position; + TEST_F(LootSettingsTest, isWindowPositionStoredShouldReturnTrueIfLeftPositionValueIsNonZero) { + LootSettings::WindowPosition position; position.left = 1; settings.storeWindowPosition(position); EXPECT_TRUE(settings.isWindowPositionStored()); } - TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfRightPositionValueIsNonZero) { - loot::LootSettings::WindowPosition position; + TEST_F(LootSettingsTest, isWindowPositionStoredShouldReturnTrueIfRightPositionValueIsNonZero) { + LootSettings::WindowPosition position; position.right = 1; settings.storeWindowPosition(position); EXPECT_TRUE(settings.isWindowPositionStored()); } - TEST_F(LootSettings, storeGameSettingsShouldReplaceExistingGameSettings) { + TEST_F(LootSettingsTest, storeGameSettingsShouldReplaceExistingGameSettings) { const std::vector gameSettings({GameSettings(GameSettings::tes5)}); settings.storeGameSettings(gameSettings); EXPECT_EQ(gameSettings, settings.getGameSettings()); } - TEST_F(LootSettings, storeLastGameShouldReplaceExistingValue) { + TEST_F(LootSettingsTest, storeLastGameShouldReplaceExistingValue) { settings.storeLastGame("Fallout3"); EXPECT_EQ("Fallout3", settings.getLastGame()); } - TEST_F(LootSettings, storeWindowPositionShouldReplaceExistingValue) { - loot::LootSettings::WindowPosition expectedPosition; + TEST_F(LootSettingsTest, storeWindowPositionShouldReplaceExistingValue) { + LootSettings::WindowPosition expectedPosition; expectedPosition.top = 1; settings.storeWindowPosition(expectedPosition); - loot::LootSettings::WindowPosition actualPosition = settings.getWindowPosition(); + LootSettings::WindowPosition actualPosition = settings.getWindowPosition(); EXPECT_EQ(expectedPosition.top, actualPosition.top); EXPECT_EQ(expectedPosition.bottom, actualPosition.bottom); EXPECT_EQ(expectedPosition.left, actualPosition.left); EXPECT_EQ(expectedPosition.right, actualPosition.right); } - TEST_F(LootSettings, updateLastVersionShouldSetValueToCurrentLootVersion) { + TEST_F(LootSettingsTest, updateLastVersionShouldSetValueToCurrentLootVersion) { const std::string currentVersion = std::to_string(g_version_major) + "." + std::to_string(g_version_minor) + "." + std::to_string(g_version_patch); YAML::Node inputYaml; inputYaml["lastVersion"] = "v0.7.1"; @@ -418,7 +418,7 @@ namespace loot { EXPECT_EQ(currentVersion, settings.getLastVersion()); } - TEST_F(LootSettings, toYamlShouldOutputStoredSettings) { + TEST_F(LootSettingsTest, toYamlShouldOutputStoredSettings) { const bool enableDebugLogging = true; const bool updateMasterlist = true; const std::string game = "Oblivion"; diff --git a/src/tests/gui/test_loot_state.h b/src/tests/gui/loot_state_test.h similarity index 74% rename from src/tests/gui/test_loot_state.h rename to src/tests/gui/loot_state_test.h index 6799cd56..8601c436 100644 --- a/src/tests/gui/test_loot_state.h +++ b/src/tests/gui/loot_state_test.h @@ -27,44 +27,44 @@ along with LOOT. If not, see #include "gui/loot_state.h" -#include "tests/fixtures.h" +#include namespace loot { namespace test { - class LootState : public ::testing::Test { + class LootStateTest : public ::testing::Test { protected: - loot::LootState lootState; + LootState lootState; }; - TEST_F(LootState, hasUnappliedChangesShouldBeFalseByDefault) { + TEST_F(LootStateTest, hasUnappliedChangesShouldBeFalseByDefault) { EXPECT_FALSE(lootState.hasUnappliedChanges()); } - TEST_F(LootState, shouldNotHaveUnappliedChangesIfCounterIsDeccremented) { + TEST_F(LootStateTest, shouldNotHaveUnappliedChangesIfCounterIsDeccremented) { lootState.decrementUnappliedChangeCounter(); EXPECT_FALSE(lootState.hasUnappliedChanges()); } - TEST_F(LootState, shouldHaveUnappliedChangesIfCounterIsIncremented) { + TEST_F(LootStateTest, shouldHaveUnappliedChangesIfCounterIsIncremented) { lootState.incrementUnappliedChangeCounter(); EXPECT_TRUE(lootState.hasUnappliedChanges()); } - TEST_F(LootState, incrementingTheChangeCounterMoreThanItIsDecrementedShouldLeaveUnappliedChanges) { + TEST_F(LootStateTest, incrementingTheChangeCounterMoreThanItIsDecrementedShouldLeaveUnappliedChanges) { lootState.incrementUnappliedChangeCounter(); lootState.incrementUnappliedChangeCounter(); lootState.decrementUnappliedChangeCounter(); EXPECT_TRUE(lootState.hasUnappliedChanges()); } - TEST_F(LootState, incrementingTheChangeCounterLessThanItIsDecrementedShouldLeaveNoUnappliedChanges) { + TEST_F(LootStateTest, incrementingTheChangeCounterLessThanItIsDecrementedShouldLeaveNoUnappliedChanges) { lootState.incrementUnappliedChangeCounter(); lootState.decrementUnappliedChangeCounter(); lootState.decrementUnappliedChangeCounter(); EXPECT_FALSE(lootState.hasUnappliedChanges()); } - TEST_F(LootState, incrementingTheChangeCounterThenDecrementingItEquallyShouldLeaveNoUnappliedChanges) { + TEST_F(LootStateTest, incrementingTheChangeCounterThenDecrementingItEquallyShouldLeaveNoUnappliedChanges) { lootState.incrementUnappliedChangeCounter(); lootState.incrementUnappliedChangeCounter(); lootState.decrementUnappliedChangeCounter(); diff --git a/src/tests/main.cpp b/src/tests/main.cpp index 0eaabece..a7db99bb 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -27,36 +27,48 @@ #define BOOST_NO_CXX11_SCOPED_ENUMS #endif +#include "api/loot_apply_load_order_test.h" +#include "api/loot_create_db_test.h" +#include "api/loot_db_test.h" +#include "api/loot_eval_lists_test.h" +#include "api/loot_get_dirty_info_test.h" +#include "api/loot_get_masterlist_revision_test.h" +#include "api/loot_get_plugin_messages_test.h" +#include "api/loot_get_plugin_tags_test.h" +#include "api/loot_get_tag_map_test.h" +#include "api/loot_load_lists_test.h" +#include "api/loot_sort_plugins_test.h" +#include "api/loot_update_masterlist_test.h" +#include "api/loot_write_minimal_list_test.h" #include "api/test_api.h" -#include "api/test_loot_db.h" -#include "backend/game/test_game.h" -#include "backend/game/test_game_cache.h" -#include "backend/game/test_game_settings.h" -#include "backend/game/test_load_order_handler.h" -#include "backend/helpers/test_git_helper.h" -#include "backend/helpers/test_helpers.h" -#include "backend/helpers/test_language.h" -#include "backend/helpers/test_version.h" -#include "backend/helpers/test_yaml_set_helpers.h" -#include "backend/metadata/test_condition_grammar.h" -#include "backend/metadata/test_conditional_metadata.h" -#include "backend/metadata/test_file.h" -#include "backend/metadata/test_location.h" -#include "backend/metadata/test_message.h" -#include "backend/metadata/test_message_content.h" -#include "backend/metadata/test_plugin_dirty_info.h" -#include "backend/metadata/test_plugin_metadata.h" -#include "backend/metadata/test_tag.h" -#include "backend/plugin/test_plugin.h" -#include "backend/test_metadata_list.h" -#include "backend/test_masterlist.h" -#include "backend/test_plugin_sorter.h" -#include "gui/test_loot_settings.h" -#include "gui/test_loot_state.h" +#include "backend/game/game_test.h" +#include "backend/game/game_cache_test.h" +#include "backend/game/game_settings_test.h" +#include "backend/game/load_order_handler_test.h" +#include "backend/helpers/git_helper_test.h" +#include "backend/helpers/helpers_test.h" +#include "backend/helpers/language_test.h" +#include "backend/helpers/version_test.h" +#include "backend/helpers/yaml_set_helpers_test.h" +#include "backend/metadata/condition_grammar_test.h" +#include "backend/metadata/conditional_metadata_test.h" +#include "backend/metadata/file_test.h" +#include "backend/metadata/location_test.h" +#include "backend/metadata/message_test.h" +#include "backend/metadata/message_content_test.h" +#include "backend/metadata/plugin_dirty_info_test.h" +#include "backend/metadata/plugin_metadata_test.h" +#include "backend/metadata/tag_test.h" +#include "backend/plugin/plugin_test.h" +#include "backend/masterlist_test.h" +#include "backend/metadata_list_test.h" +#include "backend/plugin_sorter_test.h" +#include "gui/loot_settings_test.h" +#include "gui/loot_state_test.h" #include -TEST(ModuloOperator, Cpp11Conformance) { +TEST(ModuloOperator, shouldConformToTheCpp11Standard) { // C++11 defines the modulo operator more strongly // (only x % 0 is left undefined), whereas C++03 // only defined the operator for positive first operand. diff --git a/src/tests/printers.h b/src/tests/printers.h index e521eddd..a5f105a2 100644 --- a/src/tests/printers.h +++ b/src/tests/printers.h @@ -39,65 +39,67 @@ along with LOOT. If not, see #include "backend/plugin/plugin.h" namespace loot { - void PrintTo(const File& value, ::std::ostream* os) { - *os << "loot::File(\"" << value.Name() << "\", " - << "\"" << value.DisplayName() << "\", " - << "\"" << value.Condition() << "\"" - << ")"; - } + namespace test { + void PrintTo(const File& value, ::std::ostream* os) { + *os << "File(\"" << value.Name() << "\", " + << "\"" << value.DisplayName() << "\", " + << "\"" << value.Condition() << "\"" + << ")"; + } - void PrintTo(const Location& value, ::std::ostream* os) { - *os << "loot::Location(\"" << value.URL() << "\", " - << "\"" << value.Name() << "\", " - << ")"; - } + void PrintTo(const Location& value, ::std::ostream* os) { + *os << "Location(\"" << value.URL() << "\", " + << "\"" << value.Name() << "\", " + << ")"; + } - void PrintTo(const Message& value, ::std::ostream* os) { - std::string type; - if (value.Type() == Message::warn) - type = "warn"; - else if (value.Type() == Message::error) - type = "error"; - else - type = "say"; + void PrintTo(const Message& value, ::std::ostream* os) { + std::string type; + if (value.Type() == Message::warn) + type = "warn"; + else if (value.Type() == Message::error) + type = "error"; + else + type = "say"; - *os << "loot::Message(\"" << type << "\", " - << ::testing::PrintToString(value.Content()) << ", " - << "\"" << value.Condition() << "\"" - << ")"; - } + *os << "Message(\"" << type << "\", " + << ::testing::PrintToString(value.Content()) << ", " + << "\"" << value.Condition() << "\"" + << ")"; + } - void PrintTo(const MessageContent& value, ::std::ostream* os) { - *os << "loot::MessageContent(\"" << value.Str() << "\", " - << "\"" << Language(value.Language()).Name() << "\"" - << ")"; - } + void PrintTo(const MessageContent& value, ::std::ostream* os) { + *os << "MessageContent(\"" << value.Str() << "\", " + << "\"" << Language(value.Language()).Name() << "\"" + << ")"; + } - void PrintTo(const PluginDirtyInfo& value, ::std::ostream* os) { - *os << "loot::PluginDirtyInfo(0x" - << std::hex << std::uppercase - << value.CRC() - << std::nouppercase << std::dec << ", " - << value.ITMs() << ", " - << value.DeletedRefs() << ", " - << value.DeletedNavmeshes() << ", " - << "\"" << value.CleaningUtility() << "\"" - << ")"; - } + void PrintTo(const PluginDirtyInfo& value, ::std::ostream* os) { + *os << "PluginDirtyInfo(0x" + << std::hex << std::uppercase + << value.CRC() + << std::nouppercase << std::dec << ", " + << value.ITMs() << ", " + << value.DeletedRefs() << ", " + << value.DeletedNavmeshes() << ", " + << "\"" << value.CleaningUtility() << "\"" + << ")"; + } - void PrintTo(const PluginMetadata& value, ::std::ostream* os) { - *os << "loot::PluginMetadata(\"" << value.Name() << "\")"; - } + void PrintTo(const PluginMetadata& value, ::std::ostream* os) { + *os << "PluginMetadata(\"" << value.Name() << "\")"; + } - void PrintTo(const Tag& value, ::std::ostream* os) { - *os << "loot::Tag(\"" << value.Name() << "\", " - << value.IsAddition() << ", " - << "\"" << value.Condition() << "\"" - << ")"; - } + void PrintTo(const Tag& value, ::std::ostream* os) { + *os << "Tag(\"" << value.Name() << "\", " + << value.IsAddition() << ", " + << "\"" << value.Condition() << "\"" + << ")"; + } - void PrintTo(const Plugin& value, ::std::ostream* os) { - *os << "loot::Plugin(\"" << value.Name() << "\")"; + void PrintTo(const Plugin& value, ::std::ostream* os) { + *os << "Plugin(\"" << value.Name() << "\")"; + } } }