diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index 328074c0..245047fd 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -76,7 +76,8 @@ set(LIBLOOT_SRC_TESTS_INTERFACE_H_FILES
"${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/message_content_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/plugin_cleaning_data_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/plugin_metadata_test.h"
- "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/tag_test.h")
+ "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/tag_test.h"
+ "${CMAKE_SOURCE_DIR}/src/tests/api/interface/plugin_interface_test.h")
source_group(TREE "${CMAKE_SOURCE_DIR}/src/tests/api/internals"
PREFIX "Source Files"
diff --git a/src/tests/api/interface/main.cpp b/src/tests/api/interface/main.cpp
index 9e42be34..9b217666 100644
--- a/src/tests/api/interface/main.cpp
+++ b/src/tests/api/interface/main.cpp
@@ -38,6 +38,7 @@
#include "tests/api/interface/database_interface_test.h"
#include "tests/api/interface/game_interface_test.h"
#include "tests/api/interface/is_compatible_test.h"
+#include "tests/api/interface/plugin_interface_test.h"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
diff --git a/src/tests/api/interface/plugin_interface_test.h b/src/tests/api/interface/plugin_interface_test.h
new file mode 100644
index 00000000..ed8da8ba
--- /dev/null
+++ b/src/tests/api/interface/plugin_interface_test.h
@@ -0,0 +1,486 @@
+/* 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_TESTS_API_INTERFACE_PLUGIN_INTERFACE_TEST
+#define LOOT_TESTS_API_INTERFACE_PLUGIN_INTERFACE_TEST
+
+#include "loot/api.h"
+#include "tests/api/interface/api_game_operations_test.h"
+
+namespace loot::test {
+class PluginInterfaceTest : public ApiGameOperationsTest {
+protected:
+ PluginInterfaceTest() :
+ ApiGameOperationsTest(),
+ nonAsciiEsp(u8"non\u00C1scii.esp"),
+ otherNonAsciiEsp(u8"other non\u00C1scii.esp"),
+ blankArchive("Blank" + GetArchiveFileExtension(GetParam())),
+ blankSuffixArchive("Blank - Different - suffix" +
+ GetArchiveFileExtension(GetParam())) {}
+
+ void SetUp() override {
+ ApiGameOperationsTest::SetUp();
+
+ handle_->LoadPlugins(GetInstalledPlugins(), false);
+
+ if (!supportsLightPlugins(GetParam())) {
+ ASSERT_NO_THROW(
+ std::filesystem::copy(dataPath / blankEsp, dataPath / blankEsl));
+ }
+ ASSERT_TRUE(std::filesystem::exists(dataPath / blankEsl));
+
+ // Make sure the plugins with non-ASCII filenames exists.
+ ASSERT_NO_THROW(std::filesystem::copy_file(
+ dataPath / blankEsp, dataPath / std::filesystem::u8path(nonAsciiEsp)));
+ ASSERT_NO_THROW(std::filesystem::copy_file(
+ dataPath / blankEsp,
+ dataPath / std::filesystem::u8path(otherNonAsciiEsp)));
+
+ // Copy across archive files.
+ std::filesystem::path blankMasterDependentArchive;
+ if (GetParam() == GameType::fo4 || GetParam() == GameType::fo4vr ||
+ GetParam() == GameType::starfield) {
+ copyPlugin(getSourceArchivesPath(GetParam()), "Blank - Main.ba2");
+ copyPlugin(getSourceArchivesPath(GetParam()), "Blank - Textures.ba2");
+
+ blankMasterDependentArchive = "Blank - Master Dependent - Main.ba2";
+ std::filesystem::copy_file(
+ getSourceArchivesPath(GetParam()) / "Blank - Main.ba2",
+ dataPath / blankMasterDependentArchive);
+ ASSERT_TRUE(
+ std::filesystem::exists(dataPath / blankMasterDependentArchive));
+ } else if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw) {
+ touch(dataPath / blankArchive);
+
+ blankMasterDependentArchive = "Blank - Master Dependent.bsa";
+ touch(dataPath / blankMasterDependentArchive);
+ } else {
+ copyPlugin(getSourcePluginsPath(), blankArchive);
+
+ // Also create a copy for Blank - Master Dependent.esp to test overlap.
+ blankMasterDependentArchive = "Blank - Master Dependent.bsa";
+ std::filesystem::copy_file(getSourcePluginsPath() / blankArchive,
+ dataPath / blankMasterDependentArchive);
+ ASSERT_TRUE(
+ std::filesystem::exists(dataPath / blankMasterDependentArchive));
+ }
+
+ // Create dummy archive files.
+ touch(dataPath / blankSuffixArchive);
+
+ auto nonAsciiArchivePath =
+ dataPath / std::filesystem::u8path(u8"non\u00E1scii" +
+ GetArchiveFileExtension(GetParam()));
+ touch(dataPath / nonAsciiArchivePath);
+
+ auto nonAsciiPrefixArchivePath =
+ dataPath / std::filesystem::u8path(u8"other non\u00E1scii2 - suffix" +
+ GetArchiveFileExtension(GetParam()));
+ touch(dataPath / nonAsciiPrefixArchivePath);
+ }
+
+ std::shared_ptr LoadPluginHeader(
+ std::string_view pluginName) {
+ handle_->LoadPlugins({std::filesystem::u8path(pluginName)}, true);
+
+ return handle_->GetPlugin(pluginName);
+ }
+
+ std::shared_ptr LoadPlugin(
+ std::string_view pluginName) {
+ handle_->LoadPlugins({std::filesystem::u8path(pluginName)}, false);
+
+ return handle_->GetPlugin(pluginName);
+ }
+
+ std::string nonAsciiEsp;
+ std::string otherNonAsciiEsp;
+ std::string blankArchive;
+ std::string blankSuffixArchive;
+
+ std::shared_ptr game_;
+
+private:
+ static std::string GetArchiveFileExtension(const GameType gameType) {
+ if (gameType == GameType::fo4 || gameType == GameType::fo4vr ||
+ gameType == GameType::starfield)
+ return ".ba2";
+ else
+ return ".bsa";
+ }
+};
+
+class TestPlugin : public PluginInterface {
+public:
+ std::string GetName() const override { return ""; }
+
+ std::optional GetHeaderVersion() const override {
+ return std::optional();
+ }
+
+ std::optional GetVersion() const override {
+ return std::optional();
+ }
+
+ std::vector GetMasters() const override { return {}; }
+
+ std::vector GetBashTags() const override { return {}; }
+
+ std::optional GetCRC() const override {
+ return std::optional();
+ }
+
+ bool IsMaster() const override { return false; }
+
+ bool IsLightPlugin() const override { return false; }
+
+ bool IsMediumPlugin() const override { return false; }
+
+ bool IsUpdatePlugin() const override { return false; }
+
+ bool IsBlueprintPlugin() const override { return false; }
+
+ bool IsValidAsLightPlugin() const override { return false; }
+
+ bool IsValidAsMediumPlugin() const override { return false; }
+
+ bool IsValidAsUpdatePlugin() const override { return false; }
+
+ bool IsEmpty() const override { return false; }
+
+ bool LoadsArchive() const override { return false; }
+
+ bool DoRecordsOverlap(const PluginInterface&) const override { return false; }
+};
+
+// 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_SUITE_P(,
+ PluginInterfaceTest,
+ ::testing::ValuesIn(ALL_GAME_TYPES));
+
+TEST_P(PluginInterfaceTest,
+ shouldBeAbleToGetHeaderDataFromPluginLoadedHeaderOnly) {
+ const auto plugin = LoadPluginHeader(blankEsm);
+
+ EXPECT_EQ(blankEsm, plugin->GetName());
+ EXPECT_TRUE(plugin->GetMasters().empty());
+ if (GetParam() == GameType::openmw ||
+ GetParam() == GameType::oblivionRemastered) {
+ EXPECT_FALSE(plugin->IsMaster());
+ } else {
+ EXPECT_TRUE(plugin->IsMaster());
+ }
+ EXPECT_FALSE(plugin->IsEmpty());
+ EXPECT_EQ("5.0", plugin->GetVersion());
+
+ if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw) {
+ EXPECT_FLOAT_EQ(1.2f, plugin->GetHeaderVersion().value());
+ } else if (GetParam() == GameType::tes4 ||
+ GetParam() == GameType::oblivionRemastered) {
+ EXPECT_FLOAT_EQ(0.8f, plugin->GetHeaderVersion().value());
+ } else if (GetParam() == GameType::starfield) {
+ EXPECT_FLOAT_EQ(0.96f, plugin->GetHeaderVersion().value());
+ } else {
+ EXPECT_FLOAT_EQ(0.94f, plugin->GetHeaderVersion().value());
+ }
+}
+
+TEST_P(PluginInterfaceTest, shouldBeAbleToGetAllDataFromFullyLoadedPlugin) {
+ const auto plugin = LoadPlugin(blankEsm);
+
+ EXPECT_EQ(blankEsm, plugin->GetName());
+ EXPECT_TRUE(plugin->GetMasters().empty());
+ if (GetParam() == GameType::openmw ||
+ GetParam() == GameType::oblivionRemastered) {
+ EXPECT_FALSE(plugin->IsMaster());
+ } else {
+ EXPECT_TRUE(plugin->IsMaster());
+ }
+ EXPECT_FALSE(plugin->IsEmpty());
+ EXPECT_EQ("5.0", plugin->GetVersion());
+
+ if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw) {
+ EXPECT_FLOAT_EQ(1.2f, plugin->GetHeaderVersion().value());
+ } else if (GetParam() == GameType::tes4 ||
+ GetParam() == GameType::oblivionRemastered) {
+ EXPECT_FLOAT_EQ(0.8f, plugin->GetHeaderVersion().value());
+ } else if (GetParam() == GameType::starfield) {
+ EXPECT_FLOAT_EQ(0.96f, plugin->GetHeaderVersion().value());
+ } else {
+ EXPECT_FLOAT_EQ(0.94f, plugin->GetHeaderVersion().value());
+ }
+
+ EXPECT_EQ(blankEsmCrc, plugin->GetCRC());
+}
+
+TEST_P(PluginInterfaceTest,
+ loadingANonMasterPluginShouldReadTheMasterFlagAsFalse) {
+ const auto plugin = LoadPluginHeader(blankMasterDependentEsp);
+
+ EXPECT_FALSE(plugin->IsMaster());
+}
+
+TEST_P(
+ PluginInterfaceTest,
+ isLightPluginShouldBeTrueForAPluginWithEslFileExtensionForFallout4AndSkyrimSe) {
+ const auto plugin1 = LoadPluginHeader(blankEsm);
+ const auto plugin2 = LoadPluginHeader(blankMasterDependentEsp);
+
+ EXPECT_FALSE(plugin1->IsLightPlugin());
+ EXPECT_FALSE(plugin2->IsLightPlugin());
+
+ if (GetParam() == GameType::fo4 || GetParam() == GameType::fo4vr ||
+ GetParam() == GameType::tes5se || GetParam() == GameType::tes5vr ||
+ GetParam() == GameType::starfield) {
+ const auto plugin3 = LoadPluginHeader(blankEsl);
+ EXPECT_TRUE(plugin3->IsLightPlugin());
+ }
+}
+
+TEST_P(PluginInterfaceTest,
+ isMediumPluginShouldBeTrueForAMediumFlaggedPluginForStarfield) {
+ if (GetParam() != GameType::starfield) {
+ auto bytes = ReadFile(dataPath / blankEsm);
+ bytes[9] = 0x4;
+ WriteFile(dataPath / blankEsm, bytes);
+ }
+
+ const auto& pluginName =
+ GetParam() == GameType::starfield ? blankMediumEsm : blankEsm;
+ const auto plugin = LoadPluginHeader(pluginName);
+
+ EXPECT_EQ(GetParam() == GameType::starfield, plugin->IsMediumPlugin());
+}
+
+TEST_P(PluginInterfaceTest,
+ isUpdatePluginShouldOnlyBeTrueForAStarfieldUpdatePlugin) {
+ auto bytes = ReadFile(dataPath / blankMasterDependentEsp);
+ bytes[9] = 0x2;
+ WriteFile(dataPath / blankMasterDependentEsp, bytes);
+
+ const auto plugin1 = LoadPluginHeader(blankEsp);
+ const auto plugin2 = LoadPluginHeader(blankMasterDependentEsp);
+
+ EXPECT_FALSE(plugin1->IsUpdatePlugin());
+ EXPECT_EQ(GetParam() == GameType::starfield, plugin2->IsUpdatePlugin());
+}
+
+TEST_P(PluginInterfaceTest,
+ isBlueprintPluginShouldOnlyBeTrueForAStarfieldBlueprintPlugin) {
+ SetBlueprintFlag(dataPath / blankMasterDependentEsp);
+
+ const auto plugin1 = LoadPluginHeader(blankEsp);
+ const auto plugin2 = LoadPluginHeader(blankMasterDependentEsp);
+
+ EXPECT_FALSE(plugin1->IsBlueprintPlugin());
+ EXPECT_EQ(GetParam() == GameType::starfield, plugin2->IsBlueprintPlugin());
+}
+
+TEST_P(PluginInterfaceTest, loadingAPluginWithMastersShouldReadThemCorrectly) {
+ const auto plugin = LoadPluginHeader(blankMasterDependentEsp);
+
+ if (GetParam() == GameType::starfield) {
+ EXPECT_EQ(std::vector({blankFullEsm}), plugin->GetMasters());
+ } else {
+ EXPECT_EQ(std::vector({blankEsm}), plugin->GetMasters());
+ }
+}
+
+TEST_P(
+ PluginInterfaceTest,
+ loadsArchiveForAnArchiveThatExactlyMatchesAnEsmFileBasenameShouldReturnTrueForAllGamesExceptMorrowindAndOblivion) {
+ bool loadsArchive = LoadPluginHeader(blankEsm)->LoadsArchive();
+
+ if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
+ GetParam() == GameType::tes4 ||
+ GetParam() == GameType::oblivionRemastered)
+ EXPECT_FALSE(loadsArchive);
+ else
+ EXPECT_TRUE(loadsArchive);
+}
+
+#ifdef _WIN32
+TEST_P(
+ PluginInterfaceTest,
+ loadsArchiveForAnArchiveThatExactlyMatchesANonAsciiEspFileBasenameShouldReturnTrueForAllGamesExceptMorrowindAndStarfield) {
+ bool loadsArchive = LoadPluginHeader(nonAsciiEsp)->LoadsArchive();
+
+ if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
+ GetParam() == GameType::starfield)
+ EXPECT_FALSE(loadsArchive);
+ else
+ EXPECT_TRUE(loadsArchive);
+}
+#endif
+
+TEST_P(
+ PluginInterfaceTest,
+ loadsArchiveForAnArchiveThatExactlyMatchesAnEspFileBasenameShouldReturnTrueForAllGamesExceptMorrowind) {
+ bool loadsArchive = LoadPluginHeader(blankEsp)->LoadsArchive();
+
+ if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw)
+ EXPECT_FALSE(loadsArchive);
+ else
+ EXPECT_TRUE(loadsArchive);
+}
+
+TEST_P(
+ PluginInterfaceTest,
+ loadsArchiveForAnArchiveWithAFilenameWhichStartsWithTheEsmFileBasenameShouldReturnTrueForOnlyTheFalloutGames) {
+ bool loadsArchive = LoadPluginHeader(blankDifferentEsm)->LoadsArchive();
+
+ if (GetParam() == GameType::fo3 || GetParam() == GameType::fonv ||
+ GetParam() == GameType::fo4 || GetParam() == GameType::fo4vr) {
+ EXPECT_TRUE(loadsArchive);
+ } else {
+ EXPECT_FALSE(loadsArchive);
+ }
+}
+
+TEST_P(
+ PluginInterfaceTest,
+ loadsArchiveForAnArchiveWithAFilenameWhichStartsWithTheEspFileBasenameShouldReturnTrueForOnlyOblivionAndTheFalloutGames) {
+ bool loadsArchive = LoadPluginHeader(blankDifferentEsp)->LoadsArchive();
+
+ if (GetParam() == GameType::tes4 || GetParam() == GameType::fo3 ||
+ GetParam() == GameType::fonv || GetParam() == GameType::fo4 ||
+ GetParam() == GameType::fo4vr ||
+ GetParam() == GameType::oblivionRemastered) {
+ EXPECT_TRUE(loadsArchive);
+ } else {
+ EXPECT_FALSE(loadsArchive);
+ }
+}
+
+#ifdef _WIN32
+TEST_P(
+ PluginInterfaceTest,
+ loadsArchiveForAnArchiveWithAFilenameWhichStartsWithTheNonAsciiEspFileBasenameShouldReturnTrueForOnlyOblivionAndTheFalloutGames) {
+ bool loadsArchive = LoadPluginHeader(otherNonAsciiEsp)->LoadsArchive();
+
+ if (GetParam() == GameType::tes4 || GetParam() == GameType::fo3 ||
+ GetParam() == GameType::fonv || GetParam() == GameType::fo4 ||
+ GetParam() == GameType::fo4vr ||
+ GetParam() == GameType::oblivionRemastered) {
+ EXPECT_TRUE(loadsArchive);
+ } else {
+ EXPECT_FALSE(loadsArchive);
+ }
+}
+#endif
+
+TEST_P(PluginInterfaceTest,
+ loadsArchiveShouldReturnFalseForAPluginThatDoesNotLoadAnArchive) {
+ const auto pluginName = GetParam() == GameType::starfield
+ ? blankDifferentEsp
+ : blankDifferentMasterDependentEsp;
+ bool loadsArchive = LoadPluginHeader(pluginName)->LoadsArchive();
+
+ EXPECT_FALSE(loadsArchive);
+}
+
+TEST_P(
+ PluginInterfaceTest,
+ isValidAsLightPluginShouldReturnTrueOnlyForASkyrimSEOrFallout4PluginWithNewFormIdsBetween0x800And0xFFFInclusive) {
+ bool valid = LoadPlugin(blankEsm)->IsValidAsLightPlugin();
+ if (GetParam() == GameType::fo4 || GetParam() == GameType::fo4vr ||
+ GetParam() == GameType::tes5se || GetParam() == GameType::tes5vr ||
+ GetParam() == GameType::starfield) {
+ EXPECT_TRUE(valid);
+ } else {
+ EXPECT_FALSE(valid);
+ }
+}
+
+TEST_P(
+ PluginInterfaceTest,
+ isValidAsMediumPluginShouldReturnTrueOnlyForAStarfieldPluginWithNewFormIdsBetween0And0xFFFFInclusive) {
+ bool valid = LoadPlugin(blankEsm)->IsValidAsMediumPlugin();
+ if (GetParam() == GameType::starfield) {
+ EXPECT_TRUE(valid);
+ } else {
+ EXPECT_FALSE(valid);
+ }
+}
+
+TEST_P(
+ PluginInterfaceTest,
+ IsValidAsUpdatePluginShouldOnlyReturnTrueForAStarfieldPluginWithNoNewRecords) {
+ const auto sourcePluginName =
+ GetParam() == GameType::starfield ? blankFullEsm : blankEsp;
+ const auto updatePluginName = GetParam() == GameType::starfield
+ ? blankMasterDependentEsp
+ : blankDifferentPluginDependentEsp;
+
+ std::vector> plugins;
+ plugins.push_back(LoadPlugin(sourcePluginName));
+ plugins.push_back(LoadPlugin(updatePluginName));
+
+ EXPECT_FALSE(plugins[0]->IsValidAsUpdatePlugin());
+ EXPECT_EQ(GetParam() == GameType::starfield,
+ plugins[1]->IsValidAsUpdatePlugin());
+}
+
+TEST_P(PluginInterfaceTest,
+ doRecordsOverlapShouldReturnFalseIfTheArgumentIsNotAPluginObject) {
+ const auto plugin1 = LoadPlugin(blankEsm);
+ TestPlugin plugin2;
+
+ EXPECT_FALSE(plugin1->DoRecordsOverlap(plugin2));
+}
+
+TEST_P(PluginInterfaceTest,
+ doRecordsOverlapShouldReturnFalseForTwoPluginsWithOnlyHeadersLoaded) {
+ const auto plugin1 = LoadPluginHeader(blankEsm);
+ const auto plugin2 = LoadPluginHeader(blankMasterDependentEsm);
+
+ EXPECT_FALSE(plugin1->DoRecordsOverlap(*plugin2));
+ EXPECT_FALSE(plugin2->DoRecordsOverlap(*plugin1));
+}
+
+TEST_P(PluginInterfaceTest,
+ doRecordsOverlapShouldReturnFalseIfThePluginsHaveUnrelatedRecords) {
+ const auto plugin1 = LoadPlugin(blankEsm);
+ const auto plugin2 = LoadPlugin(blankEsp);
+
+ EXPECT_FALSE(plugin1->DoRecordsOverlap(*plugin2));
+ EXPECT_FALSE(plugin2->DoRecordsOverlap(*plugin1));
+}
+
+TEST_P(PluginInterfaceTest,
+ doRecordsOverlapShouldReturnTrueIfOnePluginOverridesTheOthersRecords) {
+ const auto plugin1Name =
+ GetParam() == GameType::starfield ? blankFullEsm : blankEsm;
+
+ const auto plugin1 = LoadPlugin(plugin1Name);
+ const auto plugin2 = LoadPlugin(blankMasterDependentEsm);
+
+ EXPECT_TRUE(plugin1->DoRecordsOverlap(*plugin2));
+ EXPECT_TRUE(plugin2->DoRecordsOverlap(*plugin1));
+}
+
+}
+
+#endif
diff --git a/src/tests/api/internals/plugin_test.h b/src/tests/api/internals/plugin_test.h
index 4c7e198a..b9151cba 100644
--- a/src/tests/api/internals/plugin_test.h
+++ b/src/tests/api/internals/plugin_test.h
@@ -278,67 +278,6 @@ TEST_P(PluginTest, loadingShouldHandleNonAsciiFilenamesCorrectly) {
EXPECT_EQ(nonAsciiEsp, plugin.GetName());
}
-TEST_P(PluginTest, loadingHeaderOnlyShouldReadHeaderData) {
- Plugin plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true);
-
- EXPECT_EQ(blankEsm, plugin.GetName());
- EXPECT_TRUE(plugin.GetMasters().empty());
- if (GetParam() == GameType::openmw ||
- GetParam() == GameType::oblivionRemastered) {
- EXPECT_FALSE(plugin.IsMaster());
- } else {
- EXPECT_TRUE(plugin.IsMaster());
- }
- EXPECT_FALSE(plugin.IsEmpty());
- EXPECT_EQ("5.0", plugin.GetVersion());
-
- if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw) {
- EXPECT_FLOAT_EQ(1.2f, plugin.GetHeaderVersion().value());
- } else if (GetParam() == GameType::tes4 ||
- GetParam() == GameType::oblivionRemastered) {
- EXPECT_FLOAT_EQ(0.8f, plugin.GetHeaderVersion().value());
- } else if (GetParam() == GameType::starfield) {
- EXPECT_FLOAT_EQ(0.96f, plugin.GetHeaderVersion().value());
- } else {
- EXPECT_FLOAT_EQ(0.94f, plugin.GetHeaderVersion().value());
- }
-}
-
-TEST_P(PluginTest, loadingHeaderOnlyShouldNotReadFieldsOrCalculateCrc) {
- Plugin plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true);
-
- EXPECT_FALSE(plugin.GetCRC());
-}
-
-TEST_P(PluginTest, loadingWholePluginShouldReadHeaderData) {
- Plugin plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true);
-
- EXPECT_EQ(blankEsm, plugin.GetName());
- EXPECT_TRUE(plugin.GetMasters().empty());
- if (GetParam() == GameType::openmw ||
- GetParam() == GameType::oblivionRemastered) {
- EXPECT_FALSE(plugin.IsMaster());
- } else {
- EXPECT_TRUE(plugin.IsMaster());
- }
- EXPECT_FALSE(plugin.IsEmpty());
- EXPECT_EQ("5.0", plugin.GetVersion());
-
- if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw) {
- EXPECT_FLOAT_EQ(1.2f, plugin.GetHeaderVersion().value());
- } else if (GetParam() == GameType::tes4 ||
- GetParam() == GameType::oblivionRemastered) {
- EXPECT_FLOAT_EQ(0.8f, plugin.GetHeaderVersion().value());
- } else if (GetParam() == GameType::starfield) {
- EXPECT_FLOAT_EQ(0.96f, plugin.GetHeaderVersion().value());
- } else {
- EXPECT_FLOAT_EQ(0.94f, plugin.GetHeaderVersion().value());
- }
-}
-
TEST_P(PluginTest, loadingWholePluginShouldReadFields) {
const auto pluginName = GetParam() == GameType::openmw
? blankMasterDependentEsm
@@ -369,22 +308,6 @@ TEST_P(PluginTest, loadingWholePluginShouldReadFields) {
}
}
-TEST_P(PluginTest, loadingWholePluginShouldCalculateCrc) {
- Plugin plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false);
-
- EXPECT_EQ(blankEsmCrc, plugin.GetCRC());
-}
-
-TEST_P(PluginTest, loadingANonMasterPluginShouldReadTheMasterFlagAsFalse) {
- Plugin plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / blankMasterDependentEsp,
- true);
-
- EXPECT_FALSE(plugin.IsMaster());
-}
-
TEST_P(PluginTest, loadingWholePluginShouldSucceedForOpenMWPlugins) {
const auto omwgame = "Blank.omwgame";
const auto omwaddon = "Blank.omwaddon";
@@ -430,66 +353,6 @@ TEST_P(
plugin3.IsLightPlugin());
}
-TEST_P(PluginTest,
- isMediumPluginShouldBeTrueForAMediumFlaggedPluginForStarfield) {
- if (GetParam() != GameType::starfield) {
- auto bytes = ReadFile(dataPath / blankEsm);
- bytes[9] = 0x4;
- WriteFile(dataPath / blankEsm, bytes);
- }
-
- const auto pluginName =
- GetParam() == GameType::starfield ? blankMediumEsm : blankEsm;
- Plugin plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / pluginName, true);
-
- EXPECT_EQ(GetParam() == GameType::starfield, plugin.IsMediumPlugin());
-}
-
-TEST_P(PluginTest, isUpdatePluginShouldOnlyBeTrueForAStarfieldUpdatePlugin) {
- auto bytes = ReadFile(dataPath / blankMasterDependentEsp);
- bytes[9] = 0x2;
- WriteFile(dataPath / blankMasterDependentEsp, bytes);
-
- Plugin plugin1(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsp, true);
- Plugin plugin2(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / blankMasterDependentEsp,
- true);
-
- EXPECT_FALSE(plugin1.IsUpdatePlugin());
- EXPECT_EQ(GetParam() == GameType::starfield, plugin2.IsUpdatePlugin());
-}
-
-TEST_P(PluginTest,
- isBlueprintPluginShouldOnlyBeTrueForAStarfieldBlueprintPlugin) {
- SetBlueprintFlag(dataPath / blankMasterDependentEsp);
-
- Plugin plugin1(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsp, true);
- Plugin plugin2(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / blankMasterDependentEsp,
- true);
-
- EXPECT_FALSE(plugin1.IsBlueprintPlugin());
- EXPECT_EQ(GetParam() == GameType::starfield, plugin2.IsBlueprintPlugin());
-}
-
-TEST_P(PluginTest, loadingAPluginWithMastersShouldReadThemCorrectly) {
- Plugin plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / blankMasterDependentEsp,
- true);
-
- if (GetParam() == GameType::starfield) {
- EXPECT_EQ(std::vector({blankFullEsm}), plugin.GetMasters());
- } else {
- EXPECT_EQ(std::vector({blankEsm}), plugin.GetMasters());
- }
-}
-
TEST_P(PluginTest, loadingAPluginThatDoesNotExistShouldThrow) {
try {
Plugin(game_.GetType(),
@@ -503,125 +366,6 @@ TEST_P(PluginTest, loadingAPluginThatDoesNotExistShouldThrow) {
}
}
-TEST_P(
- PluginTest,
- loadsArchiveForAnArchiveThatExactlyMatchesAnEsmFileBasenameShouldReturnTrueForAllGamesExceptMorrowindAndOblivion) {
- bool loadsArchive =
- Plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true)
- .LoadsArchive();
-
- if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
- GetParam() == GameType::tes4 ||
- GetParam() == GameType::oblivionRemastered)
- EXPECT_FALSE(loadsArchive);
- else
- EXPECT_TRUE(loadsArchive);
-}
-
-#ifdef _WIN32
-TEST_P(
- PluginTest,
- loadsArchiveForAnArchiveThatExactlyMatchesANonAsciiEspFileBasenameShouldReturnTrueForAllGamesExceptMorrowindAndStarfield) {
- bool loadsArchive =
- Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / std::filesystem::u8path(nonAsciiEsp),
- true)
- .LoadsArchive();
-
- if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
- GetParam() == GameType::starfield)
- EXPECT_FALSE(loadsArchive);
- else
- EXPECT_TRUE(loadsArchive);
-}
-#endif
-
-TEST_P(
- PluginTest,
- loadsArchiveForAnArchiveThatExactlyMatchesAnEspFileBasenameShouldReturnTrueForAllGamesExceptMorrowind) {
- bool loadsArchive =
- Plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsp, true)
- .LoadsArchive();
-
- if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw)
- EXPECT_FALSE(loadsArchive);
- else
- EXPECT_TRUE(loadsArchive);
-}
-
-TEST_P(
- PluginTest,
- loadsArchiveForAnArchiveWithAFilenameWhichStartsWithTheEsmFileBasenameShouldReturnTrueForOnlyTheFalloutGames) {
- bool loadsArchive = Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / blankDifferentEsm,
- true)
- .LoadsArchive();
-
- if (GetParam() == GameType::fo3 || GetParam() == GameType::fonv ||
- GetParam() == GameType::fo4 || GetParam() == GameType::fo4vr) {
- EXPECT_TRUE(loadsArchive);
- } else {
- EXPECT_FALSE(loadsArchive);
- }
-}
-
-TEST_P(
- PluginTest,
- loadsArchiveForAnArchiveWithAFilenameWhichStartsWithTheEspFileBasenameShouldReturnTrueForOnlyOblivionAndTheFalloutGames) {
- bool loadsArchive = Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / blankDifferentEsp,
- true)
- .LoadsArchive();
-
- if (GetParam() == GameType::tes4 || GetParam() == GameType::fo3 ||
- GetParam() == GameType::fonv || GetParam() == GameType::fo4 ||
- GetParam() == GameType::fo4vr ||
- GetParam() == GameType::oblivionRemastered) {
- EXPECT_TRUE(loadsArchive);
- } else {
- EXPECT_FALSE(loadsArchive);
- }
-}
-
-#ifdef _WIN32
-TEST_P(
- PluginTest,
- loadsArchiveForAnArchiveWithAFilenameWhichStartsWithTheNonAsciiEspFileBasenameShouldReturnTrueForOnlyOblivionAndTheFalloutGames) {
- bool loadsArchive =
- Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / std::filesystem::u8path(otherNonAsciiEsp),
- true)
- .LoadsArchive();
-
- if (GetParam() == GameType::tes4 || GetParam() == GameType::fo3 ||
- GetParam() == GameType::fonv || GetParam() == GameType::fo4 ||
- GetParam() == GameType::fo4vr ||
- GetParam() == GameType::oblivionRemastered) {
- EXPECT_TRUE(loadsArchive);
- } else {
- EXPECT_FALSE(loadsArchive);
- }
-}
-#endif
-
-TEST_P(PluginTest,
- loadsArchiveShouldReturnFalseForAPluginThatDoesNotLoadAnArchive) {
- const auto pluginName = GetParam() == GameType::starfield
- ? blankDifferentEsp
- : blankDifferentMasterDependentEsp;
- EXPECT_FALSE(Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / pluginName,
- true)
- .LoadsArchive());
-}
-
TEST_P(PluginTest, isValidShouldReturnTrueForAValidPlugin) {
EXPECT_TRUE(Plugin::IsValid(game_.GetType(), game_.DataPath() / blankEsm));
}
@@ -655,138 +399,6 @@ TEST_P(PluginTest, isValidShouldReturnTrueForAnOpenMWOmwscriptsFile) {
}
}
-TEST_P(
- PluginTest,
- isValidAsLightPluginShouldReturnTrueOnlyForASkyrimSEOrFallout4PluginWithNewFormIdsBetween0x800And0xFFFInclusive) {
- bool valid =
- Plugin(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true)
- .IsValidAsLightPlugin();
- if (GetParam() == GameType::fo4 || GetParam() == GameType::fo4vr ||
- GetParam() == GameType::tes5se || GetParam() == GameType::tes5vr ||
- GetParam() == GameType::starfield) {
- EXPECT_TRUE(valid);
- } else {
- EXPECT_FALSE(valid);
- }
-}
-
-TEST_P(
- PluginTest,
- isValidAsMediumPluginShouldReturnTrueOnlyForAStarfieldPluginWithNewFormIdsBetween0And0xFFFFInclusive) {
- bool valid =
- Plugin(game_.GetType(), game_.GetCache(), dataPath / blankEsm, true)
- .IsValidAsMediumPlugin();
- if (GetParam() == GameType::starfield) {
- EXPECT_TRUE(valid);
- } else {
- EXPECT_FALSE(valid);
- }
-}
-
-TEST_P(
- PluginTest,
- IsValidAsUpdatePluginShouldOnlyReturnTrueForAStarfieldPluginWithNoNewRecords) {
- const auto sourcePluginName =
- GetParam() == GameType::starfield ? blankFullEsm : blankEsp;
- const auto updatePluginName = GetParam() == GameType::starfield
- ? blankMasterDependentEsp
- : blankDifferentPluginDependentEsp;
-
- std::vector plugins;
- plugins.push_back(Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / sourcePluginName,
- false));
- plugins.push_back(Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / updatePluginName,
- false));
-
- if (GetParam() == GameType::starfield) {
- const auto pluginsMetadata =
- Plugin::GetPluginsMetadata({&plugins[0], &plugins[1]});
- plugins[1].ResolveRecordIds(pluginsMetadata.get());
-
- plugins[0].ResolveRecordIds(nullptr);
- plugins[1].ResolveRecordIds(nullptr);
- }
-
- EXPECT_FALSE(plugins[0].IsValidAsUpdatePlugin());
- EXPECT_EQ(GetParam() == GameType::starfield,
- plugins[1].IsValidAsUpdatePlugin());
-}
-
-TEST_P(PluginTest,
- doRecordsOverlapShouldReturnFalseIfTheArgumentIsNotAPluginObject) {
- Plugin plugin1(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false);
- TestPlugin plugin2;
-
- EXPECT_FALSE(plugin1.DoRecordsOverlap(plugin2));
-}
-
-TEST_P(PluginTest,
- doRecordsOverlapShouldReturnFalseForTwoPluginsWithOnlyHeadersLoaded) {
- Plugin plugin1(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true);
-
- const auto pluginName = GetParam() == GameType::openmw
- ? blankMasterDependentEsm
- : blankMasterDependentEsm + ".ghost";
- Plugin plugin2(
- game_.GetType(), game_.GetCache(), game_.DataPath() / pluginName, true);
-
- EXPECT_FALSE(plugin1.DoRecordsOverlap(plugin2));
- EXPECT_FALSE(plugin2.DoRecordsOverlap(plugin1));
-}
-
-TEST_P(PluginTest,
- doRecordsOverlapShouldReturnFalseIfThePluginsHaveUnrelatedRecords) {
- Plugin plugin1(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false);
- Plugin plugin2(
- game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsp, false);
-
- if (GetParam() == GameType::starfield) {
- plugin1.ResolveRecordIds(nullptr);
- plugin2.ResolveRecordIds(nullptr);
- }
-
- EXPECT_FALSE(plugin1.DoRecordsOverlap(plugin2));
- EXPECT_FALSE(plugin2.DoRecordsOverlap(plugin1));
-}
-
-TEST_P(PluginTest,
- doRecordsOverlapShouldReturnTrueIfOnePluginOverridesTheOthersRecords) {
- const auto plugin1Name =
- GetParam() == GameType::starfield ? blankFullEsm : blankEsm;
- const auto plugin2Name = GetParam() == GameType::openmw
- ? blankMasterDependentEsm
- : blankMasterDependentEsm + ".ghost";
-
- std::vector plugins;
- plugins.push_back(Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / plugin1Name,
- false));
- plugins.push_back(Plugin(game_.GetType(),
- game_.GetCache(),
- game_.DataPath() / plugin2Name,
- false));
-
- if (GetParam() == GameType::starfield) {
- plugins[0].ResolveRecordIds(nullptr);
-
- const auto pluginsMetadata =
- Plugin::GetPluginsMetadata({&plugins[0], &plugins[1]});
- plugins[1].ResolveRecordIds(pluginsMetadata.get());
- }
-
- EXPECT_TRUE(plugins[0].DoRecordsOverlap(plugins[1]));
- EXPECT_TRUE(plugins[1].DoRecordsOverlap(plugins[0]));
-}
-
TEST_P(PluginTest,
getAssetCountShouldReturnNumberOfFilesInArchivesLoadedByPlugin) {
const auto assetCount =