Sync with libloot v0.26.1

Aside from adding GameType::oblivionRemastered and its usage, this is almost entirely about moving C++ files and tests around.
This commit is contained in:
Oliver Hamlet
2025-05-02 17:56:49 +01:00
parent f1186e4c08
commit eabc7a5d85
52 changed files with 1100 additions and 184 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
#include "api/convert.h"
#include "api/exception.h"
#include "api/exception/exception.h"
namespace loot {
// To public types
+1 -1
View File
@@ -2,7 +2,7 @@
#include "api/database.h"
#include "api/convert.h"
#include "api/exception.h"
#include "api/exception/exception.h"
namespace loot {
Database::Database(::rust::Box<loot::rust::Database>&& database) :
@@ -1,4 +1,4 @@
#include "api/exception.h"
#include "api/exception/exception.h"
#include <charconv>
+5 -1
View File
@@ -2,7 +2,7 @@
#include "api/game.h"
#include "api/convert.h"
#include "api/exception.h"
#include "api/exception/exception.h"
namespace {
loot::GameType convert(loot::rust::GameType gameType) {
@@ -29,6 +29,8 @@ loot::GameType convert(loot::rust::GameType gameType) {
return loot::GameType::starfield;
case loot::rust::GameType::OpenMW:
return loot::GameType::openmw;
case loot::rust::GameType::OblivionRemastered:
return loot::GameType::oblivionRemastered;
default:
throw std::logic_error("Unsupported GameType value");
}
@@ -58,6 +60,8 @@ loot::rust::GameType convert(loot::GameType gameType) {
return loot::rust::GameType::Starfield;
case loot::GameType::openmw:
return loot::rust::GameType::OpenMW;
case loot::GameType::oblivionRemastered:
return loot::rust::GameType::OblivionRemastered;
default:
throw std::logic_error("Unsupported GameType value");
}
+1 -1
View File
@@ -22,7 +22,7 @@ public:
GameType GetType() const override;
std::vector<std::filesystem::path> GetAdditionalDataPaths() const;
std::vector<std::filesystem::path> GetAdditionalDataPaths() const override;
void SetAdditionalDataPaths(
const std::vector<std::filesystem::path>& additionalDataPaths) override;
+2 -4
View File
@@ -4,7 +4,7 @@
#include <typeinfo>
#include "api/convert.h"
#include "api/exception.h"
#include "api/exception/exception.h"
namespace loot {
Plugin::Plugin(::rust::Box<loot::rust::Plugin> plugin) :
@@ -101,9 +101,7 @@ bool Plugin::DoRecordsOverlap(const PluginInterface& plugin) const {
return plugin_->do_records_overlap(*otherPlugin.plugin_);
} catch (std::bad_cast&) {
throw std::invalid_argument(
"Tried to check if records overlapped with a different concrete type "
"implementing PluginInterface");
return false;
} catch (const ::rust::Error& e) {
std::rethrow_exception(mapError(e));
}
+2 -2
View File
@@ -13,12 +13,12 @@ BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "LOOT"
VALUE "FileDescription", "Library providing LOOT's core functionality"
VALUE "FileVersion", "0.26.0"
VALUE "FileVersion", "0.26.1"
VALUE "InternalName", "loot"
VALUE "LegalCopyright", "Copyright (C) 2013-2022 Oliver Hamlet"
VALUE "OriginalFilename", "loot.dll"
VALUE "ProductName", "LOOT"
VALUE "ProductVersion", "0.26.0"
VALUE "ProductVersion", "0.26.1"
END
END
BLOCK "VarFileInfo"
+2
View File
@@ -21,6 +21,7 @@ impl TryFrom<libloot::GameType> for GameType {
libloot::GameType::Morrowind => Ok(GameType::Morrowind),
libloot::GameType::Starfield => Ok(GameType::Starfield),
libloot::GameType::OpenMW => Ok(GameType::OpenMW),
libloot::GameType::OblivionRemastered => Ok(GameType::OblivionRemastered),
_ => Err(UnsupportedEnumValueError),
}
}
@@ -42,6 +43,7 @@ impl TryFrom<GameType> for libloot::GameType {
GameType::Morrowind => Ok(libloot::GameType::Morrowind),
GameType::Starfield => Ok(libloot::GameType::Starfield),
GameType::OpenMW => Ok(libloot::GameType::OpenMW),
GameType::OblivionRemastered => Ok(libloot::GameType::OblivionRemastered),
_ => Err(UnsupportedEnumValueError),
}
}
+1
View File
@@ -232,6 +232,7 @@ mod ffi {
Morrowind,
Starfield,
OpenMW,
OblivionRemastered,
}
pub enum MessageType {
@@ -88,17 +88,7 @@ protected:
// but we only have the one so no prefix is necessary.
INSTANTIATE_TEST_SUITE_P(,
CreateGameHandleTest,
::testing::Values(GameType::tes4,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4,
GameType::tes5se,
GameType::fo4vr,
GameType::tes5vr,
GameType::tes3,
GameType::starfield,
GameType::openmw));
::testing::ValuesIn(ALL_GAME_TYPES));
TEST_P(CreateGameHandleTest,
shouldSucceedIfPassedValidParametersWithRelativePaths) {
@@ -151,6 +141,74 @@ TEST_P(CreateGameHandleTest,
EXPECT_TRUE(handle_);
}
#endif
#ifndef _WIN32
TEST_P(
CreateGameHandleTest,
shouldThrowOnLinuxIfLocalPathIsNotGivenExceptForMorrowindOpenMWAndOblivionRemastered) {
if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
GetParam() == GameType::oblivionRemastered) {
EXPECT_NO_THROW(CreateGameHandle(GetParam(), gamePath));
} else {
EXPECT_THROW(CreateGameHandle(GetParam(), gamePath), std::system_error);
}
}
#else
TEST_P(CreateGameHandleTest,
shouldNotThrowOnWindowsIfLocalPathIsNotGiven) {
EXPECT_NO_THROW(CreateGameHandle(GetParam(), gamePath));
}
#endif
TEST_P(CreateGameHandleTest,
shouldNotThrowIfGameAndLocalPathsAreNotEmpty) {
EXPECT_NO_THROW(CreateGameHandle(GetParam(), gamePath, localPath));
}
TEST_P(
CreateGameHandleTest,
shouldSetAdditionalDataPathsForFallout4FromMicrosoftStoreOrStarfield) {
if (GetParam() == GameType::fo4) {
// Create the file that indicates it's a Microsoft Store install.
touch(gamePath / "appxmanifest.xml");
} else if (GetParam() == GameType::openmw) {
std::ofstream out(gamePath / "openmw.cfg");
out << "data-local=\"" << (localPath / "data").u8string() << "\""
<< std::endl
<< "config=\"" << localPath.u8string() << "\"";
}
const auto game = CreateGameHandle(GetParam(), gamePath, localPath);
if (GetParam() == GameType::fo4) {
const auto basePath = gamePath / ".." / "..";
EXPECT_EQ(std::vector<std::filesystem::path>(
{basePath / "Fallout 4- Automatron (PC)" / "Content" / "Data",
basePath / "Fallout 4- Nuka-World (PC)" / "Content" / "Data",
basePath / "Fallout 4- Wasteland Workshop (PC)" / "Content" /
"Data",
basePath / "Fallout 4- High Resolution Texture Pack" /
"Content" / "Data",
basePath / "Fallout 4- Vault-Tec Workshop (PC)" / "Content" /
"Data",
basePath / "Fallout 4- Far Harbor (PC)" / "Content" / "Data",
basePath / "Fallout 4- Contraptions Workshop (PC)" /
"Content" / "Data"}),
game->GetAdditionalDataPaths());
} else if (GetParam() == GameType::starfield) {
ASSERT_EQ(1, game->GetAdditionalDataPaths().size());
const auto expectedSuffix = std::filesystem::u8path("Documents") /
"My Games" / "Starfield" / "Data";
EXPECT_TRUE(endsWith(game->GetAdditionalDataPaths()[0].u8string(),
expectedSuffix.u8string()));
} else if (GetParam() == GameType::openmw) {
EXPECT_EQ(std::vector<std::filesystem::path>{localPath / "data"},
game->GetAdditionalDataPaths());
} else {
EXPECT_TRUE(game->GetAdditionalDataPaths().empty());
}
}
}
}
@@ -113,12 +113,7 @@ protected:
// but we only have the one so no prefix is necessary.
INSTANTIATE_TEST_SUITE_P(,
DatabaseInterfaceTest,
::testing::Values(GameType::tes4,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4,
GameType::tes5se));
::testing::ValuesIn(ALL_GAME_TYPES));
TEST_P(DatabaseInterfaceTest,
loadMasterlistShouldSucceedEvenIfGameHandleIsDiscarded) {
@@ -275,7 +270,7 @@ TEST_P(DatabaseInterfaceTest, writeUserMetadataShouldShouldWriteUserMetadata) {
}
TEST_P(DatabaseInterfaceTest, evaluateShouldReturnTrueIfTheConditionIsTrue) {
EXPECT_TRUE(handle_->GetDatabase().Evaluate("file(\"Blank.esp\")"));
EXPECT_TRUE(handle_->GetDatabase().Evaluate("file(\"Blank.esp\")"));
}
TEST_P(DatabaseInterfaceTest, evaluateShouldReturnFalseIfTheConditionIsFalse) {
+345 -14
View File
@@ -30,6 +30,8 @@ along with LOOT. If not, see
namespace loot {
namespace test {
constexpr unsigned int ESP_ERROR_PLUGIN_METADATA_NOT_FOUND = 14;
class GameInterfaceTest : public ApiGameOperationsTest {
protected:
GameInterfaceTest() :
@@ -74,17 +76,7 @@ protected:
// but we only have the one so no prefix is necessary.
INSTANTIATE_TEST_SUITE_P(,
GameInterfaceTest,
::testing::Values(GameType::tes4,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4,
GameType::tes5se,
GameType::fo4vr,
GameType::tes5vr,
GameType::tes3,
GameType::starfield,
GameType::openmw));
::testing::ValuesIn(ALL_GAME_TYPES));
TEST_P(GameInterfaceTest, setAdditionalDataPathsShouldDoThat) {
const auto paths = std::vector<std::filesystem::path>{
@@ -95,6 +87,56 @@ TEST_P(GameInterfaceTest, setAdditionalDataPathsShouldDoThat) {
EXPECT_EQ(paths, handle_->GetAdditionalDataPaths());
}
TEST_P(GameInterfaceTest, setAdditionalDataPathsShouldClearTheConditionCache) {
PluginMetadata metadata(blankEsm);
metadata.SetLoadAfterFiles({File("plugin.esp", "", "file(\"plugin.esp\")")});
handle_->GetDatabase().SetPluginUserMetadata(metadata);
auto evaluatedMetadata =
handle_->GetDatabase().GetPluginUserMetadata(blankEsm, true);
EXPECT_FALSE(evaluatedMetadata.has_value());
const auto dataFilePath = gamePath.parent_path() / "Data" / "plugin.esp";
touch(dataFilePath);
handle_->SetAdditionalDataPaths({dataFilePath.parent_path()});
evaluatedMetadata =
handle_->GetDatabase().GetPluginUserMetadata(blankEsm, true);
EXPECT_FALSE(evaluatedMetadata.value().GetLoadAfterFiles().empty());
}
TEST_P(GameInterfaceTest,
setAdditionalDataPathsShouldUpdateWhereLoadOrderPluginsAreFound) {
// Set no additional data paths to avoid picking up non-test plugins on PCs
// which have Starfield or Fallout 4 installed.
handle_->SetAdditionalDataPaths({});
handle_->LoadCurrentLoadOrderState();
auto loadOrder = handle_->GetLoadOrder();
const auto filename = "plugin.esp";
const auto dataFilePath = gamePath.parent_path() / "Data" / filename;
std::filesystem::create_directories(dataFilePath.parent_path());
std::filesystem::copy_file(getSourcePluginsPath() / blankEsp, dataFilePath);
ASSERT_TRUE(std::filesystem::exists(dataFilePath));
if (GetParam() == GameType::starfield) {
std::filesystem::copy_file(getSourcePluginsPath() / blankEsp,
dataPath / filename);
ASSERT_TRUE(std::filesystem::exists(dataPath / filename));
}
std::filesystem::last_write_time(
dataFilePath,
std::filesystem::file_time_type::clock().now() + std::chrono::hours(1));
handle_->SetAdditionalDataPaths({dataFilePath.parent_path()});
handle_->LoadCurrentLoadOrderState();
loadOrder.push_back(filename);
EXPECT_EQ(loadOrder, handle_->GetLoadOrder());
}
TEST_P(GameInterfaceTest, isValidPluginShouldReturnTrueForAValidPlugin) {
EXPECT_TRUE(handle_->IsValidPlugin(blankEsm));
}
@@ -116,9 +158,37 @@ TEST_P(GameInterfaceTest, isValidPluginShouldReturnFalseForAnEmptyFile) {
EXPECT_FALSE(handle_->IsValidPlugin(emptyFile));
}
TEST_P(GameInterfaceTest,
isValidPluginShouldResolveRelativePathsRelativeToDataPath) {
const auto path = ".." / dataPath.filename() / blankEsm;
EXPECT_TRUE(handle_->IsValidPlugin(path));
}
TEST_P(GameInterfaceTest, isValidPluginShouldUseAbsolutePathsAsGiven) {
ASSERT_TRUE(dataPath.is_absolute());
const auto path = dataPath / std::filesystem::u8path(blankEsm);
EXPECT_TRUE(handle_->IsValidPlugin(path));
}
TEST_P(
GameInterfaceTest,
loadPluginsWithHeadersOnlyTrueShouldLoadTheHeadersOfAllGivenPlugins) {
isValidPluginShouldTryGhostedPathIfGivenPluginDoesNotExistExceptForOpenMW) {
if (GetParam() == GameType::openmw) {
// This wasn't done for OpenMW during common setup.
const auto pluginPath = dataPath / (blankMasterDependentEsm + ".ghost");
std::filesystem::rename(dataPath / blankMasterDependentEsm, pluginPath);
EXPECT_FALSE(handle_->IsValidPlugin(blankMasterDependentEsm));
} else {
EXPECT_TRUE(handle_->IsValidPlugin(blankMasterDependentEsm));
}
}
TEST_P(GameInterfaceTest,
loadPluginsWithHeadersOnlyTrueShouldLoadTheHeadersOfAllGivenPlugins) {
handle_->LoadPlugins(pluginsToLoad, true);
if (GetParam() == GameType::starfield) {
EXPECT_EQ(6, handle_->GetLoadedPlugins().size());
@@ -154,9 +224,29 @@ TEST_P(GameInterfaceTest, loadPluginsShouldTrimDotGhostFileExtensions) {
EXPECT_EQ(blankMasterDependentEsm, plugin->GetName());
}
TEST_P(GameInterfaceTest,
loadPluginsWithHeadersOnlyTrueShouldLoadTheHeadersOfGivenPlugins) {
handle_->LoadPlugins(pluginsToLoad, true);
if (GetParam() == GameType::starfield) {
EXPECT_EQ(6, handle_->GetLoadedPlugins().size());
} else {
EXPECT_EQ(11, handle_->GetLoadedPlugins().size());
}
// Check that one plugin's header has been read.
ASSERT_NO_THROW(handle_->GetPlugin(masterFile));
auto plugin = handle_->GetPlugin(masterFile);
EXPECT_EQ("5.0", plugin->GetVersion().value());
// Check that only the header has been read.
EXPECT_FALSE(plugin->GetCRC());
}
TEST_P(GameInterfaceTest,
loadPluginsWithHeadersOnlyFalseShouldFullyLoadAllInstalledPlugins) {
handle_->LoadPlugins(pluginsToLoad, false);
if (GetParam() == GameType::starfield) {
EXPECT_EQ(6, handle_->GetLoadedPlugins().size());
} else {
@@ -184,6 +274,211 @@ TEST_P(GameInterfaceTest, loadPluginsWithANonAsciiPluginShouldLoadIt) {
EXPECT_EQ(blankEsmCrc, plugin->GetCRC().value());
}
TEST_P(
GameInterfaceTest,
loadPluginsShouldNotThrowIfAFilenameHasNonWindows1252EncodableCharacters) {
const auto pluginName = std::filesystem::u8path(
u8"\u2551\u00BB\u00C1\u2510\u2557\u00FE\u00C3\u00CE.esp");
std::filesystem::copy(dataPath / blankEsp, dataPath / pluginName);
EXPECT_NO_THROW(handle_->LoadPlugins({pluginName}, false));
}
TEST_P(GameInterfaceTest,
loadPluginsWithANonPluginShouldNotAddItToTheLoadedPlugins) {
ASSERT_THROW(handle_->LoadPlugins({nonPluginFile}, false),
std::invalid_argument);
ASSERT_TRUE(handle_->GetLoadedPlugins().empty());
}
TEST_P(GameInterfaceTest,
loadPluginsWithAnInvalidPluginShouldNotAddItToTheLoadedPlugins) {
ASSERT_FALSE(std::filesystem::exists(dataPath / invalidPlugin));
ASSERT_NO_THROW(std::filesystem::copy_file(dataPath / blankEsm,
dataPath / invalidPlugin));
ASSERT_TRUE(std::filesystem::exists(dataPath / invalidPlugin));
std::ofstream out(dataPath / invalidPlugin, std::fstream::app);
out << "GRUP0";
out.close();
ASSERT_NO_THROW(handle_->LoadPlugins({invalidPlugin}, false));
ASSERT_TRUE(handle_->GetLoadedPlugins().empty());
}
TEST_P(GameInterfaceTest, loadPluginsShouldNotClearThePluginsCache) {
handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, true);
ASSERT_EQ(1, handle_->GetLoadedPlugins().size());
handle_->LoadPlugins({std::filesystem::u8path(blankEsp)}, true);
EXPECT_EQ(2, handle_->GetLoadedPlugins().size());
}
TEST_P(GameInterfaceTest,
loadPluginsShouldReplaceCacheEntriesForTheGivenPlugins) {
handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, true);
const auto pointer = handle_->GetPlugin(blankEsm);
ASSERT_NE(nullptr, pointer);
handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, false);
const auto newPointer = handle_->GetPlugin(blankEsm);
ASSERT_NE(nullptr, newPointer);
EXPECT_NE(pointer, newPointer);
}
TEST_P(GameInterfaceTest,
loadPluginsShouldThrowIfGivenVectorElementsWithTheSameFilename) {
const auto dataPluginPath = dataPath / std::filesystem::u8path(blankEsm);
const auto sourcePluginPath =
getSourcePluginsPath() / std::filesystem::u8path(blankEsm);
EXPECT_THROW(handle_->LoadPlugins(std::vector<std::filesystem::path>(
{dataPluginPath, sourcePluginPath}),
true),
std::invalid_argument);
}
TEST_P(GameInterfaceTest,
loadPluginsShouldResolveRelativePathsRelativeToDataPath) {
const auto relativePath = ".." / dataPath.filename() / blankEsm;
handle_->LoadPlugins(std::vector<std::filesystem::path>({relativePath}),
true);
EXPECT_NE(nullptr, handle_->GetPlugin(blankEsm));
}
TEST_P(GameInterfaceTest, loadPluginsShouldUseAbsolutePathsAsGiven) {
const auto absolutePath = dataPath / std::filesystem::u8path(blankEsm);
handle_->LoadPlugins(std::vector<std::filesystem::path>({absolutePath}),
true);
EXPECT_NE(nullptr, handle_->GetPlugin(blankEsm));
}
TEST_P(
GameInterfaceTest,
loadPluginsShouldThrowIfFullyLoadingAPluginWithAMissingMasterIfGameIsMorrowindOrStarfield) {
const auto pluginName =
GetParam() == GameType::starfield ? blankFullEsm : blankEsm;
std::filesystem::remove(dataPath / pluginName);
if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
GetParam() == GameType::starfield) {
try {
handle_->LoadPlugins({blankMasterDependentEsm}, false);
FAIL();
} catch (const std::system_error& e) {
EXPECT_EQ(ESP_ERROR_PLUGIN_METADATA_NOT_FOUND, e.code().value());
EXPECT_EQ(esplugin_category(), e.code().category());
}
} else {
handle_->LoadPlugins({blankMasterDependentEsm}, false);
EXPECT_NE(nullptr, handle_->GetPlugin(blankMasterDependentEsm));
}
}
TEST_P(
GameInterfaceTest,
loadPluginsShouldThrowIfAPluginHasAMasterThatIsNotInTheInputAndIsNotAlreadyLoadedAndGameIsMorrowindOrStarfield) {
if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
GetParam() == GameType::starfield) {
try {
handle_->LoadPlugins({blankMasterDependentEsm}, false);
FAIL();
} catch (const std::system_error& e) {
EXPECT_EQ(ESP_ERROR_PLUGIN_METADATA_NOT_FOUND, e.code().value());
EXPECT_EQ(esplugin_category(), e.code().category());
}
} else {
handle_->LoadPlugins({blankMasterDependentEsm}, false);
EXPECT_NE(nullptr, handle_->GetPlugin(blankMasterDependentEsm));
}
}
TEST_P(
GameInterfaceTest,
loadPluginsShouldNotThrowIfAPluginHasAMasterThatIsNotInTheInputButIsAlreadyLoaded) {
const auto pluginName =
GetParam() == GameType::starfield ? blankFullEsm : blankEsm;
handle_->LoadPlugins({pluginName}, true);
handle_->LoadPlugins({blankMasterDependentEsm}, false);
EXPECT_NE(nullptr, handle_->GetPlugin(blankMasterDependentEsm));
}
TEST_P(GameInterfaceTest,
sortPluginsWithNoLoadedPluginsShouldReturnAnEmptyList) {
const auto sorted = handle_->SortPlugins(handle_->GetLoadOrder());
EXPECT_TRUE(sorted.empty());
}
TEST_P(GameInterfaceTest, sortPluginsShouldOnlySortTheGivenPlugins) {
handle_->LoadPlugins(GetInstalledPlugins(), false);
std::vector<std::string> plugins{blankEsp, blankDifferentEsp};
const auto sorted = handle_->SortPlugins(plugins);
EXPECT_EQ(plugins, sorted);
}
TEST_P(GameInterfaceTest,
sortingShouldNotMakeUnnecessaryChangesToAnExistingLoadOrder) {
std::filesystem::remove(dataPath / std::filesystem::u8path(nonAsciiEsm));
handle_->LoadCurrentLoadOrderState();
auto plugins = GetInstalledPlugins();
handle_->LoadPlugins({plugins.front()}, true);
plugins.erase(plugins.begin());
handle_->LoadPlugins(plugins, false);
std::vector<std::string> expectedSortedOrder;
if (GetParam() == GameType::openmw) {
// The existing load order for OpenMW doesn't have plugins loading after
// their masters, because the game doesn't enforce that, and the test
// setup cannot enforce the positions of inactive plugins.
expectedSortedOrder = {
blankDifferentEsm,
blankDifferentMasterDependentEsm,
blankDifferentEsp,
blankDifferentPluginDependentEsp,
blankEsm,
blankMasterDependentEsm,
blankMasterDependentEsp,
blankEsp,
blankPluginDependentEsp,
masterFile,
blankDifferentMasterDependentEsp,
};
} else {
expectedSortedOrder = getLoadOrder();
}
// Check stability by running the sort 100 times.
for (int i = 0; i < 100; i++) {
auto input = handle_->GetLoadOrder();
auto sorted = handle_->SortPlugins(handle_->GetLoadOrder());
ASSERT_EQ(expectedSortedOrder, sorted) << " for sort " << i;
}
}
TEST_P(GameInterfaceTest, sortPluginsShouldThrowIfAGivenPluginIsNotLoaded) {
std::vector<std::string> plugins{blankEsp, blankDifferentEsp};
EXPECT_THROW(handle_->SortPlugins(plugins), std::runtime_error);
}
TEST_P(GameInterfaceTest, clearLoadedPluginsShouldClearThePluginsCache) {
handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, true);
const auto pointer = handle_->GetPlugin(blankEsm);
@@ -255,18 +550,54 @@ TEST_P(GameInterfaceTest, sortPluginsShouldSucceedIfPassedValidArguments) {
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldReturnFalseIfTheGivenPluginIsNotActive) {
isPluginActiveShouldReturnTrueIfTheGivenPluginIsActive) {
handle_->LoadCurrentLoadOrderState();
EXPECT_TRUE(handle_->IsPluginActive(blankEsm));
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldReturnTrueIfTheGivenPluginIsActive) {
isPluginActiveShouldReturnFalseIfTheGivenPluginIsNotActive) {
handle_->LoadCurrentLoadOrderState();
EXPECT_FALSE(handle_->IsPluginActive(blankEsp));
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldActivePluginAsActiveWithHeaderLoaded) {
handle_->LoadCurrentLoadOrderState();
ASSERT_NO_THROW(handle_->LoadPlugins({blankEsm}, true));
EXPECT_TRUE(handle_->IsPluginActive(blankEsm));
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldInactivePluginAsInactiveWithHeaderLoaded) {
handle_->LoadCurrentLoadOrderState();
ASSERT_NO_THROW(handle_->LoadPlugins({blankEsp}, true));
EXPECT_FALSE(handle_->IsPluginActive(blankEsp));
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldActivePluginAsActiveWhenFullyLoaded) {
handle_->LoadCurrentLoadOrderState();
ASSERT_NO_THROW(handle_->LoadPlugins({blankEsm}, false));
EXPECT_TRUE(handle_->IsPluginActive(blankEsm));
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldInactivePluginAsInactiveWhenFullyLoaded) {
handle_->LoadCurrentLoadOrderState();
ASSERT_NO_THROW(handle_->LoadPlugins({blankEsp}, false));
EXPECT_FALSE(handle_->IsPluginActive(blankEsp));
}
TEST_P(GameInterfaceTest, getLoadOrderShouldReturnTheCurrentLoadOrder) {
// Remove the non-ASCII duplicate plugin.
std::filesystem::remove(dataPath / std::filesystem::u8path(nonAsciiEsm));
+10
View File
@@ -25,10 +25,20 @@
#include <gtest/gtest.h>
#include "loot/api.h"
#include "tests/api/interface/metadata/conditional_metadata_test.h"
#include "tests/api/interface/metadata/file_test.h"
#include "tests/api/interface/metadata/group_test.h"
#include "tests/api/interface/metadata/location_test.h"
#include "tests/api/interface/metadata/message_content_test.h"
#include "tests/api/interface/metadata/message_test.h"
#include "tests/api/interface/metadata/plugin_cleaning_data_test.h"
#include "tests/api/interface/metadata/plugin_metadata_test.h"
#include "tests/api/interface/metadata/tag_test.h"
#include "tests/api/interface/create_game_handle_test.h"
#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);
@@ -22,8 +22,8 @@ along with LOOT. If not, see
<https://www.gnu.org/licenses/>.
*/
#ifndef LOOT_TESTS_API_INTERNALS_METADATA_CONDITIONAL_METADATA_TEST
#define LOOT_TESTS_API_INTERNALS_METADATA_CONDITIONAL_METADATA_TEST
#ifndef LOOT_TESTS_API_INTERFACE_METADATA_CONDITIONAL_METADATA_TEST
#define LOOT_TESTS_API_INTERFACE_METADATA_CONDITIONAL_METADATA_TEST
#include "loot/metadata/conditional_metadata.h"
#include "tests/common_game_test_fixture.h"
@@ -41,12 +41,7 @@ protected:
// but we only have the one so no prefix is necessary.
INSTANTIATE_TEST_SUITE_P(,
ConditionalMetadataTest,
::testing::Values(GameType::tes4,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4,
GameType::tes5se));
::testing::ValuesIn(ALL_GAME_TYPES));
TEST_P(ConditionalMetadataTest,
defaultConstructorShouldSetEmptyConditionString) {
@@ -22,15 +22,14 @@ along with LOOT. If not, see
<https://www.gnu.org/licenses/>.
*/
#ifndef LOOT_TESTS_API_INTERNALS_METADATA_FILE_TEST
#define LOOT_TESTS_API_INTERNALS_METADATA_FILE_TEST
#ifndef LOOT_TESTS_API_INTERFACE_METADATA_FILE_TEST
#define LOOT_TESTS_API_INTERFACE_METADATA_FILE_TEST
#include <gtest/gtest.h>
#include "loot/metadata/file.h"
namespace loot {
namespace test {
namespace loot::test {
TEST(File, defaultConstructorShouldInitialiseEmptyStrings) {
File file;
@@ -381,6 +380,5 @@ TEST(File, getDisplayNameShouldReturnDisplayString) {
EXPECT_EQ("display", file.GetDisplayName());
}
}
}
#endif
@@ -22,15 +22,14 @@ along with LOOT. If not, see
<https://www.gnu.org/licenses/>.
*/
#ifndef LOOT_TESTS_API_INTERNALS_METADATA_GROUP_TEST
#define LOOT_TESTS_API_INTERNALS_METADATA_GROUP_TEST
#ifndef LOOT_TESTS_API_INTERFACE_METADATA_GROUP_TEST
#define LOOT_TESTS_API_INTERFACE_METADATA_GROUP_TEST
#include <gtest/gtest.h>
#include "loot/metadata/group.h"
namespace loot {
namespace test {
namespace loot::test {
TEST(Group, defaultConstructorShouldCreateDefaultGroup) {
Group group;
@@ -350,6 +349,5 @@ TEST(
EXPECT_TRUE(group2 >= group1);
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More