mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Add libloot v0.25.3 public API tests
This commit is contained in:
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user