Make some plugin tests interface tests

This commit is contained in:
Oliver Hamlet
2025-05-01 21:48:52 +01:00
parent 0c75629fff
commit ca689727a1
4 changed files with 489 additions and 389 deletions
+2 -1
View File
@@ -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"
+1
View File
@@ -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);
@@ -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
<https://www.gnu.org/licenses/>.
*/
#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<const PluginInterface> LoadPluginHeader(
std::string_view pluginName) {
handle_->LoadPlugins({std::filesystem::u8path(pluginName)}, true);
return handle_->GetPlugin(pluginName);
}
std::shared_ptr<const PluginInterface> 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<GameInterface> 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<float> GetHeaderVersion() const override {
return std::optional<float>();
}
std::optional<std::string> GetVersion() const override {
return std::optional<std::string>();
}
std::vector<std::string> GetMasters() const override { return {}; }
std::vector<std::string> GetBashTags() const override { return {}; }
std::optional<uint32_t> GetCRC() const override {
return std::optional<uint32_t>();
}
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<std::string>({blankFullEsm}), plugin->GetMasters());
} else {
EXPECT_EQ(std::vector<std::string>({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<std::shared_ptr<const PluginInterface>> 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
-388
View File
@@ -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<std::string>({blankFullEsm}), plugin.GetMasters());
} else {
EXPECT_EQ(std::vector<std::string>({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<Plugin> 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<Plugin> 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 =