Merge branch 'refactor-plugin-cache' into dev

This commit is contained in:
Oliver Hamlet
2015-12-08 21:45:13 +00:00
23 changed files with 410 additions and 448 deletions
+2 -2
View File
@@ -33,8 +33,8 @@ LOOT requires the following C/C++ libraries (version numbers used in latest deve
* [Google Test](https://github.com/google/googletest) v1.7: Required to build the tests, but not the API or the GUI.
* [Libespm](http://github.com/WrinklyNinja/libespm) v2.5.0
* [Libgit2](http://libgit2.github.com/) v0.23.4
* [Libloadorder](http://github.com/WrinklyNinja/libloadorder) revision 3a7d694
* [Pseudosem](http://github.com/WrinklyNinja/pseudosem): v1.0.1
* [Libloadorder](http://github.com/WrinklyNinja/libloadorder) v7.0.0
* [Pseudosem](http://github.com/WrinklyNinja/pseudosem) v1.0.1
* [yaml-cpp](http://github.com/WrinklyNinja/yaml-cpp): Use the `patched-for-loot` branch.
In addition, LOOT's UI relies on the web libraries below, which can be fetched by running `bower install` from the repository root.
+2 -2
View File
@@ -25,8 +25,8 @@ make git2
cd ../..
# Build libloadorder
wget https://github.com/WrinklyNinja/libloadorder/archive/3a7d694e2eab9957b745fe828da1ed00f537c989.tar.gz -O - | tar -xz
mv libloadorder-3a7d694e2eab9957b745fe828da1ed00f537c989 libloadorder
wget https://github.com/WrinklyNinja/libloadorder/archive/7.0.0.tar.gz -O - | tar -xz
mv libloadorder-7.0.0 libloadorder
mkdir libloadorder/build && cd libloadorder/build
cmake .. -DPROJECT_ARCH=64 -DPROJECT_STATIC_RUNTIME=OFF -DBUILD_SHARED_LIBS=OFF -DGTEST_ROOT=../gtest-1.7.0
make loadorder64
+15 -16
View File
@@ -363,9 +363,9 @@ LOOT_API unsigned int loot_load_lists(loot_db db, const char * const masterlistP
db->extTagMap = nullptr;
db->extMessageArray = nullptr;
db->masterlist = temp;
db->GetMasterlist() = temp;
db->rawMetadata = temp;
db->userlist = userTemp;
db->GetUserlist() = userTemp;
db->rawUserMetadata = userTemp;
return loot_ok;
@@ -400,15 +400,14 @@ LOOT_API unsigned int loot_eval_lists(loot_db db, const unsigned int language) {
loot::MetadataList userTemp = db->rawUserMetadata;
try {
// Refresh active plugins before evaluating conditions.
db->RefreshActivePluginsList();
temp.EvalAllConditions(*db, language);
userTemp.EvalAllConditions(*db, language);
}
catch (loot::error& e) {
return c_error(e);
}
db->masterlist = temp;
db->userlist = userTemp;
db->GetMasterlist() = temp;
db->GetUserlist() = userTemp;
return loot_ok;
}
@@ -576,12 +575,12 @@ LOOT_API unsigned int loot_get_tag_map(loot_db db, char *** const tagMap, size_t
std::set<std::string> allTags;
for (const auto &plugin : db->masterlist.Plugins()) {
for (const auto &plugin : db->GetMasterlist().Plugins()) {
for (const auto &tag : plugin.Tags()) {
allTags.insert(tag.Name());
}
}
for (const auto &plugin : db->userlist.Plugins()) {
for (const auto &plugin : db->GetUserlist().Plugins()) {
for (const auto &tag : plugin.Tags()) {
allTags.insert(tag.Name());
}
@@ -650,7 +649,7 @@ LOOT_API unsigned int loot_get_plugin_tags(loot_db db, const char * const plugin
*numTags_removed = 0;
std::set<std::string> tagsAdded, tagsRemoved;
loot::PluginMetadata p = db->masterlist.FindPlugin(loot::PluginMetadata(plugin));
loot::PluginMetadata p = db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin));
for (const auto &tag : p.Tags()) {
if (tag.IsAddition())
tagsAdded.insert(tag.Name());
@@ -658,7 +657,7 @@ LOOT_API unsigned int loot_get_plugin_tags(loot_db db, const char * const plugin
tagsRemoved.insert(tag.Name());
}
p = db->userlist.FindPlugin(loot::PluginMetadata(plugin));
p = db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin));
*userlistModified = !p.Tags().empty();
for (const auto &tag : p.Tags()) {
*userlistModified = true;
@@ -731,10 +730,10 @@ LOOT_API unsigned int loot_get_plugin_messages(loot_db db, const char * const pl
*messages = nullptr;
*numMessages = 0;
loot::PluginMetadata p = db->masterlist.FindPlugin(loot::PluginMetadata(plugin));
loot::PluginMetadata p = db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin));
std::list<loot::Message> pluginMessages(p.Messages());
p = db->userlist.FindPlugin(loot::PluginMetadata(plugin));
p = db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin));
std::list<loot::Message> temp(p.Messages());
pluginMessages.insert(pluginMessages.end(), temp.begin(), temp.end());
@@ -767,8 +766,8 @@ LOOT_API unsigned int loot_get_dirty_info(loot_db db, const char * const plugin,
*needsCleaning = loot_needs_cleaning_unknown;
// Is there any dirty info? Testing for applicability happens in loot_eval_lists().
if (!db->masterlist.FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty()
|| !db->userlist.FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty()) {
if (!db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty()
|| !db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty()) {
*needsCleaning = loot_needs_cleaning_yes;
}
@@ -776,9 +775,9 @@ LOOT_API unsigned int loot_get_dirty_info(loot_db db, const char * const plugin,
// This isn't a very reliable system, because if the lists have been evaluated in some language
// other than English, the strings will be in different languages (and the API can't tell what they'd be)
// and the strings may be non-standard and begin with something other than "Do not clean." anyway.
std::list<loot::Message> messages(db->masterlist.FindPlugin(loot::PluginMetadata(plugin)).Messages());
std::list<loot::Message> messages(db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin)).Messages());
std::list<loot::Message> temp(db->userlist.FindPlugin(loot::PluginMetadata(plugin)).Messages());
std::list<loot::Message> temp(db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin)).Messages());
messages.insert(messages.end(), temp.begin(), temp.end());
for (const auto& message : messages) {
@@ -805,7 +804,7 @@ LOOT_API unsigned int loot_write_minimal_list(loot_db db, const char * const out
if (boost::filesystem::exists(outputFile) && !overwrite)
return c_error(loot_error_file_write_fail, "Output file exists but overwrite is not set to true.");
loot::Masterlist temp = db->masterlist;
loot::Masterlist temp = db->GetMasterlist();
std::unordered_set<loot::PluginMetadata> minimalPlugins;
for (const auto &plugin : temp.Plugins()) {
loot::PluginMetadata p(plugin.Name());
+27 -31
View File
@@ -41,7 +41,7 @@ namespace lc = boost::locale;
namespace loot {
Game::Game() : _pluginsFullyLoaded(false) {}
Game::Game(const GameSettings& gameSettings) : GameSettings(gameSettings.Id(), gameSettings.FolderName()), _pluginsFullyLoaded(false) {
Game::Game(const GameSettings& gameSettings) : GameSettings(gameSettings), _pluginsFullyLoaded(false) {
this->SetName(gameSettings.Name())
.SetMaster(gameSettings.Master())
.SetRepoURL(gameSettings.RepoURL())
@@ -77,12 +77,6 @@ namespace loot {
}
LoadOrderHandler::Init(*this, gameLocalAppData);
RefreshActivePluginsList();
}
void Game::RefreshActivePluginsList() {
CacheActivePlugins(GetActivePlugins());
}
void Game::RedatePlugins() {
@@ -124,29 +118,30 @@ namespace loot {
BOOST_LOG_TRIVIAL(trace) << "Scanning for plugins in " << this->DataPath();
for (fs::directory_iterator it(this->DataPath()); it != fs::directory_iterator(); ++it) {
if (fs::is_regular_file(it->status()) && Plugin::IsValid(it->path().filename().string(), *this)) {
Plugin temp(it->path().filename().string());
BOOST_LOG_TRIVIAL(info) << "Found plugin: " << temp.Name();
string name = it->path().filename().string();
BOOST_LOG_TRIVIAL(info) << "Found plugin: " << name;
// Trim .ghost extension if present.
if (boost::iends_with(name, ".ghost"))
name = name.substr(0, name.length() - 6);
uintmax_t fileSize = fs::file_size(it->path());
meanFileSize += fileSize;
//Insert the lowercased name as a key for case-insensitive matching.
string name = boost::locale::to_lower(temp.Name());
plugins.insert(pair<string, Plugin>(name, temp));
sizeMap.insert(pair<uintmax_t, string>(fileSize, name));
sizeMap.emplace(fileSize, name);
}
}
meanFileSize /= sizeMap.size(); //Rounding error, but not important.
// Get the number of threads to use.
// hardware_concurrency() may be zero, if so then use only one thread.
size_t threadsToUse = std::min((size_t)thread::hardware_concurrency(), plugins.size());
size_t threadsToUse = std::min((size_t)thread::hardware_concurrency(), sizeMap.size());
threadsToUse = std::max(threadsToUse, (size_t)1);
// Divide the plugins up by thread.
unsigned int pluginsPerThread = ceil((double)plugins.size() / threadsToUse);
vector<vector<unordered_map<string, Plugin>::iterator>> pluginGroups(threadsToUse);
BOOST_LOG_TRIVIAL(info) << "Loading " << plugins.size() << " plugins using " << threadsToUse << " threads, with up to " << pluginsPerThread << " plugins per thread.";
unsigned int pluginsPerThread = ceil((double)sizeMap.size() / threadsToUse);
vector<vector<string>> pluginGroups(threadsToUse);
BOOST_LOG_TRIVIAL(info) << "Loading " << sizeMap.size() << " plugins using " << threadsToUse << " threads, with up to " << pluginsPerThread << " plugins per thread.";
// The plugins should be split between the threads so that the data
// load is as evenly spread as possible.
@@ -155,7 +150,7 @@ namespace loot {
if (currentGroup == threadsToUse)
currentGroup = 0;
BOOST_LOG_TRIVIAL(trace) << "Adding plugin " << plugin.second << " to loading group " << currentGroup;
pluginGroups[currentGroup].push_back(plugins.find(plugin.second));
pluginGroups[currentGroup].push_back(plugin.second);
++currentGroup;
}
@@ -163,19 +158,11 @@ namespace loot {
BOOST_LOG_TRIVIAL(trace) << "Starting plugin loading.";
vector<thread> threads;
while (threads.size() < threadsToUse) {
vector<unordered_map<string, Plugin>::iterator>& pluginGroup = pluginGroups[threads.size()];
threads.push_back(thread([this, &pluginGroup, headersOnly]() {
for (auto it : pluginGroup) {
BOOST_LOG_TRIVIAL(trace) << "Loading " << it->second.Name();
try {
it->second = Plugin(*this, it->second.Name(), headersOnly);
}
catch (exception &e) {
BOOST_LOG_TRIVIAL(error) << it->second.Name() << ": Exception occurred: " << e.what();
Plugin p(it->second.Name());
p.Messages(list<Message>(1, Message(Message::error, lc::translate("An exception occurred while loading this plugin. Details:").str() + " " + e.what())));
it->second = p;
}
vector<string>& pluginGroup = pluginGroups[threads.size()];
threads.push_back(thread([&]() {
for (auto pluginName : pluginGroup) {
BOOST_LOG_TRIVIAL(trace) << "Loading " << pluginName;
AddPlugin(Plugin(*this, pluginName, headersOnly));
}
}));
}
@@ -193,6 +180,15 @@ namespace loot {
return _pluginsFullyLoaded;
}
bool Game::IsPluginActive(const std::string& pluginName) const {
try {
return GetPlugin(pluginName).IsActive();
}
catch (...) {
return LoadOrderHandler::IsPluginActive(pluginName);
}
}
std::list<Game> ToGames(const std::list<GameSettings>& settings) {
return list<Game>(settings.begin(), settings.end());
}
+3 -9
View File
@@ -28,12 +28,8 @@
#include "game_cache.h"
#include "game_settings.h"
#include "load_order_handler.h"
#include "../plugin/plugin.h"
#include "../metadata_list.h"
#include "../masterlist.h"
#include <string>
#include <unordered_map>
#include <boost/filesystem.hpp>
@@ -47,16 +43,14 @@ namespace loot {
void Init(bool createFolder, const boost::filesystem::path& gameLocalAppData = "");
void RefreshActivePluginsList();
void RedatePlugins(); //Change timestamps to match load order (Skyrim only).
void LoadPlugins(bool headersOnly); //Loads all installed plugins.
bool ArePluginsFullyLoaded() const; // Checks if the game's plugins have already been loaded.
//Plugin data and metadata lists.
Masterlist masterlist;
MetadataList userlist;
std::unordered_map<std::string, Plugin> plugins; //Map so that plugin data can be edited.
// Check if the plugin is active by using the cached value if
// available, and otherwise asking the load order handler.
bool IsPluginActive(const std::string& pluginName) const;
private:
bool _pluginsFullyLoaded;
};
+38 -31
View File
@@ -40,22 +40,29 @@ namespace lc = boost::locale;
namespace loot {
GameCache::GameCache() {}
GameCache::GameCache(const GameCache& cache)
: conditionCache(cache.conditionCache),
crcCache(cache.crcCache),
activePlugins(cache.activePlugins) {}
GameCache::GameCache(const GameCache& cache) :
masterlist(cache.masterlist),
userlist(cache.userlist),
conditionCache(cache.conditionCache),
plugins(cache.plugins) {}
GameCache& GameCache::operator=(const GameCache& cache) {
conditionCache = cache.conditionCache;
crcCache = cache.crcCache;
activePlugins = cache.activePlugins;
if (&cache != this) {
masterlist = cache.masterlist;
userlist = cache.userlist;
conditionCache = cache.conditionCache;
plugins = cache.plugins;
}
return *this;
}
void GameCache::CacheCrc(const std::string& plugin, uint32_t crc) {
std::lock_guard<std::mutex> guard(mutex);
crcCache.insert(pair<string, uint32_t>(boost::locale::to_lower(plugin), crc));
Masterlist & GameCache::GetMasterlist() {
return masterlist;
}
MetadataList & GameCache::GetUserlist() {
return userlist;
}
void GameCache::CacheCondition(const std::string& condition, bool result) {
@@ -63,22 +70,6 @@ namespace loot {
conditionCache.insert(pair<string, bool>(boost::locale::to_lower(condition), result));
}
void GameCache::CacheActivePlugins(const std::unordered_set<std::string>& plugins) {
std::lock_guard<std::mutex> guard(mutex);
activePlugins = plugins;
}
uint32_t GameCache::GetCachedCrc(const std::string& plugin) const {
std::lock_guard<std::mutex> guard(mutex);
auto it = crcCache.find(boost::locale::to_lower(plugin));
if (it != crcCache.end())
return it->second;
else
return 0;
}
std::pair<bool, bool> GameCache::GetCachedCondition(const std::string& condition) const {
std::lock_guard<std::mutex> guard(mutex);
@@ -90,17 +81,33 @@ namespace loot {
return std::pair<bool, bool>(false, false);
}
bool GameCache::IsPluginActive(const std::string& plugin) const {
std::lock_guard<std::mutex> guard(mutex);
std::set<Plugin> GameCache::GetPlugins() const {
std::set<Plugin> output;
std::transform(begin(plugins),
end(plugins),
inserter<set<Plugin>>(output, begin(output)),
[](const pair<std::string, Plugin>& pluginPair) {
return pluginPair.second;
});
return output;
}
return activePlugins.find(boost::locale::to_lower(plugin)) != activePlugins.end();
const Plugin& GameCache::GetPlugin(const std::string & pluginName) const {
auto it = plugins.find(boost::locale::to_lower(pluginName));
if (it != end(plugins))
return it->second;
throw error(error::invalid_args, "No plugin \"" + pluginName + "\" exists.");
}
void GameCache::AddPlugin(const Plugin&& plugin) {
std::lock_guard<std::mutex> lock(mutex);
plugins.emplace(boost::locale::to_lower(plugin.Name()), plugin);
}
void GameCache::ClearCache() {
std::lock_guard<std::mutex> guard(mutex);
conditionCache.clear();
crcCache.clear();
activePlugins.clear();
}
}
+15 -11
View File
@@ -25,11 +25,14 @@
#ifndef __LOOT_GAME_CRC_CACHE__
#define __LOOT_GAME_CRC_CACHE__
#include <string>
#include "../metadata_list.h"
#include "../masterlist.h"
#include "../plugin/plugin.h"
#include <cstdint>
#include <string>
#include <mutex>
#include <unordered_map>
#include <unordered_set>
namespace loot {
class GameCache {
@@ -39,22 +42,23 @@ namespace loot {
GameCache& operator=(const GameCache& cache);
void CacheCrc(const std::string& plugin, uint32_t crc);
void CacheCondition(const std::string& condition, bool result);
void CacheActivePlugins(const std::unordered_set<std::string>& plugins);
Masterlist& GetMasterlist();
MetadataList& GetUserlist();
// Returns 0 if no cached CRC.
uint32_t GetCachedCrc(const std::string& plugin) const;
// Returns false for second bool if no cached condition.
std::pair<bool, bool> GetCachedCondition(const std::string& condition) const;
bool IsPluginActive(const std::string& plugin) const;
void CacheCondition(const std::string& condition, bool result);
std::set<Plugin> GetPlugins() const;
const Plugin& GetPlugin(const std::string & pluginName) const;
void AddPlugin(const Plugin&& plugin);
void ClearCache();
private:
//Caches for condition results, CRCs and active plugins.
Masterlist masterlist;
MetadataList userlist;
std::unordered_map<std::string, bool> conditionCache;
std::unordered_map<std::string, uint32_t> crcCache;
std::unordered_set<std::string> activePlugins;
std::unordered_map<std::string, Plugin> plugins;
mutable std::mutex mutex;
};
+10 -15
View File
@@ -97,33 +97,28 @@ namespace loot {
}
}
std::unordered_set<std::string> LoadOrderHandler::GetActivePlugins() const {
BOOST_LOG_TRIVIAL(debug) << "Getting active plugins.";
bool LoadOrderHandler::IsPluginActive(const std::string& pluginName) const {
BOOST_LOG_TRIVIAL(debug) << "Checking if plugin \"" << pluginName << "\" is active.";
char ** pluginArr;
size_t pluginArrSize;
unsigned int ret = lo_get_active_plugins(_gh, &pluginArr, &pluginArrSize);
if (ret != LIBLO_OK && ret != LIBLO_WARN_BAD_FILENAME && ret != LIBLO_WARN_INVALID_LIST && ret != LIBLO_WARN_LO_MISMATCH) {
bool result = false;
unsigned int ret = lo_get_plugin_active(_gh, pluginName.c_str(), &result);
if (ret != LIBLO_OK && ret != LIBLO_WARN_BAD_FILENAME) {
const char * e = nullptr;
string err;
lo_get_error_message(&e);
if (e == nullptr) {
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to get the active plugins list. Details could not be fetched.";
err = lc::translate("libloadorder failed to get the active plugins list. Details could not be fetched.").str();
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to check if a plugin is active. Details could not be fetched.";
err = lc::translate("libloadorder failed to check if a plugin is active. Details could not be fetched.").str();
}
else {
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to get the active plugins list. Details: " << e;
err = lc::translate("libloadorder failed to get the active plugins list. Details:").str() + " " + e;
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to check if a plugin is active. Details: " << e;
err = lc::translate("libloadorder failed to check if a plugin is active. Details:").str() + " " + e;
}
lo_cleanup();
throw error(error::liblo_error, err);
}
std::unordered_set<std::string> activePlugins;
for (size_t i = 0; i < pluginArrSize; ++i) {
activePlugins.insert(boost::locale::to_lower(string(pluginArr[i])));
}
return activePlugins;
return result;
}
std::list<std::string> LoadOrderHandler::GetLoadOrder() const {
+2 -1
View File
@@ -43,9 +43,10 @@ namespace loot {
void Init(const GameSettings& game, const boost::filesystem::path& gameLocalAppData = "");
std::unordered_set<std::string> GetActivePlugins() const;
std::list<std::string> GetLoadOrder() const;
bool IsPluginActive(const std::string& pluginName) const;
//These modify game load order, even though const.
void SetLoadOrder(const char * const * const loadOrder, const size_t numPlugins) const; // For API.
void SetLoadOrder(const std::list<std::string>& loadOrder) const;
+17 -11
View File
@@ -287,21 +287,27 @@ namespace loot {
if (_game == nullptr)
return;
uint32_t crc = _game->GetCachedCrc(file);
uint32_t crc = 0;
if (file == "LOOT")
crc = GetCrc32(boost::filesystem::absolute("LOOT.exe"));
else {
// CRC could be for a plugin or a file.
// Get the CRC from the game plugin cache if possible.
try {
crc = _game->GetPlugin(file).Crc();
}
catch (...) {}
if (crc == 0) {
if (file == "LOOT")
crc = GetCrc32(boost::filesystem::absolute("LOOT.exe"));
if (boost::filesystem::exists(_game->DataPath() / file))
crc = GetCrc32(_game->DataPath() / file);
else if ((boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm")) && boost::filesystem::exists(_game->DataPath() / (file + ".ghost")))
crc = GetCrc32(_game->DataPath() / (file + ".ghost"));
if (crc == 0) {
if (boost::filesystem::exists(_game->DataPath() / file))
crc = GetCrc32(_game->DataPath() / file);
else if ((boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm")) && boost::filesystem::exists(_game->DataPath() / (file + ".ghost")))
crc = GetCrc32(_game->DataPath() / (file + ".ghost"));
}
else {
result = false;
return;
}
_game->CacheCrc(file, crc);
}
result = checksum == crc;
@@ -358,7 +364,7 @@ namespace loot {
if (file == "LOOT")
result = false;
else
result = Plugin(file).IsActive(*_game);
result = _game->IsPluginActive(file);
BOOST_LOG_TRIVIAL(trace) << "Active check result: " << result;
}
+4 -3
View File
@@ -98,9 +98,10 @@ namespace loot {
uint32_t crc = 0;
// Get the CRC from the game plugin cache if possible.
auto pluginPairIt = game.plugins.find(boost::locale::to_lower(pluginName));
if (pluginPairIt != game.plugins.end())
crc = pluginPairIt->second.Crc();
try {
crc = game.GetPlugin(pluginName).Crc();
}
catch (...) {}
// Otherwise calculate it from the file.
if (crc == 0) {
+8
View File
@@ -92,6 +92,10 @@ namespace loot {
return pluginList;
}
std::list<Message> MetadataList::Messages() const {
return messages;
}
// Merges multiple matching regex entries if any are found.
PluginMetadata MetadataList::FindPlugin(const PluginMetadata& plugin) const {
PluginMetadata match(plugin.Name());
@@ -132,6 +136,10 @@ namespace loot {
}
}
void MetadataList::AppendMessage(const Message& message) {
messages.push_back(message);
}
void MetadataList::EvalAllConditions(Game& game, const unsigned int language) {
unordered_set<PluginMetadata> replacementSet;
for (auto &plugin : plugins) {
+4 -1
View File
@@ -53,6 +53,7 @@ namespace loot {
void clear();
std::list<PluginMetadata> Plugins() const;
std::list<Message> Messages() const;
// Merges multiple matching regex entries if any are found.
PluginMetadata FindPlugin(const PluginMetadata& plugin) const;
@@ -62,13 +63,15 @@ namespace loot {
// be required for other plugins.
void ErasePlugin(const PluginMetadata& plugin);
void AppendMessage(const Message& message);
// Eval plugin conditions.
void EvalAllConditions(Game& game, const unsigned int language);
std::list<Message> messages;
protected:
std::unordered_set<PluginMetadata> plugins;
std::list<PluginMetadata> regexPlugins;
std::list<Message> messages;
};
}
+14 -19
View File
@@ -37,19 +37,11 @@ using namespace std;
using libespm::FormId;
namespace loot {
// TODO: Remove the name-only constructor.
Plugin::Plugin(const std::string& n) :
PluginMetadata(n),
libespm::Plugin(libespm::GameId::SKYRIM),
_isEmpty(true),
_loadsBsa(false),
crc(0),
numOverrideRecords(0) {}
Plugin::Plugin(Game& game, const std::string& name, const bool headerOnly) :
Plugin::Plugin(const Game& game, const std::string& name, const bool headerOnly) :
PluginMetadata(name),
libespm::Plugin(game.LibespmId()),
_isEmpty(true),
_isActive(false),
_loadsBsa(false),
crc(0),
numOverrideRecords(0) {
@@ -67,7 +59,6 @@ namespace loot {
if (!headerOnly) {
BOOST_LOG_TRIVIAL(trace) << Name() << ": Caching CRC value.";
crc = GetCrc32(filepath);
game.CacheCrc(Name(), crc);
}
BOOST_LOG_TRIVIAL(trace) << Name() << ": Counting override FormIDs.";
@@ -97,6 +88,8 @@ namespace loot {
}
}
}
// Get whether the plugin is active or not.
_isActive = game.IsPluginActive(Name());
// Get whether the plugin loads a BSA or not.
if (game.Id() == Game::tes5) {
@@ -115,7 +108,7 @@ namespace loot {
}
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Cannot read plugin file \"" << Name() << "\". Details: " << e.what();
BOOST_LOG_TRIVIAL(error) << "Cannot read plugin file \"" << name << "\". Details: " << e.what();
messages.push_back(loot::Message(loot::Message::error, (boost::format(boost::locale::translate("Cannot read \"%1%\". Details: %2%")) % name % e.what()).str()));
}
@@ -124,8 +117,6 @@ namespace loot {
bool Plugin::DoFormIDsOverlap(const Plugin& plugin) const {
//Basically std::set_intersection except with an early exit instead of an append to results.
//BOOST_LOG_TRIVIAL(trace) << "Checking for FormID overlap between \"" << name << "\" and \"" << plugin.Name() << "\".";
set<FormId> formIds(getFormIds());
set<FormId> otherFormIds(plugin.getFormIds());
auto i = begin(formIds);
@@ -193,8 +184,12 @@ namespace loot {
return false;
}
bool Plugin::IsActive(const Game& game) const {
return game.IsPluginActive(Name());
bool Plugin::operator < (const Plugin & rhs) const {
return boost::ilexicographical_compare(Name(), rhs.Name());;
}
bool Plugin::IsActive() const {
return _isActive;
}
uint32_t Plugin::Crc() const {
@@ -203,7 +198,7 @@ namespace loot {
bool Plugin::CheckInstallValidity(const Game& game) {
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to " << Name() << "'s data.";
if (IsActive(game)) {
if (IsActive()) {
auto pluginExists = [](const Game& game, const std::string& file) {
return boost::filesystem::exists(game.DataPath() / file)
|| ((boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm")) && boost::filesystem::exists(game.DataPath() / (file + ".ghost")));
@@ -214,7 +209,7 @@ namespace loot {
BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" requires \"" << master << "\", but it is missing.";
messages.push_back(Message(Message::error, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be installed, but it is missing.")) % master).str()));
}
else if (!Plugin(master).IsActive(game)) {
else if (!game.IsPluginActive(master)) {
BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" requires \"" << master << "\", but it is inactive.";
messages.push_back(Message(Message::error, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be active, but it is inactive.")) % master).str()));
}
@@ -228,7 +223,7 @@ namespace loot {
}
}
for (const auto &inc : Incs()) {
if (pluginExists(game, inc.Name()) && Plugin(inc.Name()).IsActive(game)) {
if (pluginExists(game, inc.Name()) && game.IsPluginActive(inc.Name())) {
BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" is incompatible with \"" << inc.Name() << "\", but both are present.";
messages.push_back(loot::Message(Message::error, (boost::format(boost::locale::translate("This plugin is incompatible with \"%1%\", but both are present.")) % inc.Name()).str()));
}
+5 -3
View File
@@ -41,8 +41,7 @@ namespace loot {
class Plugin : public PluginMetadata, private libespm::Plugin {
public:
Plugin(const std::string& name);
Plugin(Game& game, const std::string& name, const bool headerOnly);
Plugin(const Game& game, const std::string& name, const bool headerOnly);
using libespm::Plugin::getDescription;
using libespm::Plugin::getFormIds;
@@ -54,7 +53,7 @@ namespace loot {
size_t NumOverrideFormIDs() const;
bool LoadsBSA() const;
bool IsActive(const Game& game) const;
bool IsActive() const;
//Load ordering functions.
bool DoFormIDsOverlap(const Plugin& plugin) const;
@@ -63,8 +62,11 @@ namespace loot {
//Validity checks.
bool CheckInstallValidity(const Game& game); //Checks that reqs and masters are all present, and that no incs are present. Returns true if the plugin is dirty.
static bool IsValid(const std::string& filename, const Game& game);
bool operator < (const Plugin& rhs) const;
private:
bool _isEmpty; // Does the plugin contain any records other than the TES4 header?
bool _isActive;
bool _loadsBsa;
std::string version; //Obtained from description field.
uint32_t crc;
+4 -9
View File
@@ -177,21 +177,16 @@ namespace loot {
// Using a set of plugin names followed by finding the matching key
// in the unordered map, as it's probably faster than copying the
// full plugin objects then sorting them.
set<string> pluginNames;
for (const auto &plugin : game.plugins) {
pluginNames.insert(plugin.first);
}
for (const auto &plugin : pluginNames) {
vertex_t v = boost::add_vertex(game.plugins.find(plugin)->second, graph);
for (const auto &plugin : game.GetPlugins()) {
vertex_t v = boost::add_vertex(plugin, graph);
BOOST_LOG_TRIVIAL(trace) << "Merging for plugin \"" << graph[v].Name() << "\"";
//Check if there is a plugin entry in the masterlist. This will also find matching regex entries.
BOOST_LOG_TRIVIAL(trace) << "Merging masterlist data down to plugin list data.";
graph[v].MergeMetadata(game.masterlist.FindPlugin(graph[v]));
graph[v].MergeMetadata(game.GetMasterlist().FindPlugin(graph[v]));
//Check if there is a plugin entry in the userlist. This will also find matching regex entries.
PluginMetadata ulistPlugin = game.userlist.FindPlugin(graph[v]);
PluginMetadata ulistPlugin = game.GetUserlist().FindPlugin(graph[v]);
if (!ulistPlugin.HasNameOnly() && ulistPlugin.Enabled()) {
BOOST_LOG_TRIVIAL(trace) << "Merging userlist data down to plugin list data.";
+64 -63
View File
@@ -354,15 +354,15 @@ namespace loot {
decLength = 2;
}
size_t i = 0;
for (const auto& plugin : plugins) {
if (Plugin(plugin).IsActive(_lootState.CurrentGame())) {
for (const auto& pluginName : plugins) {
if (_lootState.CurrentGame().IsPluginActive(pluginName)) {
ss << setw(decLength) << i << " " << hex << setw(2) << i << dec << " ";
++i;
}
else {
ss << setw(decLength + 4) << " ";
}
ss << plugin << "\r\n";
ss << pluginName << "\r\n";
}
CopyToClipboard(ss.str());
callback->Success("");
@@ -400,7 +400,7 @@ namespace loot {
void Handler::GetConflictingPlugins(const std::string& pluginName, CefRefPtr<CefFrame> frame, CefRefPtr<Callback> callback) {
BOOST_LOG_TRIVIAL(debug) << "Searching for plugins that conflict with " << pluginName;
auto pluginIt = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(pluginName));
auto plugin = _lootState.CurrentGame().GetPlugin(pluginName);
// Checking for FormID overlap will only work if the plugins have been loaded, so check if
// the plugins have been fully loaded, and if not load all plugins.
@@ -411,13 +411,13 @@ namespace loot {
SendProgressUpdate(frame, loc::translate("Checking for conflicting plugins..."));
YAML::Node node;
for (const auto& pluginPair : _lootState.CurrentGame().plugins) {
for (const auto& otherPlugin : _lootState.CurrentGame().GetPlugins()) {
YAML::Node pluginNode;
pluginNode["crc"] = pluginPair.second.Crc();
pluginNode["isEmpty"] = pluginPair.second.IsEmpty();
if (pluginIt != _lootState.CurrentGame().plugins.end() && pluginIt->second.DoFormIDsOverlap(pluginPair.second)) {
BOOST_LOG_TRIVIAL(debug) << "Found conflicting plugin: " << pluginPair.second.Name();
pluginNode["crc"] = otherPlugin.Crc();
pluginNode["isEmpty"] = otherPlugin.IsEmpty();
if (plugin.DoFormIDsOverlap(otherPlugin)) {
BOOST_LOG_TRIVIAL(debug) << "Found conflicting plugin: " << otherPlugin.Name();
pluginNode["conflicts"] = true;
}
else {
@@ -425,13 +425,13 @@ namespace loot {
}
// Plugin loading may have produced an error message, so rederive displayed data.
YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name());
YAML::Node derivedNode = GenerateDerivedMetadata(otherPlugin.Name());
for (const auto &pair : derivedNode) {
const string key = pair.first.as<string>();
pluginNode[key] = pair.second;
}
node[pluginPair.second.Name()] = pluginNode;
node[otherPlugin.Name()] = pluginNode;
}
if (node.size() > 0)
@@ -444,8 +444,8 @@ namespace loot {
BOOST_LOG_TRIVIAL(debug) << "Copying metadata for plugin " << pluginName;
// Get metadata from masterlist and userlist.
PluginMetadata plugin = _lootState.CurrentGame().masterlist.FindPlugin(pluginName);
plugin.MergeMetadata(_lootState.CurrentGame().userlist.FindPlugin(pluginName));
PluginMetadata plugin = _lootState.CurrentGame().GetMasterlist().FindPlugin(pluginName);
plugin.MergeMetadata(_lootState.CurrentGame().GetUserlist().FindPlugin(pluginName));
// Generate text representation.
string text;
@@ -465,10 +465,10 @@ namespace loot {
std::string Handler::ClearPluginMetadata(const std::string& pluginName) {
BOOST_LOG_TRIVIAL(debug) << "Clearing user metadata for plugin " << pluginName;
_lootState.CurrentGame().userlist.ErasePlugin(PluginMetadata(pluginName));
_lootState.CurrentGame().GetUserlist().ErasePlugin(PluginMetadata(pluginName));
// Save userlist edits.
_lootState.CurrentGame().userlist.Save(_lootState.CurrentGame().UserlistPath());
_lootState.CurrentGame().GetUserlist().Save(_lootState.CurrentGame().UserlistPath());
// Now rederive the displayed metadata from the masterlist.
YAML::Node derivedMetadata = GenerateDerivedMetadata(pluginName);
@@ -484,7 +484,7 @@ namespace loot {
PluginMetadata newUserlistEntry(pluginMetadata["name"].as<string>());
// Find existing userlist entry.
PluginMetadata ulistPlugin = _lootState.CurrentGame().userlist.FindPlugin(newUserlistEntry);
PluginMetadata ulistPlugin = _lootState.CurrentGame().GetUserlist().FindPlugin(newUserlistEntry);
// First sort out the priority value. This is only given if it was changed.
BOOST_LOG_TRIVIAL(trace) << "Calculating userlist metadata priority value from Javascript variables.";
@@ -537,28 +537,28 @@ namespace loot {
// For cleanliness, only data that does not duplicate masterlist and plugin data should be retained, so diff that.
BOOST_LOG_TRIVIAL(trace) << "Removing any user metadata that duplicates masterlist metadata.";
auto pluginIt = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(newUserlistEntry.Name()));
if (pluginIt != _lootState.CurrentGame().plugins.end()) {
Plugin tempPlugin(pluginIt->second);
tempPlugin.MergeMetadata(_lootState.CurrentGame().masterlist.FindPlugin(newUserlistEntry));
try {
Plugin tempPlugin(_lootState.CurrentGame().GetPlugin(newUserlistEntry.Name()));
tempPlugin.MergeMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(newUserlistEntry));
newUserlistEntry = newUserlistEntry.NewMetadata(tempPlugin);
}
else
newUserlistEntry = newUserlistEntry.NewMetadata(_lootState.CurrentGame().masterlist.FindPlugin(newUserlistEntry));
catch (...) {
newUserlistEntry = newUserlistEntry.NewMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(newUserlistEntry));
}
// Now erase any existing userlist entry.
if (!ulistPlugin.HasNameOnly()) {
BOOST_LOG_TRIVIAL(trace) << "Erasing the existing userlist entry.";
_lootState.CurrentGame().userlist.ErasePlugin(ulistPlugin);
_lootState.CurrentGame().GetUserlist().ErasePlugin(ulistPlugin);
}
// Add a new userlist entry if necessary.
if (!newUserlistEntry.HasNameOnly()) {
BOOST_LOG_TRIVIAL(trace) << "Adding new metadata to new userlist entry.";
_lootState.CurrentGame().userlist.AddPlugin(newUserlistEntry);
_lootState.CurrentGame().GetUserlist().AddPlugin(newUserlistEntry);
}
// Save edited userlist.
_lootState.CurrentGame().userlist.Save(_lootState.CurrentGame().UserlistPath());
_lootState.CurrentGame().GetUserlist().Save(_lootState.CurrentGame().UserlistPath());
// Now rederive the derived metadata.
BOOST_LOG_TRIVIAL(trace) << "Returning newly derived display metadata.";
@@ -642,20 +642,18 @@ namespace loot {
// First clear CRC and condition caches, otherwise they could lead to incorrect evaluations.
_lootState.CurrentGame().ClearCache();
// Also refresh active plugins list.
_lootState.CurrentGame().RefreshActivePluginsList();
bool isFirstLoad = _lootState.CurrentGame().plugins.empty();
bool isFirstLoad = _lootState.CurrentGame().GetPlugins().empty();
_lootState.CurrentGame().LoadPlugins(true);
//Sort plugins into their load order.
list<loot::Plugin> installed;
list<string> loadOrder = _lootState.CurrentGame().GetLoadOrder();
for (const auto &pluginName : loadOrder) {
const auto pos = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(pluginName));
if (pos != _lootState.CurrentGame().plugins.end())
installed.push_back(pos->second);
try {
const auto plugin = _lootState.CurrentGame().GetPlugin(pluginName);
installed.push_back(plugin);
}
catch (...) {}
}
list<Message> parsingErrors;
@@ -665,7 +663,7 @@ namespace loot {
SendProgressUpdate(frame, loc::translate("Parsing masterlist..."));
BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist.";
try {
_lootState.CurrentGame().masterlist.Load(_lootState.CurrentGame().MasterlistPath());
_lootState.CurrentGame().GetMasterlist().Load(_lootState.CurrentGame().MasterlistPath());
}
catch (exception &e) {
parsingErrors.push_back(Message(Message::error, (boost::format(loc::translate(
@@ -682,7 +680,7 @@ namespace loot {
SendProgressUpdate(frame, loc::translate("Parsing userlist..."));
BOOST_LOG_TRIVIAL(debug) << "Parsing userlist.";
try {
_lootState.CurrentGame().userlist.Load(_lootState.CurrentGame().UserlistPath());
_lootState.CurrentGame().GetUserlist().Load(_lootState.CurrentGame().UserlistPath());
}
catch (exception &e) {
parsingErrors.push_back(Message(Message::error, (boost::format(loc::translate(
@@ -713,7 +711,7 @@ namespace loot {
// Store the masterlist revision and date.
try {
Masterlist::Info info = _lootState.CurrentGame().masterlist.GetInfo(_lootState.CurrentGame().MasterlistPath(), true);
Masterlist::Info info = _lootState.CurrentGame().GetMasterlist().GetInfo(_lootState.CurrentGame().MasterlistPath(), true);
gameNode["masterlist"]["revision"] = info.revision;
gameNode["masterlist"]["date"] = info.date;
}
@@ -733,15 +731,15 @@ namespace loot {
// description as part of it.
BOOST_LOG_TRIVIAL(trace) << "Getting masterlist metadata for: " << plugin.Name();
Plugin mlistPlugin(plugin);
mlistPlugin.MergeMetadata(_lootState.CurrentGame().masterlist.FindPlugin(plugin));
mlistPlugin.MergeMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(plugin));
// Now do the same again for any userlist data.
BOOST_LOG_TRIVIAL(trace) << "Getting userlist metadata for: " << plugin.Name();
PluginMetadata ulistPlugin(_lootState.CurrentGame().userlist.FindPlugin(plugin));
PluginMetadata ulistPlugin(_lootState.CurrentGame().GetUserlist().FindPlugin(plugin));
pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object.
pluginNode["name"] = plugin.Name();
pluginNode["isActive"] = plugin.IsActive(_lootState.CurrentGame());
pluginNode["isActive"] = plugin.IsActive();
pluginNode["isEmpty"] = plugin.IsEmpty();
pluginNode["isMaster"] = plugin.isMasterFile();
pluginNode["loadsBSA"] = plugin.LoadsBSA();
@@ -800,12 +798,14 @@ namespace loot {
//Evaluate any conditions in the global messages.
BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions.";
list<Message> messages = parsingErrors;
auto metadataListMessages = _lootState.CurrentGame().GetMasterlist().Messages();
messages.insert(end(messages),
begin(metadataListMessages),
end(metadataListMessages));
metadataListMessages = _lootState.CurrentGame().GetUserlist().Messages();
messages.insert(messages.end(),
_lootState.CurrentGame().masterlist.messages.begin(),
_lootState.CurrentGame().masterlist.messages.end());
messages.insert(messages.end(),
_lootState.CurrentGame().userlist.messages.begin(),
_lootState.CurrentGame().userlist.messages.end());
begin(metadataListMessages),
end(metadataListMessages));
try {
list<Message>::iterator it = messages.begin();
while (it != messages.end()) {
@@ -851,20 +851,20 @@ namespace loot {
bool wasChanged = true;
try {
SendProgressUpdate(frame, loc::translate("Updating and parsing masterlist..."));
wasChanged = _lootState.CurrentGame().masterlist.Update(_lootState.CurrentGame());
wasChanged = _lootState.CurrentGame().GetMasterlist().Update(_lootState.CurrentGame());
}
catch (loot::error &e) {
if (e.code() == loot::error::ok) {
// There was a parsing error, but roll-back was successful, so the process
// should still complete.
_lootState.CurrentGame().masterlist.messages.push_back(Message(Message::error, e.what()));
_lootState.CurrentGame().GetMasterlist().AppendMessage(Message(Message::error, e.what()));
wasChanged = true;
}
else {
// Error wasn't a parsing error. Need to try parsing masterlist if it exists.
try {
_lootState.CurrentGame().masterlist.Load(_lootState.CurrentGame().MasterlistPath());
_lootState.CurrentGame().GetMasterlist().Load(_lootState.CurrentGame().MasterlistPath());
}
catch (...) {}
}
@@ -879,7 +879,7 @@ namespace loot {
// Store the masterlist revision and date.
try {
Masterlist::Info info = _lootState.CurrentGame().masterlist.GetInfo(_lootState.CurrentGame().MasterlistPath(), true);
Masterlist::Info info = _lootState.CurrentGame().GetMasterlist().GetInfo(_lootState.CurrentGame().MasterlistPath(), true);
gameNode["masterlist"]["revision"] = info.revision;
gameNode["masterlist"]["date"] = info.date;
}
@@ -888,9 +888,9 @@ namespace loot {
gameNode["masterlist"]["date"] = e.what();
}
for (const auto& pluginPair : _lootState.CurrentGame().plugins) {
Plugin mlistPlugin(pluginPair.second);
mlistPlugin.MergeMetadata(_lootState.CurrentGame().masterlist.FindPlugin(pluginPair.second));
for (const auto& plugin : _lootState.CurrentGame().GetPlugins()) {
Plugin mlistPlugin(plugin);
mlistPlugin.MergeMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(plugin));
YAML::Node pluginNode;
if (!mlistPlugin.HasNameOnly()) {
@@ -906,7 +906,7 @@ namespace loot {
// Now merge masterlist and userlist metadata and evaluate,
// putting any resulting metadata into the base of the pluginNode.
YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name());
YAML::Node derivedNode = GenerateDerivedMetadata(plugin.Name());
for (const auto &pair : derivedNode) {
const string key = pair.first.as<string>();
@@ -918,7 +918,7 @@ namespace loot {
//Evaluate any conditions in the global messages.
BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions.";
list<Message> messages = _lootState.CurrentGame().masterlist.messages;
list<Message> messages = _lootState.CurrentGame().GetMasterlist().Messages();
try {
list<Message>::iterator it = messages.begin();
while (it != messages.end()) {
@@ -955,16 +955,16 @@ namespace loot {
BOOST_LOG_TRIVIAL(debug) << "Clearing all user metadata.";
// Record which plugins have userlist entries.
vector<string> userlistPlugins;
for (const auto &plugin : _lootState.CurrentGame().userlist.Plugins()) {
for (const auto &plugin : _lootState.CurrentGame().GetUserlist().Plugins()) {
userlistPlugins.push_back(plugin.Name());
}
BOOST_LOG_TRIVIAL(trace) << "User metadata exists for " << userlistPlugins.size() << " plugins.";
// Clear the user metadata.
_lootState.CurrentGame().userlist.clear();
_lootState.CurrentGame().GetUserlist().clear();
// Save userlist edits.
_lootState.CurrentGame().userlist.Save(_lootState.CurrentGame().UserlistPath());
_lootState.CurrentGame().GetUserlist().Save(_lootState.CurrentGame().UserlistPath());
// Regenerate the derived metadata (priority, messages, tags and dirty state)
// for any plugins with userlist entries.
@@ -1075,15 +1075,16 @@ namespace loot {
YAML::Node Handler::GenerateDerivedMetadata(const std::string& pluginName) {
// Now rederive the displayed metadata from the masterlist and userlist.
auto pluginIt = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(pluginName));
if (pluginIt != _lootState.CurrentGame().plugins.end()) {
PluginMetadata master(_lootState.CurrentGame().masterlist.FindPlugin(pluginIt->second));
PluginMetadata user(_lootState.CurrentGame().userlist.FindPlugin(pluginIt->second));
try {
auto plugin = _lootState.CurrentGame().GetPlugin(pluginName);
PluginMetadata master(_lootState.CurrentGame().GetMasterlist().FindPlugin(plugin));
PluginMetadata user(_lootState.CurrentGame().GetUserlist().FindPlugin(plugin));
return this->GenerateDerivedMetadata(pluginIt->second, master, user);
return this->GenerateDerivedMetadata(plugin, master, user);
}
catch (...) {
return YAML::Node();
}
return YAML::Node();
}
void Handler::CopyToClipboard(const std::string& text) {
+121 -97
View File
@@ -133,33 +133,8 @@ TEST_F(Game, Init) {
ASSERT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName()));
EXPECT_THROW(game.Init(false), loot::error);
EXPECT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName()));
EXPECT_FALSE(game.IsPluginActive("Skyrim.esm"));
EXPECT_FALSE(game.IsPluginActive("skyrim.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp"));
game = loot::Game(loot::Game::tes5).SetGamePath(dataPath.parent_path());
EXPECT_FALSE(game.IsPluginActive("Skyrim.esm"));
EXPECT_FALSE(game.IsPluginActive("skyrim.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp"));
EXPECT_NO_THROW(game.Init(false, localPath));
EXPECT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName()));
EXPECT_TRUE(game.IsPluginActive("Skyrim.esm"));
@@ -200,32 +175,6 @@ TEST_F(Game, Init) {
#endif
}
TEST_F(Game, RefreshActivePluginsList) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
// Throw because the load order handler hasn't been initialised.
EXPECT_THROW(game.RefreshActivePluginsList(), loot::error);
// Calling Init calls RefreshActivePluginsList, so clear it before testing
// separately.
game.Init(false, localPath);
EXPECT_NO_THROW(game.ClearCache());
EXPECT_NO_THROW(game.RefreshActivePluginsList());
EXPECT_TRUE(game.IsPluginActive("Skyrim.esm"));
EXPECT_TRUE(game.IsPluginActive("skyrim.esm"));
EXPECT_TRUE(game.IsPluginActive("Blank.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm"));
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp"));
EXPECT_TRUE(game.IsPluginActive("Blank - Different Master Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp"));
EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp"));
}
TEST_F(Game, RedatePlugins) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
@@ -267,11 +216,11 @@ TEST_F(Game, LoadPlugins) {
game.SetGamePath(dataPath.parent_path());
EXPECT_NO_THROW(game.LoadPlugins(false));
EXPECT_EQ(11, game.plugins.size());
EXPECT_EQ(11, game.GetPlugins().size());
// Check that all the plugins' data have loaded correctly.
ASSERT_NE(game.plugins.end(), game.plugins.find("skyrim.esm"));
loot::Plugin plugin = game.plugins.find("skyrim.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("Skyrim.esm"));
loot::Plugin plugin = game.GetPlugin("Skyrim.esm");
EXPECT_EQ("Skyrim.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -292,8 +241,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0x187BE342, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esm"));
plugin = game.plugins.find("blank.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("blank.esm"));
plugin = game.GetPlugin("blank.esm");
EXPECT_EQ("Blank.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -314,8 +263,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0x187BE342, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esm"));
plugin = game.plugins.find("blank - different.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("Blank - Different.esm"));
plugin = game.GetPlugin("Blank - Different.esm");
EXPECT_EQ("Blank - Different.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -335,8 +284,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0x64B9F757, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esm"));
plugin = game.plugins.find("blank - master dependent.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esm"));
plugin = game.GetPlugin("blank - master dependent.esm");
EXPECT_EQ("Blank - Master Dependent.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -357,8 +306,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0xB2D4119E, plugin.Crc());
EXPECT_EQ(4, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esm"));
plugin = game.plugins.find("blank - different master dependent.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esm"));
plugin = game.GetPlugin("blank - different master dependent.esm");
EXPECT_EQ("Blank - Different Master Dependent.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -378,8 +327,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0xAADF6710, plugin.Crc());
EXPECT_EQ(4, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esp"));
plugin = game.plugins.find("blank.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank.esp"));
plugin = game.GetPlugin("blank.esp");
EXPECT_EQ("Blank.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -396,8 +345,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0x24F0E2A1, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esp"));
plugin = game.plugins.find("blank - different.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different.esp"));
plugin = game.GetPlugin("blank - different.esp");
EXPECT_EQ("Blank - Different.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -413,8 +362,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0xD4C9B7AE, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esp"));
plugin = game.plugins.find("blank - master dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esp"));
plugin = game.GetPlugin("blank - master dependent.esp");
EXPECT_EQ("Blank - Master Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -431,8 +380,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0x832152DC, plugin.Crc());
EXPECT_EQ(2, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esp"));
plugin = game.plugins.find("blank - different master dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esp"));
plugin = game.GetPlugin("blank - different master dependent.esp");
EXPECT_EQ("Blank - Different Master Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -448,8 +397,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0x3AD17683, plugin.Crc());
EXPECT_EQ(2, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - plugin dependent.esp"));
plugin = game.plugins.find("blank - plugin dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - plugin dependent.esp"));
plugin = game.GetPlugin("blank - plugin dependent.esp");
EXPECT_EQ("Blank - Plugin Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -464,8 +413,8 @@ TEST_F(Game, LoadPlugins) {
EXPECT_EQ(0x28EF26DB, plugin.Crc());
EXPECT_EQ(1, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different plugin dependent.esp"));
plugin = game.plugins.find("blank - different plugin dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different plugin dependent.esp"));
plugin = game.GetPlugin("blank - different plugin dependent.esp");
EXPECT_EQ("Blank - Different Plugin Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -485,11 +434,11 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
game.SetGamePath(dataPath.parent_path());
EXPECT_NO_THROW(game.LoadPlugins(true));
EXPECT_EQ(11, game.plugins.size());
EXPECT_EQ(11, game.GetPlugins().size());
// Check that all the plugins' data have loaded correctly.
ASSERT_NE(game.plugins.end(), game.plugins.find("skyrim.esm"));
loot::Plugin plugin = game.plugins.find("skyrim.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("Skyrim.esm"));
loot::Plugin plugin = game.GetPlugin("Skyrim.esm");
EXPECT_EQ("Skyrim.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -499,8 +448,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esm"));
plugin = game.plugins.find("blank.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("blank.esm"));
plugin = game.GetPlugin("blank.esm");
EXPECT_EQ("Blank.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -510,8 +459,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esm"));
plugin = game.plugins.find("blank - different.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("Blank - Different.esm"));
plugin = game.GetPlugin("Blank - Different.esm");
EXPECT_EQ("Blank - Different.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -521,8 +470,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esm"));
plugin = game.plugins.find("blank - master dependent.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esm"));
plugin = game.GetPlugin("blank - master dependent.esm");
EXPECT_EQ("Blank - Master Dependent.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -534,8 +483,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esm"));
plugin = game.plugins.find("blank - different master dependent.esm")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esm"));
plugin = game.GetPlugin("blank - different master dependent.esm");
EXPECT_EQ("Blank - Different Master Dependent.esm", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_TRUE(plugin.isMasterFile());
@@ -547,8 +496,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esp"));
plugin = game.plugins.find("blank.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank.esp"));
plugin = game.GetPlugin("blank.esp");
EXPECT_EQ("Blank.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -558,8 +507,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esp"));
plugin = game.plugins.find("blank - different.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different.esp"));
plugin = game.GetPlugin("blank - different.esp");
EXPECT_EQ("Blank - Different.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -569,8 +518,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esp"));
plugin = game.plugins.find("blank - master dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esp"));
plugin = game.GetPlugin("blank - master dependent.esp");
EXPECT_EQ("Blank - Master Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -582,8 +531,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esp"));
plugin = game.plugins.find("blank - different master dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esp"));
plugin = game.GetPlugin("blank - different master dependent.esp");
EXPECT_EQ("Blank - Different Master Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -595,8 +544,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - plugin dependent.esp"));
plugin = game.plugins.find("blank - plugin dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - plugin dependent.esp"));
plugin = game.GetPlugin("blank - plugin dependent.esp");
EXPECT_EQ("Blank - Plugin Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -608,8 +557,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) {
EXPECT_EQ(0, plugin.Crc());
EXPECT_EQ(0, plugin.NumOverrideFormIDs());
ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different plugin dependent.esp"));
plugin = game.plugins.find("blank - different plugin dependent.esp")->second;
ASSERT_NO_THROW(game.GetPlugin("blank - different plugin dependent.esp"));
plugin = game.GetPlugin("blank - different plugin dependent.esp");
EXPECT_EQ("Blank - Different Plugin Dependent.esp", plugin.Name());
EXPECT_FALSE(plugin.IsEmpty());
EXPECT_FALSE(plugin.isMasterFile());
@@ -631,6 +580,81 @@ TEST_F(Game, ArePluginsFullyLoaded) {
EXPECT_TRUE(game.ArePluginsFullyLoaded());
}
TEST_F(Game, shouldThrowIfCheckingIfPluginThatIsntLoadedIsActiveAndGameHasNotBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
EXPECT_ANY_THROW(game.IsPluginActive("Blank.esm"));
}
TEST_F(Game, shouldShowBlankEsmAsActiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
EXPECT_TRUE(game.IsPluginActive("Blank.esm"));
}
TEST_F(Game, shouldShowBlankEspAsInctiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
}
TEST_F(Game, shouldShowBlankEsmAsInactiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.LoadPlugins(true));
EXPECT_FALSE(game.IsPluginActive("Blank.esm"));
}
TEST_F(Game, shouldShowBlankEspAsActiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.LoadPlugins(true));
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
}
TEST_F(Game, shouldShowBlankEsmAsActiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
ASSERT_NO_THROW(game.LoadPlugins(true));
EXPECT_TRUE(game.IsPluginActive("Blank.esm"));
}
TEST_F(Game, shouldShowBlankEspAsActiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
ASSERT_NO_THROW(game.LoadPlugins(true));
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
}
TEST_F(Game, shouldShowBlankEsmAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
ASSERT_NO_THROW(game.LoadPlugins(false));
EXPECT_TRUE(game.IsPluginActive("Blank.esm"));
}
TEST_F(Game, shouldShowBlankEspAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
ASSERT_NO_THROW(game.LoadPlugins(false));
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
}
TEST(ToGames, EmptySettings) {
EXPECT_EQ(std::list<loot::Game>(), loot::ToGames(std::list<loot::GameSettings>()));
}
-28
View File
@@ -35,35 +35,20 @@ TEST_F(GameCache, Constructors) {
loot::GameCache cache;
std::unordered_set<std::string> plugins({"skyrim.esm"});
EXPECT_NO_THROW(cache.CacheCrc("Blank.esp", 5));
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
EXPECT_NO_THROW(cache.CacheActivePlugins(plugins));
loot::GameCache cache2(cache);
EXPECT_EQ(5, cache2.GetCachedCrc("blank.Esp"));
EXPECT_EQ(std::make_pair(true, true), cache2.GetCachedCondition("true Condition"));
EXPECT_TRUE(cache2.IsPluginActive("Skyrim.esm"));
}
TEST_F(GameCache, AssignmentOperator) {
loot::GameCache cache;
std::unordered_set<std::string> plugins({"skyrim.esm"});
EXPECT_NO_THROW(cache.CacheCrc("Blank.esp", 5));
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
EXPECT_NO_THROW(cache.CacheActivePlugins(plugins));
loot::GameCache cache2 = cache;
EXPECT_EQ(5, cache2.GetCachedCrc("blank.Esp"));
EXPECT_EQ(std::make_pair(true, true), cache2.GetCachedCondition("true Condition"));
EXPECT_TRUE(cache2.IsPluginActive("Skyrim.esm"));
}
TEST_F(GameCache, CacheCrc) {
loot::GameCache cache;
EXPECT_NO_THROW(cache.CacheCrc("Blank.esp", 5));
EXPECT_EQ(5, cache.GetCachedCrc("blank.Esp"));
EXPECT_EQ(0, cache.GetCachedCrc("Blank.missing.esp"));
}
TEST_F(GameCache, CacheCondition) {
@@ -78,19 +63,6 @@ TEST_F(GameCache, CacheCondition) {
EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("false missing Condition"));
}
TEST_F(GameCache, CacheActivePlugins) {
loot::GameCache cache;
std::unordered_set<std::string> plugins({
"skyrim.esm",
"blank.esp"
});
EXPECT_NO_THROW(cache.CacheActivePlugins(plugins));
EXPECT_TRUE(cache.IsPluginActive("Skyrim.esm"));
EXPECT_TRUE(cache.IsPluginActive("Blank.esp"));
EXPECT_FALSE(cache.IsPluginActive("Blank.missing.esp"));
}
TEST_F(GameCache, ClearCache) {}
#endif
@@ -66,19 +66,19 @@ TEST_F(LoadOrderHandler, Init) {
EXPECT_NO_THROW(loh.Init(game, localPath));
}
TEST_F(LoadOrderHandler, GetActivePlugins) {
TEST_F(LoadOrderHandler, IsPluginActive) {
loot::LoadOrderHandler loh;
loot::GameSettings game(loot::GameSettings::tes5);
game.SetGamePath(dataPath.parent_path());
EXPECT_THROW(loh.IsPluginActive("Skyrim.esm"), loot::error);
ASSERT_NO_THROW(loh.Init(game, localPath));
std::unordered_set<std::string> expected({
"skyrim.esm",
"blank.esm",
"blank - different master dependent.esp",
});
EXPECT_EQ(expected, loh.GetActivePlugins());
EXPECT_TRUE(loh.IsPluginActive("Skyrim.esm"));
EXPECT_TRUE(loh.IsPluginActive("Blank.esm"));
EXPECT_TRUE(loh.IsPluginActive("Blank - Different Master Dependent.esp"));
EXPECT_FALSE(loh.IsPluginActive("Blank.esp"));
}
TEST_F(LoadOrderHandler, GetLoadOrder) {

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