mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
Storage: Use StringMap instead of ConcurrentQueue for updates.
Updates are merged or themselves updated as user code changes. This avoids the need for the dispatcher to do this and also avoids the need for disabling updates when the dispatcher isn't running, because there's no risk of memory usage piling up.
This commit is contained in:
@@ -16,24 +16,23 @@ namespace nt {
|
||||
|
||||
class StorageTest : public ::testing::Test {
|
||||
public:
|
||||
StorageTest() {
|
||||
storage.EnableUpdates();
|
||||
}
|
||||
Storage::EntriesMap& entries() { return storage.m_entries; }
|
||||
Storage::UpdateQueue& updates() { return storage.updates(); }
|
||||
void GetUpdates() { storage.GetUpdates(&updates, &delete_all); }
|
||||
std::shared_ptr<StorageEntry> GetEntry(StringRef name) {
|
||||
auto& entry = storage.m_entries[name];
|
||||
if (!entry) entry = std::make_shared<StorageEntry>(name);
|
||||
return entry;
|
||||
}
|
||||
Storage storage;
|
||||
Storage::UpdateMap updates;
|
||||
bool delete_all;
|
||||
};
|
||||
|
||||
class StorageTestPopulateOne : public StorageTest {
|
||||
public:
|
||||
StorageTestPopulateOne() {
|
||||
storage.SetEntryTypeValue("foo", Value::MakeBoolean(true));
|
||||
while (!updates().empty()) updates().pop();
|
||||
GetUpdates();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,7 +43,7 @@ class StorageTestPopulated : public StorageTest {
|
||||
storage.SetEntryTypeValue("foo2", Value::MakeDouble(0.0));
|
||||
storage.SetEntryTypeValue("bar", Value::MakeDouble(1.0));
|
||||
storage.SetEntryTypeValue("bar2", Value::MakeBoolean(false));
|
||||
while (!updates().empty()) updates().pop();
|
||||
GetUpdates();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -87,7 +86,7 @@ class StorageTestPersistent : public StorageTest {
|
||||
Value::MakeStringArray(std::vector<std::string>{"hello", "world\n"}));
|
||||
storage.SetEntryTypeValue(StringRef("\0\3\5\n", 4),
|
||||
Value::MakeBoolean(true));
|
||||
while (!updates().empty()) updates().pop();
|
||||
GetUpdates();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,7 +97,9 @@ class MockLoadWarn {
|
||||
|
||||
TEST_F(StorageTest, Construct) {
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
ASSERT_TRUE(updates.empty());
|
||||
ASSERT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, FindEntryNotExist) {
|
||||
@@ -134,9 +135,9 @@ TEST_F(StorageTest, GetEntryValueNotExist) {
|
||||
TEST_F(StorageTest, GetEntryValueExist) {
|
||||
auto value = Value::MakeBoolean(true);
|
||||
storage.SetEntryTypeValue("foo", value);
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
updates().pop();
|
||||
ASSERT_EQ(value, storage.GetEntryValue("foo"));
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
EXPECT_EQ(updates["foo"].value, storage.GetEntryValue("foo"));
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, SetEntryTypeValueAssignNew) {
|
||||
@@ -145,8 +146,10 @@ TEST_F(StorageTest, SetEntryTypeValueAssignNew) {
|
||||
storage.SetEntryTypeValue("foo", value);
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(value, entry->value());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
EXPECT_FALSE(delete_all);
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kAssign, update.kind);
|
||||
}
|
||||
@@ -157,8 +160,10 @@ TEST_F(StorageTestPopulateOne, SetEntryTypeValueAssignTypeChange) {
|
||||
storage.SetEntryTypeValue("foo", value);
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(value, entry->value());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
EXPECT_FALSE(delete_all);
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kAssign, update.kind);
|
||||
}
|
||||
@@ -170,7 +175,9 @@ TEST_F(StorageTestPopulateOne, SetEntryTypeValueEqualValue) {
|
||||
storage.SetEntryTypeValue("foo", value);
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(value, entry->value());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, SetEntryTypeValueDifferentValue) {
|
||||
@@ -179,8 +186,10 @@ TEST_F(StorageTestPopulateOne, SetEntryTypeValueDifferentValue) {
|
||||
storage.SetEntryTypeValue("foo", value);
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(value, entry->value());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
EXPECT_FALSE(delete_all);
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kValueUpdate, update.kind);
|
||||
}
|
||||
@@ -189,13 +198,17 @@ TEST_F(StorageTest, SetEntryTypeValueEmptyName) {
|
||||
auto value = Value::MakeBoolean(true);
|
||||
storage.SetEntryTypeValue("", value);
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, SetEntryTypeValueEmptyValue) {
|
||||
storage.SetEntryTypeValue("foo", nullptr);
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, SetEntryValueAssignNew) {
|
||||
@@ -204,8 +217,10 @@ TEST_F(StorageTest, SetEntryValueAssignNew) {
|
||||
EXPECT_TRUE(storage.SetEntryValue("foo", value));
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(value, entry->value());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
EXPECT_FALSE(delete_all);
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kAssign, update.kind);
|
||||
}
|
||||
@@ -216,7 +231,9 @@ TEST_F(StorageTestPopulateOne, SetEntryValueAssignTypeChange) {
|
||||
EXPECT_FALSE(storage.SetEntryValue("foo", value));
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_NE(value, entry->value());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, SetEntryValueEqualValue) {
|
||||
@@ -226,7 +243,9 @@ TEST_F(StorageTestPopulateOne, SetEntryValueEqualValue) {
|
||||
EXPECT_TRUE(storage.SetEntryValue("foo", value));
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(value, entry->value());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, SetEntryValueDifferentValue) {
|
||||
@@ -235,8 +254,10 @@ TEST_F(StorageTestPopulateOne, SetEntryValueDifferentValue) {
|
||||
EXPECT_TRUE(storage.SetEntryValue("foo", value));
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(value, entry->value());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
EXPECT_FALSE(delete_all);
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kValueUpdate, update.kind);
|
||||
}
|
||||
@@ -245,20 +266,26 @@ TEST_F(StorageTest, SetEntryValueEmptyName) {
|
||||
auto value = Value::MakeBoolean(true);
|
||||
EXPECT_TRUE(storage.SetEntryValue("", value));
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, SetEntryValueEmptyValue) {
|
||||
EXPECT_TRUE(storage.SetEntryValue("foo", nullptr));
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, SetEntryFlagsNew) {
|
||||
// flags setting doesn't create an entry
|
||||
storage.SetEntryFlags("foo", 0u);
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, SetEntryFlagsEqualValue) {
|
||||
@@ -267,7 +294,9 @@ TEST_F(StorageTestPopulateOne, SetEntryFlagsEqualValue) {
|
||||
storage.SetEntryFlags("foo", 0u);
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(0u, entry->flags());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
EXPECT_FALSE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, SetEntryFlagsDifferentValue) {
|
||||
@@ -275,8 +304,9 @@ TEST_F(StorageTestPopulateOne, SetEntryFlagsDifferentValue) {
|
||||
storage.SetEntryFlags("foo", 1u);
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(1u, entry->flags());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kFlagsUpdate, update.kind);
|
||||
}
|
||||
@@ -284,47 +314,52 @@ TEST_F(StorageTestPopulateOne, SetEntryFlagsDifferentValue) {
|
||||
TEST_F(StorageTest, SetEntryFlagsEmptyName) {
|
||||
storage.SetEntryFlags("", 0u);
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, GetEntryFlagsNotExist) {
|
||||
ASSERT_EQ(0u, storage.GetEntryFlags("foo"));
|
||||
ASSERT_TRUE(entries().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, GetEntryFlagsExist) {
|
||||
storage.SetEntryFlags("foo", 1u);
|
||||
while (!updates().empty()) updates().pop();
|
||||
GetUpdates();
|
||||
ASSERT_EQ(1u, storage.GetEntryFlags("foo"));
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, DeleteEntryNotExist) {
|
||||
storage.DeleteEntry("foo");
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, DeleteEntryExist) {
|
||||
auto entry = GetEntry("foo");
|
||||
storage.DeleteEntry("foo");
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kDelete, update.kind);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, DeleteAllEntriesEmpty) {
|
||||
storage.DeleteAllEntries();
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulated, DeleteAllEntries) {
|
||||
storage.DeleteAllEntries();
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
EXPECT_EQ(nullptr, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kDeleteAll, update.kind);
|
||||
GetUpdates();
|
||||
EXPECT_TRUE(updates.empty());
|
||||
ASSERT_TRUE(delete_all);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulated, GetEntryInfoAll) {
|
||||
@@ -443,7 +478,8 @@ TEST_F(StorageTest, LoadPersistentBadHeader) {
|
||||
EXPECT_CALL(warn, Warn(1, "header line mismatch, ignoring rest of file"));
|
||||
EXPECT_FALSE(storage.LoadPersistent(iss2, warn_func));
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
ASSERT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentCommentHeader) {
|
||||
@@ -455,7 +491,8 @@ TEST_F(StorageTest, LoadPersistentCommentHeader) {
|
||||
"\n; comment\n# comment\n[NetworkTables Storage 3.0]\n");
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
ASSERT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentEmptyName) {
|
||||
@@ -467,7 +504,8 @@ TEST_F(StorageTest, LoadPersistentEmptyName) {
|
||||
"[NetworkTables Storage 3.0]\nboolean \"\"=true\n");
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
ASSERT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentAssign) {
|
||||
@@ -481,10 +519,13 @@ TEST_F(StorageTest, LoadPersistentAssign) {
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(true), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kAssign, update.kind);
|
||||
EXPECT_EQ(entry->value(), update.value);
|
||||
EXPECT_EQ(NT_PERSISTENT, update.flags);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, LoadPersistentUpdateFlags) {
|
||||
@@ -498,10 +539,12 @@ TEST_F(StorageTestPopulateOne, LoadPersistentUpdateFlags) {
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(true), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
ASSERT_EQ(1u, updates.size());
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kFlagsUpdate, update.kind);
|
||||
EXPECT_EQ(NT_PERSISTENT, update.flags);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, LoadPersistentUpdateValue) {
|
||||
@@ -510,7 +553,7 @@ TEST_F(StorageTestPopulateOne, LoadPersistentUpdateValue) {
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
GetEntry("foo")->set_flags(NT_PERSISTENT);
|
||||
while (!updates().empty()) updates().pop();
|
||||
GetUpdates();
|
||||
|
||||
std::istringstream iss(
|
||||
"[NetworkTables Storage 3.0]\nboolean \"foo\"=false\n");
|
||||
@@ -518,10 +561,12 @@ TEST_F(StorageTestPopulateOne, LoadPersistentUpdateValue) {
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(false), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
EXPECT_EQ(1u, updates.size());
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kValueUpdate, update.kind);
|
||||
EXPECT_EQ(entry->value(), update.value);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, LoadPersistentUpdateValueFlags) {
|
||||
@@ -535,13 +580,13 @@ TEST_F(StorageTestPopulateOne, LoadPersistentUpdateValueFlags) {
|
||||
auto entry = GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(false), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(2u, updates().size());
|
||||
auto update = updates().pop();
|
||||
GetUpdates();
|
||||
ASSERT_EQ(1u, updates.size());
|
||||
auto& update = updates["foo"];
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kValueUpdate, update.kind);
|
||||
update = updates().pop();
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kFlagsUpdate, update.kind);
|
||||
EXPECT_EQ(Storage::Update::kValueFlagsUpdate, update.kind);
|
||||
EXPECT_EQ(entry->value(), update.value);
|
||||
EXPECT_EQ(NT_PERSISTENT, update.flags);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistent) {
|
||||
@@ -575,7 +620,8 @@ TEST_F(StorageTest, LoadPersistent) {
|
||||
std::istringstream iss(in);
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
ASSERT_EQ(21u, entries().size());
|
||||
ASSERT_EQ(21u, updates().size());
|
||||
GetUpdates();
|
||||
EXPECT_EQ(21u, updates.size());
|
||||
|
||||
EXPECT_EQ(*Value::MakeBoolean(true), *storage.GetEntryValue("boolean/true"));
|
||||
EXPECT_EQ(*Value::MakeBoolean(false),
|
||||
@@ -629,7 +675,8 @@ TEST_F(StorageTest, LoadPersistentWarn) {
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
GetUpdates();
|
||||
ASSERT_TRUE(updates.empty());
|
||||
}
|
||||
|
||||
} // namespace nt
|
||||
|
||||
Reference in New Issue
Block a user