diff --git a/src/api/plugin/plugin.cpp b/src/api/plugin/plugin.cpp index 7a92027a..6b448b63 100644 --- a/src/api/plugin/plugin.cpp +++ b/src/api/plugin/plugin.cpp @@ -160,26 +160,27 @@ bool Plugin::LoadsArchive() const { } bool Plugin::DoFormIDsOverlap(const PluginInterface& plugin) const { - // Assume the PluginInterface is another plugin: it'll throw if it's not. - // Not great design, but the function needs getFormIds() and that can't - // be exposed in the interface. - const Plugin& otherPlugin = dynamic_cast(plugin); + try { + auto otherPlugin = dynamic_cast(plugin); - //Basically std::set_intersection except with an early exit instead of an append to results. - set formIds(getFormIds()); - set otherFormIds(otherPlugin.getFormIds()); - auto i = begin(formIds); - auto j = begin(otherFormIds); - auto iend = end(formIds); - auto jend = end(otherFormIds); + //Basically std::set_intersection except with an early exit instead of an append to results. + set formIds(getFormIds()); + set otherFormIds(otherPlugin.getFormIds()); + auto i = begin(formIds); + auto j = begin(otherFormIds); + auto iend = end(formIds); + auto jend = end(otherFormIds); - while (i != iend && j != jend) { - if (*i < *j) - ++i; - else if (*j < *i) - ++j; - else - return true; + while (i != iend && j != jend) { + if (*i < *j) + ++i; + else if (*j < *i) + ++j; + else + return true; + } + } catch (std::bad_cast& e) { + BOOST_LOG_TRIVIAL(error) << "Tried to check if FormIDs overlapped with a non-Plugin implementation of PluginInterface."; } return false; diff --git a/src/tests/api/internals/plugin/plugin_test.h b/src/tests/api/internals/plugin/plugin_test.h index 25d71eec..07016af7 100644 --- a/src/tests/api/internals/plugin/plugin_test.h +++ b/src/tests/api/internals/plugin/plugin_test.h @@ -79,6 +79,22 @@ protected: const std::string blankSuffixArchive; }; +class OtherPluginType : public PluginInterface { +public: + std::string GetName() const { return ""; } + 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; } + + bool IsMaster() const { return false; } + bool IsEmpty() const { return false; } + bool LoadsArchive() const { return false; } + bool DoFormIDsOverlap(const PluginInterface& plugin) const { return true; } +}; + // 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(, @@ -216,6 +232,14 @@ TEST_P(PluginTest, lessThanOperatorShouldUseCaseInsensitiveLexicographicalNameCo EXPECT_FALSE(plugin4 < plugin3); } +TEST_P(PluginTest, doFormIDsOverlapShouldReturnFalseIfTheArgumentIsNotAPluginObject) { + Plugin plugin1(game_, blankEsm, false); + OtherPluginType plugin2; + + EXPECT_FALSE(plugin1.DoFormIDsOverlap(plugin2)); + EXPECT_TRUE(plugin2.DoFormIDsOverlap(plugin1)); +} + TEST_P(PluginTest, doFormIDsOverlapShouldReturnFalseForTwoPluginsWithOnlyHeadersLoaded) { Plugin plugin1(game_, blankEsm, true); Plugin plugin2(game_, blankMasterDependentEsm, true);