Refactor dirty metadata evaluation

Into the PluginDirtyInfo class, to match other conditional
metadata.
This commit is contained in:
Oliver Hamlet
2015-12-05 13:36:38 +00:00
parent 4ba2b095a2
commit a2813f0e4d
4 changed files with 101 additions and 70 deletions
@@ -24,6 +24,9 @@
#include "plugin_dirty_info.h"
#include "../game/game.h"
#include "../helpers/helpers.h"
#include <boost/locale.hpp>
#include <boost/format.hpp>
@@ -86,6 +89,31 @@ namespace loot {
return Message(Message::warn, f.str());
}
bool PluginDirtyInfo::EvalCondition(Game& game, const std::string& pluginName) const {
if (pluginName.empty())
return false;
// First need to get plugin's CRC.
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();
// Otherwise calculate it from the file.
if (crc == 0) {
if (boost::filesystem::exists(game.DataPath() / pluginName)) {
crc = GetCrc32(game.DataPath() / pluginName);
}
else if (boost::filesystem::exists(game.DataPath() / (pluginName + ".ghost"))) {
crc = GetCrc32(game.DataPath() / (pluginName + ".ghost"));
}
}
return _crc == crc;
}
}
namespace YAML {
+4
View File
@@ -32,6 +32,8 @@
#include <yaml-cpp/yaml.h>
namespace loot {
class Game;
class PluginDirtyInfo {
public:
PluginDirtyInfo();
@@ -47,6 +49,8 @@ namespace loot {
std::string CleaningUtility() const;
Message AsMessage() const;
bool EvalCondition(Game& game, const std::string& pluginName) const;
private:
uint32_t _crc;
unsigned int _itm;
+3 -25
View File
@@ -296,33 +296,11 @@ namespace loot {
++it;
}
// Regex plugins shouldn't have dirty info, but just clear in case.
if (IsRegexPlugin())
if (IsRegexPlugin()) // Remove any dirty metadata from a regex plugin.
_dirtyInfo.clear();
if (!_dirtyInfo.empty()) {
//First need to get plugin's CRC, if it is an exact plugin and it does not have its CRC set.
uint32_t crc = game.GetCachedCrc(name);
if (crc == 0) {
if (boost::filesystem::exists(game.DataPath() / name)) {
crc = GetCrc32(game.DataPath() / name);
}
else if (boost::filesystem::exists(game.DataPath() / (name + ".ghost"))) {
crc = GetCrc32(game.DataPath() / (name + ".ghost"));
}
else {
// The plugin isn't installed, discard the dirty info.
_dirtyInfo.clear();
}
// Store the CRC in the cache in case it's not already in there.
if (crc != 0)
game.CacheCrc(name, crc);
}
// Now use the CRC to evaluate the dirty info.
else {
for (auto it = _dirtyInfo.begin(); it != _dirtyInfo.end();) {
if (it->CRC() != crc)
if (!it->EvalCondition(game, name))
_dirtyInfo.erase(it++);
else
++it;
@@ -28,17 +28,17 @@ along with LOOT. If not, see
#include "backend/metadata/plugin_dirty_info.h"
#include "tests/fixtures.h"
using loot::PluginDirtyInfo;
class PluginDirtyInfo : public SkyrimTest {};
TEST(PluginDirtyInfo, ConstructorsAndDataAccess) {
PluginDirtyInfo info;
TEST_F(PluginDirtyInfo, ConstructorsAndDataAccess) {
loot::PluginDirtyInfo info;
EXPECT_EQ(0, info.CRC());
EXPECT_EQ(0, info.ITMs());
EXPECT_EQ(0, info.DeletedRefs());
EXPECT_EQ(0, info.DeletedNavmeshes());
EXPECT_EQ("", info.CleaningUtility());
info = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
EXPECT_EQ(0x12345678, info.CRC());
EXPECT_EQ(2, info.ITMs());
EXPECT_EQ(10, info.DeletedRefs());
@@ -46,100 +46,121 @@ TEST(PluginDirtyInfo, ConstructorsAndDataAccess) {
EXPECT_EQ("cleaner", info.CleaningUtility());
}
TEST(PluginDirtyInfo, MessageOutput) {
TEST_F(PluginDirtyInfo, MessageOutput) {
loot::Message message;
message = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Contains 2 ITM records, 10 deleted references and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str());
message = PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Clean with cleaner.", message.ChooseContent(Language::any).Str());
message = PluginDirtyInfo(0x12345678, 0, 10, 30, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 0, 10, 30, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Contains 10 deleted references and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str());
message = PluginDirtyInfo(0x12345678, 0, 0, 30, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 0, 0, 30, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Contains 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str());
message = PluginDirtyInfo(0x12345678, 0, 10, 0, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 0, 10, 0, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Contains 10 deleted references. Clean with cleaner.", message.ChooseContent(Language::any).Str());
message = PluginDirtyInfo(0x12345678, 2, 0, 30, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 2, 0, 30, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Contains 2 ITM records and 30 deleted navmeshes. Clean with cleaner.", message.ChooseContent(Language::any).Str());
message = PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Contains 2 ITM records. Clean with cleaner.", message.ChooseContent(Language::any).Str());
message = PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner").AsMessage();
message = loot::PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner").AsMessage();
EXPECT_EQ(loot::Message::warn, message.Type());
EXPECT_EQ("Contains 2 ITM records and 10 deleted references. Clean with cleaner.", message.ChooseContent(Language::any).Str());
}
TEST(PluginDirtyInfo, EqualityOperator) {
PluginDirtyInfo info1, info2;
TEST_F(PluginDirtyInfo, EqualityOperator) {
loot::PluginDirtyInfo info1, info2;
EXPECT_TRUE(info1 == info2);
info1 = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner1");
info2 = PluginDirtyInfo(0x12345678, 4, 20, 60, "cleaner2");
info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner1");
info2 = loot::PluginDirtyInfo(0x12345678, 4, 20, 60, "cleaner2");
EXPECT_TRUE(info1 == info2);
info1 = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
info2 = PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner");
info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
info2 = loot::PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner");
EXPECT_FALSE(info1 == info2);
}
TEST(PluginDirtyInfo, LessThanOperator) {
PluginDirtyInfo info1, info2;
TEST_F(PluginDirtyInfo, LessThanOperator) {
loot::PluginDirtyInfo info1, info2;
EXPECT_FALSE(info1 < info2);
EXPECT_FALSE(info2 < info1);
info1 = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner1");
info2 = PluginDirtyInfo(0x12345678, 4, 20, 60, "cleaner2");
info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner1");
info2 = loot::PluginDirtyInfo(0x12345678, 4, 20, 60, "cleaner2");
EXPECT_FALSE(info1 < info2);
EXPECT_FALSE(info2 < info1);
info1 = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
info2 = PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner");
info1 = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
info2 = loot::PluginDirtyInfo(0x87654321, 2, 10, 30, "cleaner");
EXPECT_TRUE(info1 < info2);
EXPECT_FALSE(info2 < info1);
}
TEST(PluginDirtyInfo, YamlEmitter) {
PluginDirtyInfo info;
TEST_F(PluginDirtyInfo, EvalConditionTrue) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
info = PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner");
loot::PluginDirtyInfo dirtyInfo = loot::PluginDirtyInfo(0x24F0E2A1, 2, 10, 30, "cleaner");
EXPECT_TRUE(dirtyInfo.EvalCondition(game, "Blank.esp"));
}
TEST_F(PluginDirtyInfo, EvalConditionFalse) {
loot::Game game(loot::Game::tes5);
game.SetGamePath(dataPath.parent_path());
ASSERT_NO_THROW(game.Init(false, localPath));
loot::PluginDirtyInfo dirtyInfo;
EXPECT_FALSE(dirtyInfo.EvalCondition(game, ""));
dirtyInfo = loot::PluginDirtyInfo(0xDEADBEEF, 2, 10, 30, "cleaner");
EXPECT_FALSE(dirtyInfo.EvalCondition(game, "Blank.esp"));
}
TEST_F(PluginDirtyInfo, YamlEmitter) {
loot::PluginDirtyInfo info;
info = loot::PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner");
YAML::Emitter e1;
e1 << info;
EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'", e1.c_str());
info = PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner");
YAML::Emitter e2;
e2 << info;
EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\nitm: 2", e2.c_str());
info = PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner");
YAML::Emitter e3;
e3 << info;
EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\nitm: 2\nudr: 10", e3.c_str());
info = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
YAML::Emitter e4;
e4 << info;
EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\nitm: 2\nudr: 10\nnav: 30", e4.c_str());
}
TEST(PluginDirtyInfo, YamlEncode) {
TEST_F(PluginDirtyInfo, YamlEncode) {
YAML::Node node;
PluginDirtyInfo info;
loot::PluginDirtyInfo info;
info = PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 0, 0, 0, "cleaner");
node = info;
EXPECT_EQ(0x12345678, node["crc"].as<uint32_t>());
EXPECT_EQ("cleaner", node["util"].as<std::string>());
@@ -147,7 +168,7 @@ TEST(PluginDirtyInfo, YamlEncode) {
EXPECT_FALSE(node["udr"]);
EXPECT_FALSE(node["nav"]);
info = PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 2, 0, 0, "cleaner");
node = info;
EXPECT_EQ(0x12345678, node["crc"].as<uint32_t>());
EXPECT_EQ("cleaner", node["util"].as<std::string>());
@@ -155,7 +176,7 @@ TEST(PluginDirtyInfo, YamlEncode) {
EXPECT_FALSE(node["udr"]);
EXPECT_FALSE(node["nav"]);
info = PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 2, 10, 0, "cleaner");
node = info;
EXPECT_EQ(0x12345678, node["crc"].as<uint32_t>());
EXPECT_EQ("cleaner", node["util"].as<std::string>());
@@ -163,7 +184,7 @@ TEST(PluginDirtyInfo, YamlEncode) {
EXPECT_EQ(10, node["udr"].as<unsigned int>());
EXPECT_FALSE(node["nav"]);
info = PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
info = loot::PluginDirtyInfo(0x12345678, 2, 10, 30, "cleaner");
node = info;
EXPECT_EQ(0x12345678, node["crc"].as<uint32_t>());
EXPECT_EQ("cleaner", node["util"].as<std::string>());
@@ -172,12 +193,12 @@ TEST(PluginDirtyInfo, YamlEncode) {
EXPECT_EQ(30, node["nav"].as<unsigned int>());
}
TEST(PluginDirtyInfo, YamlDecode) {
TEST_F(PluginDirtyInfo, YamlDecode) {
YAML::Node node;
PluginDirtyInfo info;
loot::PluginDirtyInfo info;
node = YAML::Load("{crc: 0x12345678, util: cleaner}");
info = node.as<PluginDirtyInfo>();
info = node.as<loot::PluginDirtyInfo>();
EXPECT_EQ(0x12345678, info.CRC());
EXPECT_EQ(0, info.ITMs());
EXPECT_EQ(0, info.DeletedRefs());
@@ -185,7 +206,7 @@ TEST(PluginDirtyInfo, YamlDecode) {
EXPECT_EQ("cleaner", info.CleaningUtility());
node = YAML::Load("{crc: 0x12345678, util: cleaner, itm: 2}");
info = node.as<PluginDirtyInfo>();
info = node.as<loot::PluginDirtyInfo>();
EXPECT_EQ(0x12345678, info.CRC());
EXPECT_EQ(2, info.ITMs());
EXPECT_EQ(0, info.DeletedRefs());
@@ -193,7 +214,7 @@ TEST(PluginDirtyInfo, YamlDecode) {
EXPECT_EQ("cleaner", info.CleaningUtility());
node = YAML::Load("{crc: 0x12345678, util: cleaner, itm: 2, udr: 10}");
info = node.as<PluginDirtyInfo>();
info = node.as<loot::PluginDirtyInfo>();
EXPECT_EQ(0x12345678, info.CRC());
EXPECT_EQ(2, info.ITMs());
EXPECT_EQ(10, info.DeletedRefs());
@@ -201,7 +222,7 @@ TEST(PluginDirtyInfo, YamlDecode) {
EXPECT_EQ("cleaner", info.CleaningUtility());
node = YAML::Load("{crc: 0x12345678, util: cleaner, itm: 2, udr: 10, nav: 30}");
info = node.as<PluginDirtyInfo>();
info = node.as<loot::PluginDirtyInfo>();
EXPECT_EQ(0x12345678, info.CRC());
EXPECT_EQ(2, info.ITMs());
EXPECT_EQ(10, info.DeletedRefs());
@@ -209,10 +230,10 @@ TEST(PluginDirtyInfo, YamlDecode) {
EXPECT_EQ("cleaner", info.CleaningUtility());
node = YAML::Load("scalar");
EXPECT_ANY_THROW(node.as<PluginDirtyInfo>());
EXPECT_ANY_THROW(node.as<loot::PluginDirtyInfo>());
node = YAML::Load("[0, 1, 2]");
EXPECT_ANY_THROW(node.as<PluginDirtyInfo>());
EXPECT_ANY_THROW(node.as<loot::PluginDirtyInfo>());
}
#endif