From e06ce7efee8c7fb63aa5c781d1fe45de3534b620 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Wed, 19 Sep 2018 19:37:00 +0100 Subject: [PATCH] Differentiate between load after and requirement metadata sources When reporting a cyclic interaction error. --- .../loot/exception/cyclic_interaction_error.h | 11 +- src/api/sorting/cyclic_interaction_error.cpp | 56 ++++---- src/api/sorting/group_sort.cpp | 123 ++++++++++++++---- src/api/sorting/group_sort.h | 4 +- src/api/sorting/plugin_sorter.cpp | 44 ++++--- src/api/sorting/plugin_sorting_data.cpp | 44 ++++++- src/api/sorting/plugin_sorting_data.h | 21 ++- .../api/internals/sorting/group_sort_test.h | 64 +++++---- .../internals/sorting/plugin_sorter_test.h | 18 ++- 9 files changed, 271 insertions(+), 114 deletions(-) diff --git a/include/loot/exception/cyclic_interaction_error.h b/include/loot/exception/cyclic_interaction_error.h index f0670b40..67519881 100644 --- a/include/loot/exception/cyclic_interaction_error.h +++ b/include/loot/exception/cyclic_interaction_error.h @@ -38,8 +38,10 @@ enum struct EdgeType : unsigned int { Hardcoded, MasterFlag, Master, - Requirement, - LoadAfter, + MasterlistRequirement, + UserRequirement, + MasterlistLoadAfter, + UserLoadAfter, Group, Overlap, TieBreak, @@ -62,7 +64,7 @@ public: /** * @brief Get the name of the plugin or group. * @return The name of the plugin or group. - */ + */ std::string GetName() const; /** @@ -70,8 +72,9 @@ public: * @details Each edge goes from the vertex that loads earlier to the vertex * that loads later. * @return The edge type. - */ + */ EdgeType GetTypeOfEdgeToNextVertex() const; + private: std::string name_; EdgeType outEdgeType_; diff --git a/src/api/sorting/cyclic_interaction_error.cpp b/src/api/sorting/cyclic_interaction_error.cpp index a2baaea0..c01a0dd5 100644 --- a/src/api/sorting/cyclic_interaction_error.cpp +++ b/src/api/sorting/cyclic_interaction_error.cpp @@ -24,45 +24,47 @@ #include "loot/exception/cyclic_interaction_error.h" namespace loot { -Vertex::Vertex(std::string name, EdgeType outEdgeType) : name_(name), outEdgeType_(outEdgeType) {} +Vertex::Vertex(std::string name, EdgeType outEdgeType) : + name_(name), + outEdgeType_(outEdgeType) {} -std::string Vertex::GetName() const { - return name_; -} +std::string Vertex::GetName() const { return name_; } -EdgeType Vertex::GetTypeOfEdgeToNextVertex() const { - return outEdgeType_; -} +EdgeType Vertex::GetTypeOfEdgeToNextVertex() const { return outEdgeType_; } std::string describe(EdgeType edgeType) { switch (edgeType) { - case EdgeType::Hardcoded: - return "Hardcoded"; - case EdgeType::MasterFlag: - return "Master Flag"; - case EdgeType::Master: - return "Master"; - case EdgeType::Requirement: - return "Requirement"; - case EdgeType::LoadAfter: - return "Load After"; - case EdgeType::Group: - return "Group"; - case EdgeType::Overlap: - return "Overlap"; - case EdgeType::TieBreak: - return "Tie Break"; - default: - return "Unknown"; + case EdgeType::Hardcoded: + return "Hardcoded"; + case EdgeType::MasterFlag: + return "Master Flag"; + case EdgeType::Master: + return "Master"; + case EdgeType::MasterlistRequirement: + return "Masterlist Requirement"; + case EdgeType::UserRequirement: + return "User Requirement"; + case EdgeType::MasterlistLoadAfter: + return "Masterlist Load After"; + case EdgeType::UserLoadAfter: + return "User Load After"; + case EdgeType::Group: + return "Group"; + case EdgeType::Overlap: + return "Overlap"; + case EdgeType::TieBreak: + return "Tie Break"; + default: + return "Unknown"; } } - // A.esp --[Master Flag]-> B.esp --Group-> std::string describeCycle(const std::vector& cycle) { std::string text; for (const auto& vertex : cycle) { - text += vertex.GetName() + " --[" + describe(vertex.GetTypeOfEdgeToNextVertex()) + "]-> "; + text += vertex.GetName() + " --[" + + describe(vertex.GetTypeOfEdgeToNextVertex()) + "]-> "; } if (!cycle.empty()) { text += cycle[0].GetName(); diff --git a/src/api/sorting/group_sort.cpp b/src/api/sorting/group_sort.cpp index ff9af471..a9c2db7f 100644 --- a/src/api/sorting/group_sort.cpp +++ b/src/api/sorting/group_sort.cpp @@ -25,19 +25,49 @@ #include "group_sort.h" #include -#include #include +#include +#include "api/helpers/logging.h" #include "loot/exception/cyclic_interaction_error.h" #include "loot/exception/undefined_group_error.h" -#include "api/helpers/logging.h" namespace loot { +class GroupSortingData { +public: + GroupSortingData() {} + GroupSortingData(std::string name) : name_(name) {} + + std::string GetName() const { return name_; } + + std::unordered_set GetMasterlistAfterGroups() const { + return masterlistAfterGroups_; + } + + std::unordered_set GetUserAfterGroups() const { + return userAfterGroups_; + } + + void SetMasterlistAfterGroups(std::unordered_set groups) { + masterlistAfterGroups_ = groups; + } + + void SetUserAfterGroups(std::unordered_set groups) { + userAfterGroups_ = groups; + } + +private: + std::string name_; + std::unordered_set masterlistAfterGroups_; + std::unordered_set userAfterGroups_; +}; + typedef boost::adjacency_list GroupGraph; + GroupSortingData, + EdgeType> + GroupGraph; typedef boost::graph_traits::vertex_descriptor vertex_t; typedef boost::graph_traits::edge_descriptor edge_t; @@ -46,11 +76,11 @@ public: void tree_edge(edge_t edge, const GroupGraph& graph) { auto source = boost::source(edge, graph); - auto vertex = Vertex(graph[source], graph[edge]); + auto vertex = Vertex(graph[source].GetName(), graph[edge]); // Check if the plugin already exists in the recorded trail. auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { - return v.GetName() == graph[source]; + return v.GetName() == graph[source].GetName(); }); if (it != end(trail)) { @@ -66,11 +96,11 @@ public: auto source = boost::source(edge, graph); auto target = boost::target(edge, graph); - auto vertex = Vertex(graph[source], graph[edge]); + auto vertex = Vertex(graph[source].GetName(), graph[edge]); trail.push_back(vertex); auto it = find_if(begin(trail), end(trail), [&](const Vertex& v) { - return v.GetName() == graph[target]; + return v.GetName() == graph[target].GetName(); }); if (it != trail.end()) { @@ -84,20 +114,22 @@ private: class AfterGroupsVisitor : public boost::dfs_visitor<> { public: - AfterGroupsVisitor(std::unordered_set& visitedGroups) : visitedGroups_(visitedGroups) {} + AfterGroupsVisitor(std::unordered_set& visitedGroups) : + visitedGroups_(visitedGroups) {} void tree_edge(edge_t edge, const GroupGraph& graph) { auto target = boost::target(edge, graph); - visitedGroups_.insert(graph[target]); + visitedGroups_.insert(graph[target].GetName()); } std::unordered_set get_visited_groups() const { return visitedGroups_; } + private: std::unordered_set& visitedGroups_; }; -std::string join(const std::unordered_set set) { +std::string join(const std::unordered_set& set) { std::string output; for (const auto& element : set) { output += element + ", "; @@ -106,7 +138,9 @@ std::string join(const std::unordered_set set) { return output.substr(0, output.length() - 2); } -std::unordered_map> GetTransitiveAfterGroups(const std::unordered_set groups) { +std::unordered_map> +GetTransitiveAfterGroups(const std::unordered_set& masterlistGroups, + const std::unordered_set& userGroups) { GroupGraph graph; auto logger = getLogger(); @@ -115,24 +149,59 @@ std::unordered_map> GetTransitiveAf } std::unordered_map groupVertices; - for (const auto& group : groups) { - auto vertex = boost::add_vertex(group.GetName(), graph); + for (const auto& group : masterlistGroups) { + auto groupSortingData = GroupSortingData(group.GetName()); + groupSortingData.SetMasterlistAfterGroups(group.GetAfterGroups()); + + auto vertex = boost::add_vertex(groupSortingData, graph); + groupVertices.emplace(group.GetName(), vertex); + } + for (const auto& group : userGroups) { + auto it = groupVertices.find(group.GetName()); + if (it != groupVertices.end()) { + graph[it->second].SetUserAfterGroups(group.GetAfterGroups()); + } else { + auto groupSortingData = GroupSortingData(group.GetName()); + groupSortingData.SetUserAfterGroups(group.GetAfterGroups()); + + auto vertex = boost::add_vertex(groupSortingData, graph); groupVertices.emplace(group.GetName(), vertex); + } } - for (const auto& group : groups) { + for (const vertex_t& vertex : + boost::make_iterator_range(boost::vertices(graph))) { + auto group = graph[vertex]; + if (logger) { - logger->trace("Group \"{}\" directly loads after groups \"{}\"", - group.GetName(), join(group.GetAfterGroups())); + logger->trace( + "Group \"{}\" directly loads after masterlist groups \"{}\" and user " + "groups \"{}\"", + group.GetName(), + join(group.GetMasterlistAfterGroups()), + join(group.GetUserAfterGroups())); } - for (const auto& otherGroupName : group.GetAfterGroups()) { + + for (const auto& otherGroupName : group.GetMasterlistAfterGroups()) { auto otherVertex = groupVertices.find(otherGroupName); if (otherVertex == groupVertices.end()) { throw UndefinedGroupError(otherGroupName); } auto vertex = groupVertices[group.GetName()]; - boost::add_edge(vertex, otherVertex->second, EdgeType::LoadAfter, graph); + boost::add_edge( + vertex, otherVertex->second, EdgeType::MasterlistLoadAfter, graph); + } + + for (const auto& otherGroupName : group.GetUserAfterGroups()) { + auto otherVertex = groupVertices.find(otherGroupName); + if (otherVertex == groupVertices.end()) { + throw UndefinedGroupError(otherGroupName); + } + + auto vertex = groupVertices[group.GetName()]; + boost::add_edge( + vertex, otherVertex->second, EdgeType::UserLoadAfter, graph); } } @@ -142,23 +211,25 @@ std::unordered_map> GetTransitiveAf } boost::depth_first_search(graph, boost::visitor(CycleDetector())); - std::unordered_map> transitiveAfterGroups; - for (const vertex_t& vertex : boost::make_iterator_range(boost::vertices(graph))) { + std::unordered_map> + transitiveAfterGroups; + for (const vertex_t& vertex : + boost::make_iterator_range(boost::vertices(graph))) { std::unordered_set visitedGroups; AfterGroupsVisitor afterGroupsVisitor(visitedGroups); // Create a color map. std::vector colorVec(boost::num_vertices(graph)); - auto colorMap = boost::make_iterator_property_map(colorVec.begin(), - boost::get(boost::vertex_index, graph), - colorVec[0]); + auto colorMap = boost::make_iterator_property_map( + colorVec.begin(), boost::get(boost::vertex_index, graph), colorVec[0]); boost::depth_first_visit(graph, vertex, afterGroupsVisitor, colorMap); - transitiveAfterGroups[graph[vertex]] = visitedGroups; + transitiveAfterGroups[graph[vertex].GetName()] = visitedGroups; if (logger) { logger->trace("Group \"{}\" transitively loads after groups \"{}\"", - graph[vertex], join(visitedGroups)); + graph[vertex].GetName(), + join(visitedGroups)); } } diff --git a/src/api/sorting/group_sort.h b/src/api/sorting/group_sort.h index 6ba46bb2..32032f7c 100644 --- a/src/api/sorting/group_sort.h +++ b/src/api/sorting/group_sort.h @@ -33,6 +33,8 @@ namespace loot { // Map entries are a group name and names of transitive load after groups. -std::unordered_map> GetTransitiveAfterGroups(const std::unordered_set groups); +std::unordered_map> +GetTransitiveAfterGroups(const std::unordered_set& masterlistGroups, + const std::unordered_set& userGroups); } #endif diff --git a/src/api/sorting/plugin_sorter.cpp b/src/api/sorting/plugin_sorter.cpp index ddcb2f94..831c4fb2 100644 --- a/src/api/sorting/plugin_sorter.cpp +++ b/src/api/sorting/plugin_sorter.cpp @@ -208,15 +208,22 @@ void PluginSorter::AddPluginVertices(Game& game) { for (const auto& plugin : game.GetCache()->GetPlugins()) { if (logger_) { - logger_->trace("Getting and evaluating metadata for plugin {}", + logger_->trace("Getting and evaluating metadata for plugin \"{}\"", plugin->GetName()); } - auto metadata = game.GetDatabase() - ->GetPluginMetadata(plugin->GetName(), true, true) - .value_or(PluginMetadata(plugin->GetName())); + auto masterlistMetadata = + game.GetDatabase() + ->GetPluginMetadata(plugin->GetName(), false, true) + .value_or(PluginMetadata(plugin->GetName())); + auto userMetadata = game.GetDatabase() + ->GetPluginUserMetadata(plugin->GetName(), true) + .value_or(PluginMetadata(plugin->GetName())); - auto groupName = metadata.GetGroup().value_or(Group().GetName()); + auto pluginSortingData = + PluginSortingData(*plugin, masterlistMetadata, userMetadata); + + auto groupName = pluginSortingData.GetGroup(); auto groupIt = groupPlugins.find(groupName); if (groupIt == groupPlugins.end()) { groupPlugins.emplace(groupName, @@ -225,18 +232,15 @@ void PluginSorter::AddPluginVertices(Game& game) { groupIt->second.push_back(plugin->GetName()); } - if (logger_) { - logger_->trace("Getting and evaluating metadata for plugin \"{}\"", - plugin->GetName()); - } - - boost::add_vertex(PluginSortingData(*plugin, std::move(metadata)), graph_); + boost::add_vertex(pluginSortingData, graph_); } // Map sets of transitive group dependencies to sets of transitive plugin // dependencies. groups_ = game.GetDatabase()->GetGroups(); - auto groups = GetTransitiveAfterGroups(groups_); + + auto groups = GetTransitiveAfterGroups(game.GetDatabase()->GetGroups(false), + game.GetDatabase()->GetUserGroups()); for (auto& group : groups) { std::unordered_set transitivePlugins; for (const auto& afterGroup : group.second) { @@ -465,17 +469,25 @@ void PluginSorter::AddSpecificEdges() { if (logger_) { logger_->trace("Adding in-edges for requirements."); } - for (const auto& file : graph_[*vit].GetRequirements()) { + for (const auto& file : graph_[*vit].GetMasterlistRequirements()) { if (GetVertexByName(file.GetName(), parentVertex)) - AddEdge(parentVertex, *vit, EdgeType::Requirement); + AddEdge(parentVertex, *vit, EdgeType::MasterlistRequirement); + } + for (const auto& file : graph_[*vit].GetUserRequirements()) { + if (GetVertexByName(file.GetName(), parentVertex)) + AddEdge(parentVertex, *vit, EdgeType::UserRequirement); } if (logger_) { logger_->trace("Adding in-edges for 'load after's."); } - for (const auto& file : graph_[*vit].GetLoadAfterFiles()) { + for (const auto& file : graph_[*vit].GetMasterlistLoadAfterFiles()) { if (GetVertexByName(file.GetName(), parentVertex)) - AddEdge(parentVertex, *vit, EdgeType::LoadAfter); + AddEdge(parentVertex, *vit, EdgeType::MasterlistLoadAfter); + } + for (const auto& file : graph_[*vit].GetUserLoadAfterFiles()) { + if (GetVertexByName(file.GetName(), parentVertex)) + AddEdge(parentVertex, *vit, EdgeType::UserLoadAfter); } } } diff --git a/src/api/sorting/plugin_sorting_data.cpp b/src/api/sorting/plugin_sorting_data.cpp index a6bbf63e..a9b0ca03 100644 --- a/src/api/sorting/plugin_sorting_data.cpp +++ b/src/api/sorting/plugin_sorting_data.cpp @@ -25,18 +25,34 @@ #include "plugin_sorting_data.h" #include +#include #include namespace loot { PluginSortingData::PluginSortingData(const Plugin& plugin, - const PluginMetadata&& metadata) : + const PluginMetadata& masterlistMetadata, + const PluginMetadata& userMetadata) : plugin_(plugin), - PluginMetadata(metadata), - group_(metadata.GetGroup().value_or(Group().GetName())) {} + masterlistLoadAfter_(masterlistMetadata.GetLoadAfterFiles()), + userLoadAfter_(userMetadata.GetLoadAfterFiles()), + masterlistReq_(masterlistMetadata.GetRequirements()), + userReq_(userMetadata.GetRequirements()) { + if (userMetadata.GetGroup()) { + group_ = userMetadata.GetGroup().value(); + } else if (masterlistMetadata.GetGroup()) { + group_ = masterlistMetadata.GetGroup().value(); + } else { + group_ = Group().GetName(); + } +} std::string PluginSortingData::GetName() const { return plugin_.GetName(); } +std::string PluginSortingData::GetLowercasedName() const { + return boost::locale::to_lower(plugin_.GetName()); +} + bool PluginSortingData::IsMaster() const { return plugin_.IsMaster() || (plugin_.IsLightMaster() && !boost::iends_with(plugin_.GetName(), ".esp")); @@ -59,11 +75,29 @@ bool PluginSortingData::DoFormIDsOverlap( std::string PluginSortingData::GetGroup() const { return group_; } -std::unordered_set PluginSortingData::GetAfterGroupPlugins() const { +std::unordered_set PluginSortingData::GetAfterGroupPlugins() + const { return afterGroupPlugins_; } -void PluginSortingData::SetAfterGroupPlugins(std::unordered_set plugins) { +void PluginSortingData::SetAfterGroupPlugins( + std::unordered_set plugins) { afterGroupPlugins_ = plugins; } + +const std::set& PluginSortingData::GetMasterlistLoadAfterFiles() const { + return masterlistLoadAfter_; +} + +const std::set& PluginSortingData::GetUserLoadAfterFiles() const { + return userLoadAfter_; +} + +const std::set& PluginSortingData::GetMasterlistRequirements() const { + return masterlistReq_; +} + +const std::set& PluginSortingData::GetUserRequirements() const { + return userReq_; +} } diff --git a/src/api/sorting/plugin_sorting_data.h b/src/api/sorting/plugin_sorting_data.h index a634072d..ffd2fec2 100644 --- a/src/api/sorting/plugin_sorting_data.h +++ b/src/api/sorting/plugin_sorting_data.h @@ -29,11 +29,14 @@ #include "loot/metadata/plugin_metadata.h" namespace loot { -class PluginSortingData : private PluginMetadata { +class PluginSortingData { public: - PluginSortingData(const Plugin& plugin, const PluginMetadata&& metadata); + PluginSortingData(const Plugin& plugin, + const PluginMetadata& masterlistMetadata, + const PluginMetadata& userMetadata); std::string GetName() const; + std::string GetLowercasedName() const; bool IsMaster() const; bool LoadsArchive() const; std::vector GetMasters() const; @@ -44,15 +47,21 @@ public: std::unordered_set GetAfterGroupPlugins() const; void SetAfterGroupPlugins(std::unordered_set plugins); - - using PluginMetadata::GetLowercasedName; - using PluginMetadata::GetLoadAfterFiles; - using PluginMetadata::GetRequirements; + + const std::set& GetMasterlistLoadAfterFiles() const; + const std::set& GetUserLoadAfterFiles() const; + const std::set& GetMasterlistRequirements() const; + const std::set& GetUserRequirements() const; private: const Plugin& plugin_; std::string group_; std::unordered_set afterGroupPlugins_; + + std::set masterlistLoadAfter_; + std::set userLoadAfter_; + std::set masterlistReq_; + std::set userReq_; }; } diff --git a/src/tests/api/internals/sorting/group_sort_test.h b/src/tests/api/internals/sorting/group_sort_test.h index bae0f3e4..a8a0ba0a 100644 --- a/src/tests/api/internals/sorting/group_sort_test.h +++ b/src/tests/api/internals/sorting/group_sort_test.h @@ -35,55 +35,73 @@ along with LOOT. If not, see namespace loot { namespace test { TEST(GetTransitiveAfterGroups, shouldMapGroupsToTheirTransitiveAfterGroups) { - std::unordered_set groups({ - Group("a"), - Group("b", std::unordered_set({ "a" })), - Group("c", std::unordered_set({"b"})) - }); + std::unordered_set groups( + {Group("a"), + Group("b", std::unordered_set({"a"})), + Group("c", std::unordered_set({"b"}))}); - auto mapped = GetTransitiveAfterGroups(groups); + auto mapped = GetTransitiveAfterGroups(groups, {}); EXPECT_TRUE(mapped["a"].empty()); - EXPECT_EQ(std::unordered_set({ "a" }), mapped["b"]); - EXPECT_EQ(std::unordered_set({ "a", "b" }), mapped["c"]); + EXPECT_EQ(std::unordered_set({"a"}), mapped["b"]); + EXPECT_EQ(std::unordered_set({"a", "b"}), mapped["c"]); } TEST(GetTransitiveAfterGroups, shouldThrowIfAnAfterGroupDoesNotExist) { - std::unordered_set groups({ - Group("b", std::unordered_set({ "a" })) - }); + std::unordered_set groups( + {Group("b", std::unordered_set({"a"}))}); - EXPECT_THROW(GetTransitiveAfterGroups(groups), UndefinedGroupError); + EXPECT_THROW(GetTransitiveAfterGroups(groups, {}), UndefinedGroupError); } TEST(GetTransitiveAfterGroups, shouldThrowIfAfterGroupsAreCyclic) { - std::unordered_set groups({ - Group("a", std::unordered_set({ "c" })), - Group("b", std::unordered_set({ "a" })), - Group("c", std::unordered_set({ "b" })) - }); + std::unordered_set groups( + {Group("a", std::unordered_set({"c"})), + Group("b", std::unordered_set({"a"}))}); + std::unordered_set userGroups( + {Group("c", std::unordered_set({"b"}))}); try { - GetTransitiveAfterGroups(groups); + GetTransitiveAfterGroups(groups, userGroups); FAIL(); - } - catch (CyclicInteractionError &e) { + } catch (CyclicInteractionError &e) { ASSERT_EQ(3, e.GetCycle().size()); - EXPECT_EQ(EdgeType::LoadAfter, e.GetCycle()[0].GetTypeOfEdgeToNextVertex()); - EXPECT_EQ(EdgeType::LoadAfter, e.GetCycle()[1].GetTypeOfEdgeToNextVertex()); - EXPECT_EQ(EdgeType::LoadAfter, e.GetCycle()[2].GetTypeOfEdgeToNextVertex()); // Vertices can be added in any order, so which group is first is undefined. if (e.GetCycle()[0].GetName() == "a") { + EXPECT_EQ(EdgeType::MasterlistLoadAfter, + e.GetCycle()[0].GetTypeOfEdgeToNextVertex()); + EXPECT_EQ("c", e.GetCycle()[1].GetName()); + EXPECT_EQ(EdgeType::UserLoadAfter, + e.GetCycle()[1].GetTypeOfEdgeToNextVertex()); + EXPECT_EQ("b", e.GetCycle()[2].GetName()); + EXPECT_EQ(EdgeType::MasterlistLoadAfter, + e.GetCycle()[2].GetTypeOfEdgeToNextVertex()); } else if (e.GetCycle()[0].GetName() == "b") { + EXPECT_EQ(EdgeType::MasterlistLoadAfter, + e.GetCycle()[0].GetTypeOfEdgeToNextVertex()); + EXPECT_EQ("a", e.GetCycle()[1].GetName()); + EXPECT_EQ(EdgeType::MasterlistLoadAfter, + e.GetCycle()[1].GetTypeOfEdgeToNextVertex()); + EXPECT_EQ("c", e.GetCycle()[2].GetName()); + EXPECT_EQ(EdgeType::UserLoadAfter, + e.GetCycle()[2].GetTypeOfEdgeToNextVertex()); } else { EXPECT_EQ("c", e.GetCycle()[0].GetName()); + EXPECT_EQ(EdgeType::UserLoadAfter, + e.GetCycle()[0].GetTypeOfEdgeToNextVertex()); + EXPECT_EQ("b", e.GetCycle()[1].GetName()); + EXPECT_EQ(EdgeType::MasterlistLoadAfter, + e.GetCycle()[1].GetTypeOfEdgeToNextVertex()); + EXPECT_EQ("a", e.GetCycle()[2].GetName()); + EXPECT_EQ(EdgeType::MasterlistLoadAfter, + e.GetCycle()[2].GetTypeOfEdgeToNextVertex()); } } } diff --git a/src/tests/api/internals/sorting/plugin_sorter_test.h b/src/tests/api/internals/sorting/plugin_sorter_test.h index 70e53194..974b4a9f 100644 --- a/src/tests/api/internals/sorting/plugin_sorter_test.h +++ b/src/tests/api/internals/sorting/plugin_sorter_test.h @@ -98,9 +98,9 @@ protected: std::string getCCCFilename() { if (GetParam() == GameType::fo4) { return "Fallout4.ccc"; - } - else { - // Not every game has a .ccc file, but Skyrim SE does, so just assume that. + } else { + // Not every game has a .ccc file, but Skyrim SE does, so just assume + // that. return "Skyrim.ccc"; } } @@ -147,23 +147,28 @@ TEST_P(PluginSorterTest, auto esp = PluginSortingData( *dynamic_cast(game_.GetPlugin(blankEsp).value().get()), + PluginMetadata(), PluginMetadata()); EXPECT_FALSE(esp.IsMaster()); auto master = PluginSortingData( *dynamic_cast(game_.GetPlugin(blankEsm).value().get()), + PluginMetadata(), PluginMetadata()); EXPECT_TRUE(master.IsMaster()); if (GetParam() == GameType::fo4 || GetParam() == GameType::tes5se) { auto lightMaster = PluginSortingData( *dynamic_cast(game_.GetPlugin(blankEsl).value().get()), + PluginMetadata(), PluginMetadata()); EXPECT_TRUE(lightMaster.IsMaster()); - auto lightMasterEsp = PluginSortingData(*dynamic_cast( + auto lightMasterEsp = + PluginSortingData(*dynamic_cast( game_.GetPlugin(blankEslEsp).value().get()), - PluginMetadata()); + PluginMetadata(), + PluginMetadata()); EXPECT_FALSE(lightMasterEsp.IsMaster()); } } @@ -379,7 +384,8 @@ TEST_P( FAIL(); } catch (CyclicInteractionError &e) { ASSERT_EQ(3, e.GetCycle().size()); - EXPECT_EQ("Blank - Different Master Dependent.esm", e.GetCycle()[0].GetName()); + EXPECT_EQ("Blank - Different Master Dependent.esm", + e.GetCycle()[0].GetName()); EXPECT_EQ(EdgeType::Group, e.GetCycle()[0].GetTypeOfEdgeToNextVertex()); EXPECT_EQ("Blank.esm", e.GetCycle()[1].GetName()); EXPECT_EQ(EdgeType::Master, e.GetCycle()[1].GetTypeOfEdgeToNextVertex());