diff --git a/include/loot/database_interface.h b/include/loot/database_interface.h index 5c971323..f88190a0 100644 --- a/include/loot/database_interface.h +++ b/include/loot/database_interface.h @@ -148,6 +148,20 @@ public: virtual MasterlistInfo GetMasterlistRevision(const std::string& masterlist_path, const bool get_short_id) const = 0; + /** + * Check if the given masterlist is the latest available for a given branch. + * @param masterlist_path + * A string containing the relative or absolute path to the masterlist + * file for which the latest revision should be obtained. It needs to + * be in a local Git repository. + * @param branch + * The branch to check against. + * @return True if the masterlist revision matches the latest masterlist + * revision for the given branch, and false otherwise. + */ + virtual bool IsLatestMasterlist(const std::string& masterlist_path, + const std::string& branch) const = 0; + /** * @} * @name Non-plugin Data Access diff --git a/include/loot/metadata/plugin_cleaning_data.h b/include/loot/metadata/plugin_cleaning_data.h index 2aacd439..fb5262f4 100644 --- a/include/loot/metadata/plugin_cleaning_data.h +++ b/include/loot/metadata/plugin_cleaning_data.h @@ -143,13 +143,6 @@ public: * does not exist, the English-language MessageContent object. */ LOOT_API MessageContent ChooseInfo(const LanguageCode language) const; - - /** - * Get a warning message describing the cleaning data. - * @return A Message object detailing the number and types of dirty edits - * found, the cleaning utility used, plus any additional information. - */ - LOOT_API Message AsMessage() const; private: uint32_t crc_; unsigned int itm_; diff --git a/include/loot/plugin_interface.h b/include/loot/plugin_interface.h index 3f3bb6b4..43130496 100644 --- a/include/loot/plugin_interface.h +++ b/include/loot/plugin_interface.h @@ -65,14 +65,6 @@ public: */ virtual std::vector GetMasters() const = 0; - /** - * Get any status messages associated with the plugin. - * - * For example, if parsing failed, it could be recorded in a status message. - * @return A vector of status messages. - */ - virtual std::vector GetStatusMessages() const = 0; - /** * Get any Bash Tags found in the plugin's description field. * @return A set of Bash Tags. The order of elements in the set holds no diff --git a/src/api/api_database.cpp b/src/api/api_database.cpp index bf481738..a48948b9 100644 --- a/src/api/api_database.cpp +++ b/src/api/api_database.cpp @@ -116,6 +116,11 @@ MasterlistInfo ApiDatabase::GetMasterlistRevision(const std::string& masterlistP return Masterlist::GetInfo(masterlistPath, getShortID); } +bool ApiDatabase::IsLatestMasterlist(const std::string& masterlist_path, + const std::string& branch) const { + return Masterlist::IsLatest(masterlist_path, branch); +} + ////////////////////////// // DB Access Functions ////////////////////////// diff --git a/src/api/api_database.h b/src/api/api_database.h index a56514a5..0b75891f 100644 --- a/src/api/api_database.h +++ b/src/api/api_database.h @@ -54,6 +54,9 @@ struct ApiDatabase : public DatabaseInterface { MasterlistInfo GetMasterlistRevision(const std::string& masterlist_path, const bool get_short_id) const; + bool IsLatestMasterlist(const std::string& masterlist_path, + const std::string& branch) const; + std::set GetKnownBashTags() const; std::vector GetGeneralMessages(bool evaluateConditions = false) const; diff --git a/src/api/helpers/git_helper.cpp b/src/api/helpers/git_helper.cpp index c00dfb13..71c1d27a 100644 --- a/src/api/helpers/git_helper.cpp +++ b/src/api/helpers/git_helper.cpp @@ -25,13 +25,11 @@ #include "api/helpers/git_helper.h" #include -#include #include #include "loot/exception/error_categories.h" #include "loot/exception/git_state_error.h" -using boost::locale::translate; using std::string; namespace fs = boost::filesystem; @@ -101,16 +99,9 @@ void GitHelper::Call(int error_code) { gitError = std::to_string(error_code) + "; " + last_error->message; giterr_clear(); - if (errorMessage_.empty()) - errorMessage_ = "Git operation failed."; + auto message = (boost::format("Git operation failed. Details: %1%") % gitError).str(); - errorMessage_ = (boost::format("%1% Details: %2%") % errorMessage_ % gitError).str(); - - throw std::system_error(error_code, libgit2_category(), errorMessage_); -} - -void GitHelper::SetErrorMessage(const std::string& message) { - errorMessage_ = message; + throw std::system_error(error_code, libgit2_category(), message); } bool GitHelper::IsRepository(const boost::filesystem::path& path) { @@ -144,7 +135,6 @@ void GitHelper::Clone(const boost::filesystem::path& path, const std::string& ur if (data_.repo != nullptr) throw GitStateError("Cannot clone repository that has already been opened."); - SetErrorMessage(translate("An error occurred while trying to clone the remote masterlist repository.")); // Clone the remote repository. BOOST_LOG_TRIVIAL(info) << "Repository doesn't exist, cloning the remote repository."; @@ -193,7 +183,6 @@ void GitHelper::Fetch(const std::string& remote) { throw GitStateError("Cannot fetch updates for repository that has not been opened."); BOOST_LOG_TRIVIAL(trace) << "Fetching updates from remote."; - SetErrorMessage(translate("An error occurred while trying to update the masterlist. This could be due to a server-side error. Try again in a few minutes.")); // Get the origin remote. Call(git_remote_lookup(&data_.remote, data_.repo, remote.c_str())); diff --git a/src/api/helpers/git_helper.h b/src/api/helpers/git_helper.h index 6dc709d3..0361412c 100644 --- a/src/api/helpers/git_helper.h +++ b/src/api/helpers/git_helper.h @@ -60,7 +60,6 @@ public: }; void Call(int error_code); - void SetErrorMessage(const std::string& message); static bool IsRepository(const boost::filesystem::path& path); static bool IsFileDifferent(const boost::filesystem::path& repoRoot, const std::string& filename); @@ -81,7 +80,6 @@ private: static void FixRepoPermissions(const boost::filesystem::path& path); GitData data_; - std::string errorMessage_; }; } #endif diff --git a/src/api/masterlist.cpp b/src/api/masterlist.cpp index 04b512fe..a9655264 100644 --- a/src/api/masterlist.cpp +++ b/src/api/masterlist.cpp @@ -33,17 +33,15 @@ #include "api/helpers/git_helper.h" using boost::format; -using boost::locale::translate; using std::string; namespace fs = boost::filesystem; namespace loot { MasterlistInfo Masterlist::GetInfo(const boost::filesystem::path& path, bool shortID) { - // Compare HEAD and working copy, and get revision info. + // Compare HEAD and working copy, and get revision info. GitHelper git; MasterlistInfo info; - git.SetErrorMessage((format(translate("An error occurred while trying to read the local masterlist's version. If this error happens again, try deleting the \".git\" folder in %1%.")) % path.parent_path().string()).str()); if (!fs::exists(path)) { BOOST_LOG_TRIVIAL(info) << "Unknown masterlist revision: No masterlist present."; @@ -84,6 +82,34 @@ MasterlistInfo Masterlist::GetInfo(const boost::filesystem::path& path, bool sho return info; } +bool Masterlist::IsLatest(const boost::filesystem::path& path, + const std::string& repoBranch) { + if (repoBranch.empty()) + throw std::invalid_argument("Repository branch must not be empty."); + + GitHelper git; + + if (!git.IsRepository(path.parent_path())) { + BOOST_LOG_TRIVIAL(info) << "Cannot get latest masterlist revision: Git repository missing."; + throw GitStateError(string("Unknown: \"") + path.parent_path().string() + "\" is not a Git repository."); + } + + BOOST_LOG_TRIVIAL(info) << "Attempting to open repository."; + git.Call(git_repository_open(&git.GetData().repo, path.parent_path().string().c_str())); + + git.Fetch("origin"); + + // Get the remote branch's commit ID. + git_oid branchOid; + git.Call(git_reference_name_to_id(&branchOid, git.GetData().repo, (string("refs/remotes/origin/") + repoBranch).c_str())); + + // Get HEAD's commit ID. + git_oid headOid; + git.Call(git_reference_name_to_id(&headOid, git.GetData().repo, "HEAD")); + + return boost::equal(branchOid.id, headOid.id); +} + bool Masterlist::Update(const boost::filesystem::path& path, const std::string& repoUrl, const std::string& repoBranch) { GitHelper git; fs::path repoPath = path.parent_path(); @@ -92,7 +118,7 @@ bool Masterlist::Update(const boost::filesystem::path& path, const std::string& if (repoUrl.empty() || repoBranch.empty()) throw std::invalid_argument("Repository URL and branch must not be empty."); -// Initialise checkout options. + // Initialise checkout options. BOOST_LOG_TRIVIAL(debug) << "Setting up checkout options."; char * paths = new char[filename.length() + 1]; strcpy(paths, filename.c_str()); @@ -110,8 +136,7 @@ bool Masterlist::Update(const boost::filesystem::path& path, const std::string& if (!git.IsRepository(repoPath)) git.Clone(repoPath, repoUrl); else { - // Repository exists: check settings are correct, then pull updates. - git.SetErrorMessage((format(translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); + // Repository exists: check settings are correct, then pull updates. // Open the repository. BOOST_LOG_TRIVIAL(info) << "Existing repository found, attempting to open it."; @@ -125,7 +150,6 @@ bool Masterlist::Update(const boost::filesystem::path& path, const std::string& git.Fetch("origin"); // Check that a local branch with the correct name exists. - git.SetErrorMessage((format(translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); int ret = git_branch_lookup(&git.GetData().reference, git.GetData().repo, repoBranch.c_str(), GIT_BRANCH_LOCAL); if (ret == GIT_ENOTFOUND) // Branch doesn't exist. Create a new branch using the remote branch's latest commit. @@ -231,10 +255,8 @@ bool Masterlist::Update(const boost::filesystem::path& path, const std::string& // and try again. bool parsingFailed = false; - std::string parsingError; - git.SetErrorMessage((format(translate("An error occurred while trying to read information on the updated masterlist. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); do { - // Get the HEAD revision's short ID. + // Get the HEAD revision's short ID. string revision = git.GetHeadShortId(); //Now try parsing the masterlist. @@ -245,18 +267,13 @@ bool Masterlist::Update(const boost::filesystem::path& path, const std::string& parsingFailed = false; } catch (std::exception& e) { parsingFailed = true; - if (parsingError.empty()) - parsingError = (format(translate("Masterlist revision %1%: %2%. The latest masterlist revision contains a syntax error, LOOT is using the most recent valid revision instead. Syntax errors are usually minor and fixed within hours.")) % revision % e.what()).str(); - //There was an error, roll back one revision. + //There was an error, roll back one revision. BOOST_LOG_TRIVIAL(error) << "Masterlist parsing failed. Masterlist revision " + string(revision) + ": " + e.what(); git.CheckoutRevision("HEAD^"); } } while (parsingFailed); - if (!parsingError.empty()) - AppendMessage(Message(MessageType::error, parsingError)); - return true; } } diff --git a/src/api/masterlist.h b/src/api/masterlist.h index 96d68afc..4cf44128 100644 --- a/src/api/masterlist.h +++ b/src/api/masterlist.h @@ -42,6 +42,9 @@ public: const std::string& repoBranch); static MasterlistInfo GetInfo(const boost::filesystem::path& path, bool shortID); + + static bool IsLatest(const boost::filesystem::path& path, + const std::string& repoBranch); }; } diff --git a/src/api/metadata/plugin_cleaning_data.cpp b/src/api/metadata/plugin_cleaning_data.cpp index 2288ae62..98c8629e 100644 --- a/src/api/metadata/plugin_cleaning_data.cpp +++ b/src/api/metadata/plugin_cleaning_data.cpp @@ -81,45 +81,4 @@ MessageContent PluginCleaningData::ChooseInfo(const LanguageCode language) const BOOST_LOG_TRIVIAL(trace) << "Choosing dirty info content."; return MessageContent::Choose(info_, language); } - -Message PluginCleaningData::AsMessage() const { - using boost::format; - using boost::locale::translate; - - const std::string itmRecords = (format(translate("%1% ITM record", "%1% ITM records", itm_)) % itm_).str(); - const std::string deletedReferences = (format(translate("%1% deleted reference", "%1% deleted references", ref_)) % ref_).str(); - const std::string deletedNavmeshes = (format(translate("%1% deleted navmesh", "%1% deleted navmeshes", nav_)) % nav_).str(); - - format f; - if (itm_ > 0 && ref_ > 0 && nav_ > 0) - f = format(translate("%1% found %2%, %3% and %4%.")) % utility_ % itmRecords % deletedReferences % deletedNavmeshes; - else if (itm_ == 0 && ref_ == 0 && nav_ == 0) - f = format(translate("%1% found dirty edits.")) % utility_; - - else if (itm_ == 0 && ref_ > 0 && nav_ > 0) - f = format(translate("%1% found %2% and %3%.")) % utility_ % deletedReferences % deletedNavmeshes; - else if (itm_ > 0 && ref_ == 0 && nav_ > 0) - f = format(translate("%1% found %2% and %3%.")) % utility_ % itmRecords % deletedNavmeshes; - else if (itm_ > 0 && ref_ > 0 && nav_ == 0) - f = format(translate("%1% found %2% and %3%.")) % utility_ % itmRecords % deletedReferences; - - else if (itm_ > 0) - f = format(translate("%1% found %2%.")) % utility_ % itmRecords; - else if (ref_ > 0) - f = format(translate("%1% found %2%.")) % utility_ % deletedReferences; - else if (nav_ > 0) - f = format(translate("%1% found %2%.")) % utility_ % deletedNavmeshes; - - std::string message = f.str(); - if (info_.empty()) { - return Message(MessageType::warn, message); - } - - auto info = info_; - for (auto& content : info) { - content = MessageContent(message + " " + content.GetText(), content.GetLanguage()); - } - - return Message(MessageType::warn, info); -} } diff --git a/src/api/plugin/plugin.cpp b/src/api/plugin/plugin.cpp index 379da9eb..03fab59a 100644 --- a/src/api/plugin/plugin.cpp +++ b/src/api/plugin/plugin.cpp @@ -35,6 +35,7 @@ #include "api/game/game.h" #include "api/helpers/crc.h" #include "api/helpers/version.h" +#include "loot/exception/file_access_error.h" using libespm::FormId; using std::set; @@ -113,7 +114,7 @@ Plugin::Plugin(const Game& game, const std::string& name, const bool headerOnly) } } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Cannot read plugin file \"" << name << "\". Details: " << e.what(); - messages_.push_back(Message(MessageType::error, (boost::format(boost::locale::translate("Cannot read \"%1%\". Details: %2%")) % name % e.what()).str())); + throw FileAccessError((boost::format("Cannot read \"%1%\". Details: %2%") % name % e.what()).str()); } BOOST_LOG_TRIVIAL(trace) << name_ << ": " << "Plugin loading complete."; @@ -135,10 +136,6 @@ std::vector Plugin::GetMasters() const { return getMasters(); } -std::vector Plugin::GetStatusMessages() const { - return messages_; -} - std::set Plugin::GetBashTags() const { return tags_; } diff --git a/src/api/plugin/plugin.h b/src/api/plugin/plugin.h index e230ad81..0aeb7024 100644 --- a/src/api/plugin/plugin.h +++ b/src/api/plugin/plugin.h @@ -48,7 +48,6 @@ public: std::string GetLowercasedName() const; std::string GetVersion() const; std::vector GetMasters() const; - std::vector GetStatusMessages() const; std::set GetBashTags() const; uint32_t GetCRC() const; diff --git a/src/api/plugin/plugin_sorter.cpp b/src/api/plugin/plugin_sorter.cpp index 7dd5754a..1d9b01d1 100644 --- a/src/api/plugin/plugin_sorter.cpp +++ b/src/api/plugin/plugin_sorter.cpp @@ -215,15 +215,7 @@ void PluginSorter::AddPluginVertices(Game& game) { for (const auto &plugin : game.GetPlugins()) { BOOST_LOG_TRIVIAL(trace) << "Getting and evaluating metadata for plugin " << plugin->GetName(); - PluginMetadata metadata(plugin->GetName()); - try { - metadata = game.GetDatabase()->GetPluginMetadata(plugin->GetName(), true, true); - } catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "\"" << plugin->GetName() << "\" contains a condition that could not be evaluated. Details: " << e.what(); - metadata.SetMessages({ - Message(MessageType::error, (boost::format(boost::locale::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % plugin->GetName() % e.what()).str()), - }); - } + auto metadata = game.GetDatabase()->GetPluginMetadata(plugin->GetName(), true, true); BOOST_LOG_TRIVIAL(trace) << "Adding vertex for plugin \"" << plugin->GetName() << "\""; diff --git a/src/tests/api/interface/database_interface_test.h b/src/tests/api/interface/database_interface_test.h index a06ca3e7..accb1615 100644 --- a/src/tests/api/interface/database_interface_test.h +++ b/src/tests/api/interface/database_interface_test.h @@ -38,6 +38,7 @@ protected: userlistPath_(localPath / "userlist.yaml"), url_("https://github.com/loot/testing-metadata.git"), branch_("master"), + oldBranch_("old-branch"), minimalOutputPath_(localPath / "minimal.yml"), generalUserlistMessage("A general userlist message.") {} @@ -124,6 +125,7 @@ protected: const boost::filesystem::path minimalOutputPath_; const std::string url_; const std::string branch_; + const std::string oldBranch_; const std::string generalUserlistMessage; std::shared_ptr db_; @@ -321,6 +323,18 @@ TEST_P(DatabaseInterfaceTest, getMasterlistRevisionShouldSucceedIfAnEditedVersio EXPECT_TRUE(info.is_modified); } +TEST_P(DatabaseInterfaceTest, isLatestMasterlistShouldReturnFalseIfTheCurrentRevisionIsNotTheLatestRevisionInTheGivenBranch) { + ASSERT_NO_THROW(db_->UpdateMasterlist(masterlistPath.string(), url_, oldBranch_)); + + EXPECT_FALSE(db_->IsLatestMasterlist(masterlistPath.string(), branch_)); +} + +TEST_P(DatabaseInterfaceTest, isLatestMasterlistShouldReturnTrueIfTheCurrentRevisionIsTheLatestRevisioninTheGivenBranch) { + ASSERT_NO_THROW(db_->UpdateMasterlist(masterlistPath.string(), url_, branch_)); + + EXPECT_TRUE(db_->IsLatestMasterlist(masterlistPath.string(), branch_)); +} + TEST_P(DatabaseInterfaceTest, getKnownBashTagsShouldReturnAllBashTagsListedInLoadedMetadata) { ASSERT_NO_THROW(GenerateMasterlist()); ASSERT_NO_THROW(GenerateUserlist()); diff --git a/src/tests/api/internals/helpers/git_helper_test.h b/src/tests/api/internals/helpers/git_helper_test.h index d953b719..129ceb8a 100644 --- a/src/tests/api/internals/helpers/git_helper_test.h +++ b/src/tests/api/internals/helpers/git_helper_test.h @@ -98,18 +98,6 @@ TEST_F(GitHelperTest, callShouldThrowIfPassedANonZeroValue) { EXPECT_THROW(git_.Call(-1), std::system_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 (std::system_error& e) { - EXPECT_NE(nullptr, strstr(e.what(), errorMessage)); - } -} - TEST_F(GitHelperTest, isRepositoryShouldReturnTrueForARepositoryRoot) { EXPECT_TRUE(GitHelper::IsRepository(parentRepoRoot)); } diff --git a/src/tests/api/internals/masterlist_test.h b/src/tests/api/internals/masterlist_test.h index 6b3ebef7..373489f0 100644 --- a/src/tests/api/internals/masterlist_test.h +++ b/src/tests/api/internals/masterlist_test.h @@ -35,6 +35,7 @@ class MasterlistTest : public CommonGameTestFixture { protected: MasterlistTest() : repoBranch("master"), + oldBranch("old-branch"), repoUrl("https://github.com/loot/testing-metadata.git"), masterlistPath(localPath / "masterlist.yaml") {} @@ -53,6 +54,7 @@ protected: const std::string repoUrl; const std::string repoBranch; + const std::string oldBranch; const boost::filesystem::path masterlistPath; }; @@ -177,6 +179,39 @@ TEST_P(MasterlistTest, getInfoShouldAppendSuffixesToReturnedStringsIfTheMasterli EXPECT_EQ(10, info.revision_date.length()); EXPECT_TRUE(info.is_modified); } + +TEST_P(MasterlistTest, isLatestShouldThrowIfTheGivenPathDoesNotBelongToAGitRepository) { + ASSERT_NO_THROW(boost::filesystem::copy("./testing-metadata/masterlist.yaml", masterlistPath)); + + EXPECT_THROW(Masterlist::IsLatest(masterlistPath, repoBranch), GitStateError); +} + +TEST_P(MasterlistTest, isLatestShouldThrowIfTheGivenBranchIsAnEmptyString) { + Masterlist masterlist; + ASSERT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + + EXPECT_THROW(Masterlist::IsLatest(masterlistPath, ""), std::invalid_argument); +} + +TEST_P(MasterlistTest, isLatestShouldReturnFalseIfTheCurrentRevisionIsNotTheLatestRevisionInTheGivenBranch) { + Masterlist masterlist; + ASSERT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + oldBranch)); + + EXPECT_FALSE(Masterlist::IsLatest(masterlistPath, repoBranch)); +} + +TEST_P(MasterlistTest, isLatestShouldReturnTrueIfTheCurrentRevisionIsTheLatestRevisioninTheGivenBranch) { + Masterlist masterlist; + ASSERT_TRUE(masterlist.Update(masterlistPath, + repoUrl, + repoBranch)); + + EXPECT_TRUE(Masterlist::IsLatest(masterlistPath, repoBranch)); +} } } diff --git a/src/tests/api/internals/metadata/plugin_cleaning_data_test.h b/src/tests/api/internals/metadata/plugin_cleaning_data_test.h index 3f21cadb..2b7a7260 100644 --- a/src/tests/api/internals/metadata/plugin_cleaning_data_test.h +++ b/src/tests/api/internals/metadata/plugin_cleaning_data_test.h @@ -69,60 +69,6 @@ TEST_P(PluginCleaningDataTest, contentConstructorShouldStoreAllGivenData) { EXPECT_EQ(info_, info.GetInfo()); } -TEST_P(PluginCleaningDataTest, asMessageShouldOutputAllNonZeroCounts) { - Message message = PluginCleaningData(0x12345678, "cleaner", info_, 2, 10, 30).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 2 ITM records, 10 deleted references and 30 deleted navmeshes. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 0, 0, 0).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found dirty edits. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 0, 10, 30).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 10 deleted references and 30 deleted navmeshes. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 0, 0, 30).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 30 deleted navmeshes. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 0, 10, 0).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 10 deleted references. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 2, 0, 30).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 2 ITM records and 30 deleted navmeshes. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 2, 0, 0).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 2 ITM records. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 2, 10, 0).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 2 ITM records and 10 deleted references. info", message.GetContent(LanguageCode::english).GetText()); -} - -TEST_P(PluginCleaningDataTest, asMessageShouldDistinguishBetweenSingularAndPluralCounts) { - Message message = PluginCleaningData(0x12345678, "cleaner", info_, 1, 2, 3).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 1 ITM record, 2 deleted references and 3 deleted navmeshes. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 2, 1, 3).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 2 ITM records, 1 deleted reference and 3 deleted navmeshes. info", message.GetContent(LanguageCode::english).GetText()); - - message = PluginCleaningData(0x12345678, "cleaner", info_, 3, 2, 1).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 3 ITM records, 2 deleted references and 1 deleted navmesh. info", message.GetContent(LanguageCode::english).GetText()); -} - -TEST_P(PluginCleaningDataTest, asMessageShouldReturnAMessageWithCountsButNoInfoStringIfInfoIsAnEmptyString) { - Message message = PluginCleaningData(0x12345678, "cleaner", std::vector(), 1, 2, 3).AsMessage(); - EXPECT_EQ(MessageType::warn, message.GetType()); - EXPECT_EQ("cleaner found 1 ITM record, 2 deleted references and 3 deleted navmeshes.", message.GetContent(LanguageCode::english).GetText()); -} - TEST_P(PluginCleaningDataTest, dirtyInfoShouldBeEqualIfCrcValuesAreEqual) { PluginCleaningData info1(0x12345678, "cleaner1", info_, 2, 10, 30); PluginCleaningData info2(0x12345678, "cleaner2", info_, 4, 20, 60); diff --git a/src/tests/api/internals/plugin/plugin_test.h b/src/tests/api/internals/plugin/plugin_test.h index 07016af7..cc0c4349 100644 --- a/src/tests/api/internals/plugin/plugin_test.h +++ b/src/tests/api/internals/plugin/plugin_test.h @@ -37,6 +37,7 @@ protected: PluginTest() : emptyFile("EmptyFile.esm"), nonPluginFile("NotAPlugin.esm"), + lowercaseBlankEsp("blank.esp"), game_(GetParam(), dataPath.parent_path(), localPath), blankArchive("Blank" + game_.GetArchiveFileExtension()), blankSuffixArchive("Blank - Different - suffix" + game_.GetArchiveFileExtension()) {} @@ -55,6 +56,10 @@ protected: out.close(); ASSERT_TRUE(boost::filesystem::exists(dataPath / nonPluginFile)); +#ifndef _WIN32 + ASSERT_NO_THROW(boost::filesystem::copy(dataPath / blankEsp, dataPath / lowercaseBlankEsp)); +#endif + // Create dummy archive files. out.open(dataPath / blankArchive); out.close(); @@ -67,6 +72,9 @@ protected: boost::filesystem::remove(dataPath / emptyFile); boost::filesystem::remove(dataPath / nonPluginFile); +#ifndef _WIN32 + boost::filesystem::remove(dataPath / lowercaseBlankEsp); +#endif boost::filesystem::remove(dataPath / blankArchive); boost::filesystem::remove(dataPath / blankSuffixArchive); } @@ -75,6 +83,7 @@ protected: const std::string emptyFile; const std::string nonPluginFile; + const std::string lowercaseBlankEsp; const std::string blankArchive; const std::string blankSuffixArchive; }; @@ -85,7 +94,6 @@ public: std::string GetLowercasedName() const { return ""; } std::string GetVersion() const { return ""; } std::vector GetMasters() const { return std::vector(); } - std::vector GetStatusMessages() const { return std::vector(); } std::set GetBashTags() const { return std::set(); } uint32_t GetCRC() const { return 0; } @@ -159,6 +167,10 @@ TEST_P(PluginTest, loadingAPluginWithMastersShouldReadThemCorrectly) { }), plugin.GetMasters()); } +TEST_P(PluginTest, loadingAPluginThatDoesNotExistShouldThrow) { + EXPECT_THROW(Plugin(game_, "Blank\\.esp", true), FileAccessError); +} + TEST_P(PluginTest, loadsArchiveForAnArchiveThatExactlyMatchesAnEsmFileBasenameShouldReturnTrueForAllGamesExceptOblivion) { bool loadsArchive = Plugin(game_, blankEsm, true).LoadsArchive(); @@ -194,10 +206,6 @@ TEST_P(PluginTest, loadsArchiveShouldReturnFalseForAPluginThatDoesNotLoadAnArchi EXPECT_FALSE(Plugin(game_, blankMasterDependentEsp, true).LoadsArchive()); } -TEST_P(PluginTest, loadsArchiveShouldReturnFalseForAPluginWithARegexFilename) { - EXPECT_FALSE(Plugin(game_, "Blank\\.esp", true).LoadsArchive()); -} - TEST_P(PluginTest, isValidShouldReturnTrueForAValidPlugin) { EXPECT_TRUE(Plugin::IsValid(blankEsm, game_)); } @@ -219,14 +227,14 @@ TEST_P(PluginTest, isActiveShouldReturnFalseForAPluginThatIsNotActive) { } TEST_P(PluginTest, lessThanOperatorShouldUseCaseInsensitiveLexicographicalNameComparison) { - Plugin plugin1(game_, "Blank.esp", true); - Plugin plugin2(game_, "blank.esp", true); + Plugin plugin1(game_, blankEsp, true); + Plugin plugin2(game_, lowercaseBlankEsp, true); EXPECT_FALSE(plugin1 < plugin2); EXPECT_FALSE(plugin2 < plugin1); - Plugin plugin3 = Plugin(game_, "blank.esm", true); - Plugin plugin4 = Plugin(game_, "blank.esp", true); + Plugin plugin3 = Plugin(game_, blankEsm, true); + Plugin plugin4 = Plugin(game_, blankEsp, true); EXPECT_TRUE(plugin3 < plugin4); EXPECT_FALSE(plugin4 < plugin3);