Add libloot v0.25.3 public API tests

This commit is contained in:
Oliver Hamlet
2025-03-25 22:02:15 +00:00
parent 7b0add5e72
commit 6ea0c47f37
9 changed files with 2370 additions and 0 deletions
@@ -0,0 +1,132 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2013-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_API_GAME_OPERATIONS_TEST
#define LOOT_TESTS_API_INTERFACE_API_GAME_OPERATIONS_TEST
#include <fstream>
#include "loot/api.h"
#include "tests/common_game_test_fixture.h"
namespace loot {
namespace test {
class ApiGameOperationsTest : public CommonGameTestFixture,
public testing::WithParamInterface<GameType> {
protected:
ApiGameOperationsTest() :
CommonGameTestFixture(GetParam()),
handle_(nullptr),
masterlistPath(localPath / "masterlist.yaml"),
noteMessage(
"Do not clean ITM records, they are intentional and required for "
"the mod to function."),
warningMessage(
"Check you are using v2+. If not, Update. v1 has a severe bug with "
"the Mystic Emporium disappearing."),
errorMessage("Obsolete. Remove this and install Enhanced Weather."),
generalMasterlistMessage("A general masterlist message.") {}
void SetUp() override {
CommonGameTestFixture::SetUp();
ASSERT_FALSE(std::filesystem::exists(masterlistPath));
handle_ = CreateGameHandle(GetParam(), gamePath, localPath);
}
void GenerateMasterlist() {
using std::endl;
std::ofstream masterlist(masterlistPath);
masterlist << "bash_tags:" << endl
<< " - Actors.ACBS" << endl
<< " - C.Climate" << endl
<< "globals:" << endl
<< " - type: say" << endl
<< " content: '" << generalMasterlistMessage << "'" << endl
<< " condition: 'file(\"" << missingEsp << "\")'" << endl
<< "groups:" << endl
<< " - name: group1" << endl
<< " - name: group2" << endl
<< " after:" << endl
<< " - group1" << endl
<< "plugins:" << endl
<< " - name: " << blankEsm << endl
<< " after:" << endl
<< " - " << masterFile << endl
<< " msg:" << endl
<< " - type: say" << endl
<< " content: '" << noteMessage << "'" << endl
<< " condition: 'file(\"" << missingEsp << "\")'" << endl
<< " tag:" << endl
<< " - Actors.ACBS" << endl
<< " - Actors.AIData" << endl
<< " - '-C.Water'" << endl
<< " - name: " << blankDifferentEsm << endl
<< " after:" << endl
<< " - " << blankMasterDependentEsm << endl
<< " msg:" << endl
<< " - type: warn" << endl
<< " content: '" << warningMessage << "'" << endl
<< " dirty:" << endl
<< " - crc: 0x7d22f9df" << endl
<< " util: TES4Edit" << endl
<< " udr: 4" << endl
<< " - name: " << blankDifferentEsp << endl
<< " after:" << endl
<< " - " << blankPluginDependentEsp << endl
<< " msg:" << endl
<< " - type: error" << endl
<< " content: '" << errorMessage << "'" << endl
<< " - name: " << blankEsp << endl
<< " after:" << endl
<< " - " << blankDifferentMasterDependentEsp << endl
<< " - name: " << blankDifferentMasterDependentEsp << endl
<< " after:" << endl
<< " - " << blankMasterDependentEsp << endl
<< " msg:" << endl
<< " - type: say" << endl
<< " content: '" << noteMessage << "'" << endl
<< " - type: warn" << endl
<< " content: '" << warningMessage << "'" << endl
<< " - type: error" << endl
<< " content: '" << errorMessage << "'" << endl;
masterlist.close();
}
std::unique_ptr<GameInterface> handle_;
const std::filesystem::path masterlistPath;
const std::string noteMessage;
const std::string warningMessage;
const std::string errorMessage;
const std::string generalMasterlistMessage;
};
}
}
#endif
@@ -0,0 +1,157 @@
/* 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_CREATE_GAME_HANDLE_TEST
#define LOOT_TESTS_API_INTERFACE_CREATE_GAME_HANDLE_TEST
#include <climits>
#include "loot/api.h"
#include "tests/common_game_test_fixture.h"
namespace loot {
namespace test {
class CreateGameHandleTest : public CommonGameTestFixture,
public testing::WithParamInterface<GameType> {
protected:
CreateGameHandleTest() :
CommonGameTestFixture(GetParam()),
handle_(nullptr),
gamePathSymlink(gamePath.string() + ".symlink"),
localPathSymlink(localPath.string() + ".symlink"),
gamePathJunctionLink(gamePath.string() + ".junction"),
localPathJunctionLink(localPath.string() + ".junction"),
originalWorkingDirectory(std::filesystem::current_path()) {}
void SetUp() override {
using std::filesystem::file_type;
using std::filesystem::status;
CommonGameTestFixture::SetUp();
std::filesystem::create_directory_symlink(gamePath, gamePathSymlink);
ASSERT_EQ(file_type::directory, status(gamePathSymlink).type());
std::filesystem::create_directory_symlink(localPath, localPathSymlink);
ASSERT_EQ(file_type::directory, status(localPathSymlink).type());
#ifdef _WIN32
system(("mklink /J \"" +
std::filesystem::absolute(gamePathJunctionLink).string() + "\" \"" +
std::filesystem::absolute(dataPath).parent_path().string() + "\"")
.c_str());
system(("mklink /J \"" +
std::filesystem::absolute(localPathJunctionLink).string() +
"\" \"" + std::filesystem::absolute(localPath).string() + "\"")
.c_str());
#endif
// relative() doesn't work when the current working directory and the given
// path are on separate drives, so ensure that's not the case.
std::filesystem::current_path(gamePath.parent_path());
}
void TearDown() override {
std::filesystem::current_path(originalWorkingDirectory);
}
std::unique_ptr<GameInterface> handle_;
const std::filesystem::path gamePathSymlink;
const std::filesystem::path localPathSymlink;
const std::filesystem::path gamePathJunctionLink;
const std::filesystem::path localPathJunctionLink;
const std::filesystem::path originalWorkingDirectory;
};
// 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(,
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));
TEST_P(CreateGameHandleTest,
shouldSucceedIfPassedValidParametersWithRelativePaths) {
using std::filesystem::relative;
EXPECT_NO_THROW(handle_ = CreateGameHandle(
GetParam(), relative(gamePath), relative(localPath)));
EXPECT_TRUE(handle_);
}
TEST_P(CreateGameHandleTest,
shouldSucceedIfPassedValidParametersWithAbsolutePaths) {
EXPECT_NO_THROW(handle_ = CreateGameHandle(GetParam(), gamePath, localPath));
EXPECT_TRUE(handle_);
}
TEST_P(CreateGameHandleTest, shouldThrowIfPassedAGamePathThatDoesNotExist) {
EXPECT_THROW(CreateGameHandle(GetParam(), missingPath, localPath),
std::invalid_argument);
}
TEST_P(CreateGameHandleTest, shouldSucceedIfPassedALocalPathThatDoesNotExist) {
EXPECT_NO_THROW(handle_ =
CreateGameHandle(GetParam(), gamePath, missingPath));
EXPECT_TRUE(handle_);
}
TEST_P(CreateGameHandleTest, shouldThrowIfPassedALocalPathThatIsNotADirectory) {
EXPECT_THROW(CreateGameHandle(GetParam(), gamePath, dataPath / blankEsm),
std::invalid_argument);
}
#ifdef _WIN32
TEST_P(CreateGameHandleTest, shouldReturnOkIfPassedAnEmptyLocalPathString) {
EXPECT_NO_THROW(handle_ = CreateGameHandle(GetParam(), gamePath, ""));
EXPECT_TRUE(handle_);
}
#endif
TEST_P(CreateGameHandleTest, shouldReturnOkIfPassedGameAndLocalPathSymlinks) {
EXPECT_NO_THROW(handle_ = CreateGameHandle(
GetParam(), gamePathSymlink, localPathSymlink));
EXPECT_TRUE(handle_);
}
#ifdef _WIN32
TEST_P(CreateGameHandleTest,
shouldReturnOkIfPassedGameAndLocalPathJunctionLinks) {
EXPECT_NO_THROW(handle_ = CreateGameHandle(
GetParam(), gamePathJunctionLink, localPathJunctionLink));
EXPECT_TRUE(handle_);
}
#endif
}
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,383 @@
/* 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_GAME_INTERFACE_TEST
#define LOOT_TESTS_API_INTERFACE_GAME_INTERFACE_TEST
#include "loot/api.h"
#include "tests/api/interface/api_game_operations_test.h"
namespace loot {
namespace test {
class GameInterfaceTest : public ApiGameOperationsTest {
protected:
GameInterfaceTest() :
emptyFile("EmptyFile.esm"), nonAsciiEsm(u8"non\u00C1scii.esm") {
// Make sure the plugin with a non-ASCII filename exists.
std::filesystem::copy_file(dataPath / blankEsm,
dataPath / std::filesystem::u8path(nonAsciiEsm));
if (GetParam() == GameType::starfield) {
pluginsToLoad = {
masterFile,
blankEsm,
blankFullEsm,
blankMasterDependentEsm,
blankEsp,
blankMasterDependentEsp,
};
} else {
pluginsToLoad = {
// These are all ASCII filenames.
masterFile,
blankEsm,
blankDifferentEsm,
blankMasterDependentEsm,
blankDifferentMasterDependentEsm,
blankEsp,
blankDifferentEsp,
blankMasterDependentEsp,
blankDifferentMasterDependentEsp,
blankPluginDependentEsp,
blankDifferentPluginDependentEsp,
};
}
}
const std::string emptyFile;
const std::string nonAsciiEsm;
std::vector<std::filesystem::path> pluginsToLoad;
};
// 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(,
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));
TEST_P(GameInterfaceTest, setAdditionalDataPathsShouldDoThat) {
const auto paths = std::vector<std::filesystem::path>{
localPath, localPath.parent_path() / "other"};
handle_->SetAdditionalDataPaths(paths);
EXPECT_EQ(paths, handle_->GetAdditionalDataPaths());
}
TEST_P(GameInterfaceTest, isValidPluginShouldReturnTrueForAValidPlugin) {
EXPECT_TRUE(handle_->IsValidPlugin(blankEsm));
}
TEST_P(GameInterfaceTest,
isValidPluginShouldReturnTrueForAValidNonAsciiPlugin) {
EXPECT_TRUE(handle_->IsValidPlugin(std::filesystem::u8path(nonAsciiEsm)));
}
TEST_P(GameInterfaceTest, isValidPluginShouldReturnFalseForANonPluginFile) {
EXPECT_FALSE(handle_->IsValidPlugin(nonPluginFile));
}
TEST_P(GameInterfaceTest, isValidPluginShouldReturnFalseForAnEmptyFile) {
// Write out an empty file.
touch(dataPath / emptyFile);
ASSERT_TRUE(std::filesystem::exists(dataPath / emptyFile));
EXPECT_FALSE(handle_->IsValidPlugin(emptyFile));
}
TEST_P(
GameInterfaceTest,
loadPluginsWithHeadersOnlyTrueShouldLoadTheHeadersOfAllGivenPlugins) {
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, loadPluginsShouldTrimDotGhostFileExtensions) {
if (GetParam() == GameType::openmw) {
// Ghosting is not supported for OpenMW.
EXPECT_THROW(
handle_->LoadPlugins({blankMasterDependentEsm + ".ghost"}, true),
std::invalid_argument);
return;
} else {
handle_->LoadPlugins({blankMasterDependentEsm + ".ghost"}, true);
}
EXPECT_EQ(1, handle_->GetLoadedPlugins().size());
ASSERT_NO_THROW(handle_->GetPlugin(blankMasterDependentEsm));
const auto plugin = handle_->GetPlugin(blankMasterDependentEsm);
ASSERT_NE(nullptr, plugin);
EXPECT_EQ(blankMasterDependentEsm, plugin->GetName());
}
TEST_P(GameInterfaceTest,
loadPluginsWithHeadersOnlyFalseShouldFullyLoadAllInstalledPlugins) {
handle_->LoadPlugins(pluginsToLoad, false);
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 not only the header has been read.
EXPECT_EQ(blankEsmCrc, plugin->GetCRC().value());
}
TEST_P(GameInterfaceTest, loadPluginsWithANonAsciiPluginShouldLoadIt) {
handle_->LoadPlugins({std::filesystem::u8path(nonAsciiEsm)}, false);
EXPECT_EQ(1, handle_->GetLoadedPlugins().size());
// Check that one plugin's header has been read.
auto plugin = handle_->GetPlugin(nonAsciiEsm);
EXPECT_EQ("5.0", plugin->GetVersion().value());
// Check that not only the header has been read.
EXPECT_EQ(blankEsmCrc, plugin->GetCRC().value());
}
TEST_P(GameInterfaceTest, clearLoadedPluginsShouldClearThePluginsCache) {
handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, true);
const auto pointer = handle_->GetPlugin(blankEsm);
ASSERT_NE(nullptr, pointer);
handle_->ClearLoadedPlugins();
EXPECT_EQ(nullptr, handle_->GetPlugin(blankEsm));
}
TEST_P(GameInterfaceTest, getPluginThatIsNotCachedShouldReturnANullPointer) {
EXPECT_FALSE(handle_->GetPlugin(blankEsm));
}
TEST_P(GameInterfaceTest,
gettingPluginsShouldReturnAnEmptySetIfNoneHaveBeenLoaded) {
EXPECT_TRUE(handle_->GetLoadedPlugins().empty());
}
TEST_P(GameInterfaceTest, sortPluginsShouldSucceedIfPassedValidArguments) {
std::vector<std::string> expectedOrder;
if (GetParam() == GameType::starfield) {
expectedOrder = {
masterFile,
blankEsm,
blankFullEsm,
blankMasterDependentEsm,
blankEsp,
blankMasterDependentEsp,
};
} else {
expectedOrder = {
masterFile,
blankEsm,
blankMasterDependentEsm,
blankDifferentEsm,
blankDifferentMasterDependentEsm,
blankMasterDependentEsp,
blankDifferentMasterDependentEsp,
blankEsp,
blankPluginDependentEsp,
blankDifferentEsp,
blankDifferentPluginDependentEsp,
};
}
if (GetParam() == GameType::fo4 || GetParam() == GameType::tes5se) {
expectedOrder.insert(expectedOrder.begin() + 5, blankEsl);
}
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(handle_->GetDatabase().LoadLists(masterlistPath, ""));
if (GetParam() == GameType::fo4 || GetParam() == GameType::tes5se) {
pluginsToLoad.push_back(blankEsl);
}
handle_->LoadCurrentLoadOrderState();
handle_->LoadPlugins(pluginsToLoad, false);
std::vector<std::string> pluginsToSort;
for (const auto& plugin : pluginsToLoad) {
pluginsToSort.push_back(plugin.filename().u8string());
}
std::vector<std::string> actualOrder = handle_->SortPlugins(pluginsToSort);
EXPECT_EQ(expectedOrder, actualOrder);
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldReturnFalseIfTheGivenPluginIsNotActive) {
handle_->LoadCurrentLoadOrderState();
EXPECT_TRUE(handle_->IsPluginActive(blankEsm));
}
TEST_P(GameInterfaceTest,
isPluginActiveShouldReturnTrueIfTheGivenPluginIsActive) {
handle_->LoadCurrentLoadOrderState();
EXPECT_FALSE(handle_->IsPluginActive(blankEsp));
}
TEST_P(GameInterfaceTest, getLoadOrderShouldReturnTheCurrentLoadOrder) {
// Remove the non-ASCII duplicate plugin.
std::filesystem::remove(dataPath / std::filesystem::u8path(nonAsciiEsm));
// Set no additional data paths to avoid picking up non-test plugins on PCs
// which have Starfield or Fallout 4 installed. Don't clear the additional
// data paths for OpenMW because they come from test config.
if (GetParam() != GameType::openmw) {
handle_->SetAdditionalDataPaths({});
}
handle_->LoadCurrentLoadOrderState();
if (GetParam() == GameType::openmw) {
ASSERT_EQ(std::vector<std::string>({
blankDifferentEsm,
blankDifferentMasterDependentEsm,
blankDifferentEsp,
blankDifferentPluginDependentEsp,
blankMasterDependentEsm,
blankMasterDependentEsp,
blankEsp,
blankPluginDependentEsp,
masterFile,
blankEsm,
blankDifferentMasterDependentEsp,
}),
handle_->GetLoadOrder());
} else {
ASSERT_EQ(getLoadOrder(), handle_->GetLoadOrder());
}
}
TEST_P(GameInterfaceTest, setLoadOrderShouldSetTheLoadOrder) {
// Remove the non-ASCII duplicate plugin.
std::filesystem::remove(dataPath / std::filesystem::u8path(nonAsciiEsm));
// Set no additional data paths to avoid picking up non-test plugins on PCs
// which have Starfield or Fallout 4 installed. Don't clear the additional
// data paths for OpenMW because they come from test config.
if (GetParam() != GameType::openmw) {
handle_->SetAdditionalDataPaths({});
}
handle_->LoadCurrentLoadOrderState();
const auto gameSupportsEsl =
GetParam() == GameType::fo4 || GetParam() == GameType::fo4vr ||
GetParam() == GameType::tes5se || GetParam() == GameType::tes5vr ||
GetParam() == GameType::starfield;
std::vector<std::string> loadOrder;
if (GetParam() == GameType::starfield) {
loadOrder = {
masterFile,
blankEsm,
blankMasterDependentEsm,
blankDifferentEsm,
blankDifferentEsp,
blankEsp,
blankMasterDependentEsp,
};
} else if (GetParam() == GameType::openmw) {
loadOrder = {
blankDifferentMasterDependentEsm,
blankDifferentPluginDependentEsp,
blankDifferentEsm,
blankDifferentEsp,
blankMasterDependentEsm,
blankMasterDependentEsp,
blankPluginDependentEsp,
blankEsp,
masterFile,
blankDifferentMasterDependentEsp,
blankEsm,
};
} else {
loadOrder = {
masterFile,
blankEsm,
blankMasterDependentEsm,
blankDifferentEsm,
blankDifferentMasterDependentEsm,
blankDifferentEsp,
blankDifferentPluginDependentEsp,
blankEsp,
blankMasterDependentEsp,
blankDifferentMasterDependentEsp,
blankPluginDependentEsp,
};
if (gameSupportsEsl) {
loadOrder.insert(loadOrder.begin() + 5, blankEsl);
}
}
EXPECT_NO_THROW(handle_->SetLoadOrder(loadOrder));
EXPECT_EQ(loadOrder, handle_->GetLoadOrder());
// It's not possible to persist the load order of inactive plugins for
// OpenMW.
if (GetParam() != GameType::openmw) {
if (gameSupportsEsl) {
loadOrder.erase(std::begin(loadOrder));
}
EXPECT_EQ(loadOrder, getLoadOrder());
}
}
}
}
#endif
@@ -0,0 +1,61 @@
/* 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_IS_COMPATIBLE_TEST
#define LOOT_TESTS_API_INTERFACE_IS_COMPATIBLE_TEST
#include <gtest/gtest.h>
#include "loot/api.h"
namespace loot {
namespace test {
TEST(IsCompatible,
shouldReturnTrueWithEqualMajorAndMinorVersionsAndUnequalPatchVersion) {
EXPECT_TRUE(IsCompatible(
LIBLOOT_VERSION_MAJOR, LIBLOOT_VERSION_MINOR, LIBLOOT_VERSION_PATCH));
}
TEST(IsCompatible,
shouldReturnFalseWithEqualMajorVersionAndUnequalMinorAndPatchVersions) {
EXPECT_FALSE(IsCompatible(LIBLOOT_VERSION_MAJOR,
LIBLOOT_VERSION_MINOR + 1,
LIBLOOT_VERSION_PATCH + 1));
}
TEST(GetLiblootRevision, shouldReturnANonEmptyString) {
EXPECT_FALSE(GetLiblootRevision().empty());
}
TEST(GetVersion, shouldConcatenateMajorMinorAndPatchVersionNumbersWithPeriods) {
auto expectedVersion = std::to_string(LIBLOOT_VERSION_MAJOR) + "." +
std::to_string(LIBLOOT_VERSION_MINOR) + "." +
std::to_string(LIBLOOT_VERSION_PATCH);
EXPECT_EQ(expectedVersion, GetLiblootVersion());
}
}
}
#endif
+126
View File
@@ -0,0 +1,126 @@
/* 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/>.
*/
#include <gtest/gtest.h>
#include "loot/api.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"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
namespace loot {
namespace test {
void testLoggingCallback(LogLevel, const char *) {
// Do nothing.
}
struct TestLogger {
void callback(LogLevel, const char *message) {
loggedMessages += std::string(message);
}
std::string loggedMessages;
};
TEST(SetLoggingCallback, shouldAcceptAFreeFunction) {
SetLoggingCallback(testLoggingCallback);
try {
CreateGameHandle(GameType::tes4, "dummy");
FAIL();
} catch (...) {
SetLoggingCallback([](LogLevel, const char *) {});
}
}
TEST(SetLoggingCallback, shouldAcceptAMemberFunction) {
TestLogger testLogger;
auto boundCallback = std::bind(&TestLogger::callback,
&testLogger,
std::placeholders::_1,
std::placeholders::_2);
SetLoggingCallback(boundCallback);
try {
CreateGameHandle(GameType::tes4, "dummy");
FAIL();
} catch (...) {
EXPECT_EQ(
"Attempting to create a game handle for game type \"The Elder Scrolls "
"IV: Oblivion\" with game path \"dummy\" and game local path \"\"",
testLogger.loggedMessages);
SetLoggingCallback([](LogLevel, const char *) {});
}
}
TEST(SetLoggingCallback, shouldAcceptALambdaFunction) {
std::string loggedMessages;
auto callback = [&](LogLevel, const char *string) {
loggedMessages += std::string(string);
};
SetLoggingCallback(callback);
try {
CreateGameHandle(GameType::tes4, "dummy");
FAIL();
} catch (...) {
EXPECT_EQ(
"Attempting to create a game handle for game type \"The Elder Scrolls "
"IV: Oblivion\" with game path \"dummy\" and game local path \"\"",
loggedMessages);
SetLoggingCallback([](LogLevel, const char *) {});
}
}
TEST(SetLoggingCallback,
shouldNotBreakLoggingIfPassedLambdaFunctionGoesOutOfScope) {
std::string loggedMessages;
{
SetLoggingCallback([&](LogLevel, const char *string) {
loggedMessages += std::string(string);
});
}
try {
CreateGameHandle(GameType::tes4, "dummy");
FAIL();
} catch (...) {
EXPECT_EQ(
"Attempting to create a game handle for game type \"The Elder Scrolls "
"IV: Oblivion\" with game path \"dummy\" and game local path \"\"",
loggedMessages);
SetLoggingCallback([](LogLevel, const char *) {});
}
}
}
}
File diff suppressed because it is too large Load Diff
+102
View File
@@ -0,0 +1,102 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2013-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_PRINTERS
#define LOOT_TESTS_PRINTERS
#include <gtest/gtest.h>
#include <iostream>
#include "api/metadata/message_content.h"
#include "api/plugin.h"
#include "loot/metadata/file.h"
#include "loot/metadata/location.h"
#include "loot/metadata/message.h"
#include "loot/metadata/plugin_cleaning_data.h"
#include "loot/metadata/plugin_metadata.h"
#include "loot/metadata/tag.h"
namespace loot {
namespace test {
void PrintTo(const File& value, ::std::ostream* os) {
*os << "File(\"" << std::string(value.GetName()) << "\", "
<< "\"" << value.GetDisplayName() << "\", "
<< "\"" << value.GetCondition() << "\""
<< ")";
}
void PrintTo(const Location& value, ::std::ostream* os) {
*os << "Location(\"" << value.GetURL() << "\", "
<< "\"" << value.GetName() << "\", "
<< ")";
}
void PrintTo(const Message& value, ::std::ostream* os) {
std::string type;
if (value.GetType() == MessageType::warn)
type = "warn";
else if (value.GetType() == MessageType::error)
type = "error";
else
type = "say";
*os << "Message(\"" << type << "\", "
<< ::testing::PrintToString(value.GetContent()) << ", "
<< "\"" << value.GetCondition() << "\""
<< ")";
}
void PrintTo(const MessageContent& value, ::std::ostream* os) {
*os << "MessageContent(\"" << value.GetText() << "\", "
<< "\"" << Language(value.GetLanguage()).GetName() << "\""
<< ")";
}
void PrintTo(const PluginCleaningData& value, ::std::ostream* os) {
*os << "PluginCleaningData(0x" << std::hex << std::uppercase << value.GetCRC()
<< std::nouppercase << std::dec << ", " << value.GetITMCount() << ", "
<< value.GetDeletedReferenceCount() << ", "
<< value.GetDeletedNavmeshCount() << ", "
<< "\"" << value.GetCleaningUtility() << "\""
<< ")";
}
void PrintTo(const PluginMetadata& value, ::std::ostream* os) {
*os << "PluginMetadata(\"" << value.GetName() << "\")";
}
void PrintTo(const Tag& value, ::std::ostream* os) {
*os << "Tag(\"" << value.GetName() << "\", " << value.IsAddition() << ", "
<< "\"" << value.GetCondition() << "\""
<< ")";
}
void PrintTo(const Plugin& value, ::std::ostream* os) {
*os << "Plugin(\"" << value.GetName() << "\")";
}
}
}
#endif
+84
View File
@@ -0,0 +1,84 @@
/* 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_TEST_HELPERS
#define LOOT_TESTS_TEST_HELPERS
#include <filesystem>
#include <random>
#include <string>
#include "loot/enum/game_type.h"
namespace loot::test {
bool supportsLightPlugins(GameType gameType) {
return gameType == GameType::tes5se || gameType == GameType::tes5vr ||
gameType == GameType::fo4 || gameType == GameType::fo4vr ||
gameType == GameType::starfield;
}
std::filesystem::path getSourcePluginsPath(GameType gameType) {
using std::filesystem::absolute;
if (gameType == GameType::tes3 || gameType == GameType::openmw) {
return absolute("./testing-plugins/Morrowind/Data Files");
} else if (gameType == GameType::tes4) {
return absolute("./testing-plugins/Oblivion/Data");
} else if (gameType == GameType::starfield) {
return absolute("./testing-plugins/Starfield/Data");
} else if (supportsLightPlugins(gameType)) {
return absolute("./testing-plugins/SkyrimSE/Data");
} else {
return absolute("./testing-plugins/Skyrim/Data");
}
}
std::filesystem::path getSourceArchivesPath(GameType gameType) {
if (gameType == GameType::fo4 || gameType == GameType::fo4vr ||
gameType == GameType::starfield) {
return "./testing-plugins/Fallout 4/Data";
} else {
return getSourcePluginsPath(gameType);
}
}
std::filesystem::path getRootTestPath() {
std::random_device randomDevice;
std::default_random_engine prng(randomDevice());
std::uniform_int_distribution dist(0x61,
0x7A); // values of a-z in ASCII/UTF-8.
// The non-ASCII character is there to ensure test coverage of non-ASCII path
// handling.
std::string directoryName = u8"libloot-t\u00E9st-";
for (int i = 0; i < 16; i += 1) {
directoryName.push_back(static_cast<char>(dist(prng)));
}
return std::filesystem::absolute(std::filesystem::temp_directory_path() /
std::filesystem::u8path(directoryName));
}
}
#endif