mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Fix game plugin loading
The plugin cache wasn't getting cleared before being re-loaded so CRCs and other data would not be updated correctly. Also fixed the GameCache tests not running and rewrote the tests to provide better coverage.
This commit is contained in:
+1
-1
@@ -297,7 +297,7 @@ LOOT_API unsigned int loot_eval_lists(loot_db * const db, const unsigned int lan
|
||||
return c_error(loot_error_invalid_args, "Invalid language code given.");
|
||||
|
||||
// Clear caches before evaluating conditions.
|
||||
db->ClearCache();
|
||||
db->ClearCachedConditions();
|
||||
|
||||
loot::Masterlist temp = db->rawMetadata;
|
||||
loot::MetadataList userTemp = db->rawUserMetadata;
|
||||
|
||||
@@ -154,6 +154,9 @@ namespace loot {
|
||||
++currentGroup;
|
||||
}
|
||||
|
||||
// Clear the existing plugin cache.
|
||||
ClearCachedPlugins();
|
||||
|
||||
// Load the plugins.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Starting plugin loading.";
|
||||
vector<thread> threads;
|
||||
|
||||
@@ -102,12 +102,21 @@ namespace loot {
|
||||
|
||||
void GameCache::AddPlugin(const Plugin&& plugin) {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
plugins.emplace(boost::locale::to_lower(plugin.Name()), plugin);
|
||||
|
||||
auto pair = plugins.emplace(boost::locale::to_lower(plugin.Name()), plugin);
|
||||
if (!pair.second)
|
||||
pair.first->second = plugin;
|
||||
}
|
||||
|
||||
void GameCache::ClearCache() {
|
||||
void GameCache::ClearCachedConditions() {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
conditionCache.clear();
|
||||
}
|
||||
|
||||
void GameCache::ClearCachedPlugins() {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
plugins.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,8 @@ namespace loot {
|
||||
const Plugin& GetPlugin(const std::string& pluginName) const;
|
||||
void AddPlugin(const Plugin&& plugin);
|
||||
|
||||
void ClearCache();
|
||||
void ClearCachedConditions();
|
||||
void ClearCachedPlugins();
|
||||
private:
|
||||
Masterlist masterlist;
|
||||
MetadataList userlist;
|
||||
|
||||
+2
-2
@@ -632,7 +632,7 @@ namespace loot {
|
||||
SendProgressUpdate(frame, loc::translate("Loading plugin headers..."));
|
||||
|
||||
// First clear CRC and condition caches, otherwise they could lead to incorrect evaluations.
|
||||
_lootState.CurrentGame().ClearCache();
|
||||
_lootState.CurrentGame().ClearCachedConditions();
|
||||
|
||||
bool isFirstLoad = _lootState.CurrentGame().GetPlugins().empty();
|
||||
_lootState.CurrentGame().LoadPlugins(true);
|
||||
@@ -735,7 +735,7 @@ namespace loot {
|
||||
pluginNode["isEmpty"] = plugin.IsEmpty();
|
||||
pluginNode["isMaster"] = plugin.isMasterFile();
|
||||
pluginNode["loadsArchive"] = plugin.LoadsArchive();
|
||||
pluginNode["crc"] = IntToHexString(plugin.Crc());
|
||||
pluginNode["crc"] = plugin.Crc();
|
||||
pluginNode["version"] = Version(plugin.getDescription()).AsString();
|
||||
|
||||
if (!mlistPlugin.HasNameOnly()) {
|
||||
|
||||
@@ -22,47 +22,141 @@ along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TEST_BACKEND_GAME
|
||||
#define LOOT_TEST_BACKEND_GAME
|
||||
#ifndef LOOT_TEST_BACKEND_GAME_CACHE
|
||||
#define LOOT_TEST_BACKEND_GAME_CACHE
|
||||
|
||||
#include "backend/game/game_cache.h"
|
||||
|
||||
#include "tests/fixtures.h"
|
||||
|
||||
class GameCache : public SkyrimTest {};
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class GameCache : public SkyrimTest {
|
||||
protected:
|
||||
loot::GameCache cache;
|
||||
};
|
||||
|
||||
TEST_F(GameCache, Constructors) {
|
||||
loot::GameCache cache;
|
||||
std::unordered_set<std::string> plugins({"skyrim.esm"});
|
||||
TEST_F(GameCache, copyConstructorShouldCopyCachedData) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
|
||||
cache.CacheCondition("True Condition", true);
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", true));
|
||||
|
||||
loot::GameCache cache2(cache);
|
||||
EXPECT_EQ(std::make_pair(true, true), cache2.GetCachedCondition("true Condition"));
|
||||
loot::GameCache otherCache(cache);
|
||||
EXPECT_EQ(std::make_pair(true, true), otherCache.GetCachedCondition("true Condition"));
|
||||
EXPECT_EQ("Blank.esm", otherCache.GetPlugin("Blank.esm").Name());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, assignmentOperatorShouldCopyCachedData) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
cache.CacheCondition("True Condition", true);
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", true));
|
||||
|
||||
loot::GameCache otherCache = cache;
|
||||
EXPECT_EQ(std::make_pair(true, true), otherCache.GetCachedCondition("true Condition"));
|
||||
EXPECT_EQ("Blank.esm", otherCache.GetPlugin("Blank.esm").Name());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, gettingATrueConditionShouldReturnATrueTruePair) {
|
||||
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
|
||||
|
||||
EXPECT_EQ(std::make_pair(true, true), cache.GetCachedCondition("true Condition"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, gettingAFalseConditionShouldReturnAFalseTruePair) {
|
||||
EXPECT_NO_THROW(cache.CacheCondition("False Condition", false));
|
||||
|
||||
EXPECT_EQ(std::make_pair(false, true), cache.GetCachedCondition("false Condition"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, gettingANonCachedConditionShouldReturnAFalseFalsePair) {
|
||||
EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("true missing Condition"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, addingAPluginThatDoesNotExistShouldSucceed) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", true));
|
||||
EXPECT_EQ("Blank.esm", cache.GetPlugin("Blank.esm").Name());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, addingAPluginThatIsAlreadyCachedShouldOverwriteExistingEntry) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", true));
|
||||
EXPECT_EQ(0, cache.GetPlugin("Blank.esm").Crc());
|
||||
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", false));
|
||||
EXPECT_EQ(0x187BE342, cache.GetPlugin("Blank.esm").Crc());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, gettingAPluginThatIsNotCachedShouldThrow) {
|
||||
EXPECT_ANY_THROW(cache.GetPlugin("Blank.esm"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, gettingAPluginShouldBeCaseInsensitive) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", true));
|
||||
EXPECT_EQ("Blank.esm", cache.GetPlugin("blanK.esm").Name());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, gettingPluginsShouldReturnAnEmptySetIfNoPluginsHaveBeenCached) {
|
||||
EXPECT_TRUE(cache.GetPlugins().empty());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, gettingPluginsShouldReturnASetOfCachedPluginsIfPluginsHaveBeenCached) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", true));
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank - Master Dependent.esp", true));
|
||||
|
||||
EXPECT_EQ(std::set<loot::Plugin>({
|
||||
loot::Plugin(game, "Blank.esm", true),
|
||||
loot::Plugin(game, "Blank - Master Dependent.esp", true),
|
||||
}), cache.GetPlugins());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, clearingCachedConditionsShouldNotThrowIfNoConditionsAreCached) {
|
||||
EXPECT_NO_THROW(cache.ClearCachedConditions());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, clearingCachedConditionsShouldClearAnyCachedConditions) {
|
||||
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
|
||||
|
||||
EXPECT_NO_THROW(cache.ClearCachedConditions());
|
||||
|
||||
EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("true Condition"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, clearingCachedPluginsShouldNotThrowIfNoPluginsAreCached) {
|
||||
EXPECT_NO_THROW(cache.ClearCachedPlugins());
|
||||
}
|
||||
|
||||
TEST_F(GameCache, clearingCachedPluginsShouldClearAnyCachedPlugins) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
cache.AddPlugin(loot::Plugin(game, "Blank.esm", true));
|
||||
cache.ClearCachedPlugins();
|
||||
|
||||
EXPECT_TRUE(cache.GetPlugins().empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GameCache, AssignmentOperator) {
|
||||
loot::GameCache cache;
|
||||
std::unordered_set<std::string> plugins({"skyrim.esm"});
|
||||
|
||||
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
|
||||
|
||||
loot::GameCache cache2 = cache;
|
||||
EXPECT_EQ(std::make_pair(true, true), cache2.GetCachedCondition("true Condition"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, CacheCondition) {
|
||||
loot::GameCache cache;
|
||||
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
|
||||
EXPECT_NO_THROW(cache.CacheCondition("False Condition", false));
|
||||
|
||||
EXPECT_EQ(std::make_pair(true, true), cache.GetCachedCondition("true Condition"));
|
||||
EXPECT_EQ(std::make_pair(false, true), cache.GetCachedCondition("false Condition"));
|
||||
|
||||
EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("true missing Condition"));
|
||||
EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("false missing Condition"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, ClearCache) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "api/test_api.h"
|
||||
#include "api/test_loot_db.h"
|
||||
#include "backend/game/test_game.h"
|
||||
#include "backend/game/test_game_cache.h"
|
||||
#include "backend/game/test_game_settings.h"
|
||||
#include "backend/game/test_load_order_handler.h"
|
||||
#include "backend/helpers/test_git_helper.h"
|
||||
|
||||
Reference in New Issue
Block a user