mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
StorageTest: Add LoadPersistent and SavePersistent coverage.
This commit is contained in:
@@ -7,7 +7,10 @@
|
||||
|
||||
#include "Storage.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
namespace nt {
|
||||
|
||||
@@ -37,6 +40,55 @@ class StorageTestPopulated : public StorageTest {
|
||||
}
|
||||
};
|
||||
|
||||
class StorageTestPersistent : public StorageTest {
|
||||
public:
|
||||
StorageTestPersistent() {
|
||||
storage.SetEntryTypeValue("boolean/true", Value::MakeBoolean(true));
|
||||
storage.SetEntryTypeValue("boolean/false", Value::MakeBoolean(false));
|
||||
storage.SetEntryTypeValue("double/neg", Value::MakeDouble(-1.5));
|
||||
storage.SetEntryTypeValue("double/zero", Value::MakeDouble(0.0));
|
||||
storage.SetEntryTypeValue("double/big", Value::MakeDouble(1.3e8));
|
||||
storage.SetEntryTypeValue("string/empty", Value::MakeString(StringRef("")));
|
||||
storage.SetEntryTypeValue("string/normal",
|
||||
Value::MakeString(StringRef("hello")));
|
||||
storage.SetEntryTypeValue("string/special",
|
||||
Value::MakeString(StringRef("\0\3\5\n", 4)));
|
||||
storage.SetEntryTypeValue("raw/empty", Value::MakeRaw(StringRef("")));
|
||||
storage.SetEntryTypeValue("raw/normal", Value::MakeRaw(StringRef("hello")));
|
||||
storage.SetEntryTypeValue("raw/special",
|
||||
Value::MakeRaw(StringRef("\0\3\5\n", 4)));
|
||||
storage.SetEntryTypeValue("booleanarr/empty",
|
||||
Value::MakeBooleanArray(std::vector<int>{}));
|
||||
storage.SetEntryTypeValue("booleanarr/one",
|
||||
Value::MakeBooleanArray(std::vector<int>{1}));
|
||||
storage.SetEntryTypeValue("booleanarr/two",
|
||||
Value::MakeBooleanArray(std::vector<int>{1, 0}));
|
||||
storage.SetEntryTypeValue("doublearr/empty",
|
||||
Value::MakeDoubleArray(std::vector<double>{}));
|
||||
storage.SetEntryTypeValue("doublearr/one",
|
||||
Value::MakeDoubleArray(std::vector<double>{0.5}));
|
||||
storage.SetEntryTypeValue(
|
||||
"doublearr/two",
|
||||
Value::MakeDoubleArray(std::vector<double>{0.5, -0.25}));
|
||||
storage.SetEntryTypeValue(
|
||||
"stringarr/empty", Value::MakeStringArray(std::vector<std::string>{}));
|
||||
storage.SetEntryTypeValue(
|
||||
"stringarr/one",
|
||||
Value::MakeStringArray(std::vector<std::string>{"hello"}));
|
||||
storage.SetEntryTypeValue(
|
||||
"stringarr/two",
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
class MockLoadWarn {
|
||||
public:
|
||||
MOCK_METHOD2(Warn, void(std::size_t line, const char* msg));
|
||||
};
|
||||
|
||||
TEST_F(StorageTest, Construct) {
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
@@ -309,4 +361,268 @@ TEST_F(StorageTestPopulated, GetEntryInfoPrefixTypes) {
|
||||
EXPECT_EQ(NT_BOOLEAN, info[0].type);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPersistent, SavePersistentEmpty) {
|
||||
std::ostringstream oss;
|
||||
storage.SavePersistent(oss);
|
||||
ASSERT_EQ("[NetworkTables Storage 3.0]\n", oss.str());
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPersistent, SavePersistent) {
|
||||
for (auto& i : entries()) i.getValue()->set_flags(NT_PERSISTENT);
|
||||
std::ostringstream oss;
|
||||
storage.SavePersistent(oss);
|
||||
std::string out = oss.str();
|
||||
//fputs(out.c_str(), stderr);
|
||||
llvm::StringRef line, rem = out;
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("[NetworkTables Storage 3.0]", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("boolean \"\\x00\\x03\\x05\\n\"=true", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("boolean \"boolean/false\"=false", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("boolean \"boolean/true\"=true", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array boolean \"booleanarr/empty\"=", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array boolean \"booleanarr/one\"=true", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array boolean \"booleanarr/two\"=true,false", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("double \"double/big\"=1.3e+08", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("double \"double/neg\"=-1.5", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("double \"double/zero\"=0", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array double \"doublearr/empty\"=", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array double \"doublearr/one\"=0.5", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array double \"doublearr/two\"=0.5,-0.25", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("raw \"raw/empty\"=", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("raw \"raw/normal\"=aGVsbG8=", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("raw \"raw/special\"=AAMFCg==", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("string \"string/empty\"=\"\"", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("string \"string/normal\"=\"hello\"", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("string \"string/special\"=\"\\x00\\x03\\x05\\n\"", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array string \"stringarr/empty\"=", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array string \"stringarr/one\"=\"hello\"", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("array string \"stringarr/two\"=\"hello\",\"world\\n\"", line);
|
||||
std::tie(line, rem) = rem.split('\n');
|
||||
ASSERT_EQ("", line);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentBadHeader) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::istringstream iss("");
|
||||
EXPECT_CALL(warn, Warn(1, "header line mismatch, ignoring rest of file"));
|
||||
EXPECT_FALSE(storage.LoadPersistent(iss, warn_func));
|
||||
|
||||
std::istringstream iss2("[NetworkTables");
|
||||
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());
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentCommentHeader) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::istringstream iss(
|
||||
"\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());
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentEmptyName) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::istringstream iss(
|
||||
"[NetworkTables Storage 3.0]\nboolean \"\"=true\n");
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentAssign) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::istringstream iss(
|
||||
"[NetworkTables Storage 3.0]\nboolean \"foo\"=true\n");
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
auto entry = storage.GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(true), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kAssign, update.kind);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, LoadPersistentUpdateFlags) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::istringstream iss(
|
||||
"[NetworkTables Storage 3.0]\nboolean \"foo\"=true\n");
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
auto entry = storage.GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(true), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kFlagsUpdate, update.kind);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, LoadPersistentUpdateValue) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
storage.GetEntry("foo")->set_flags(NT_PERSISTENT);
|
||||
while (!updates().empty()) updates().pop();
|
||||
|
||||
std::istringstream iss(
|
||||
"[NetworkTables Storage 3.0]\nboolean \"foo\"=false\n");
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
auto entry = storage.GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(false), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(1u, updates().size());
|
||||
auto update = updates().pop();
|
||||
EXPECT_EQ(entry, update.entry);
|
||||
EXPECT_EQ(Storage::Update::kValueUpdate, update.kind);
|
||||
}
|
||||
|
||||
TEST_F(StorageTestPopulateOne, LoadPersistentUpdateValueFlags) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::istringstream iss(
|
||||
"[NetworkTables Storage 3.0]\nboolean \"foo\"=false\n");
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
auto entry = storage.GetEntry("foo");
|
||||
EXPECT_EQ(*Value::MakeBoolean(false), *entry->value());
|
||||
EXPECT_EQ(NT_PERSISTENT, entry->flags());
|
||||
ASSERT_EQ(2u, updates().size());
|
||||
auto update = updates().pop();
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistent) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::string in = "[NetworkTables Storage 3.0]\n";
|
||||
in += "boolean \"\\x00\\x03\\x05\\n\"=true\n";
|
||||
in += "boolean \"boolean/false\"=false\n";
|
||||
in += "boolean \"boolean/true\"=true\n";
|
||||
in += "array boolean \"booleanarr/empty\"=\n";
|
||||
in += "array boolean \"booleanarr/one\"=true\n";
|
||||
in += "array boolean \"booleanarr/two\"=true,false\n";
|
||||
in += "double \"double/big\"=1.3e+08\n";
|
||||
in += "double \"double/neg\"=-1.5\n";
|
||||
in += "double \"double/zero\"=0\n";
|
||||
in += "array double \"doublearr/empty\"=\n";
|
||||
in += "array double \"doublearr/one\"=0.5\n";
|
||||
in += "array double \"doublearr/two\"=0.5,-0.25\n";
|
||||
in += "raw \"raw/empty\"=\n";
|
||||
in += "raw \"raw/normal\"=aGVsbG8=\n";
|
||||
in += "raw \"raw/special\"=AAMFCg==\n";
|
||||
in += "string \"string/empty\"=\"\"\n";
|
||||
in += "string \"string/normal\"=\"hello\"\n";
|
||||
in += "string \"string/special\"=\"\\x00\\x03\\x05\\n\"\n";
|
||||
in += "array string \"stringarr/empty\"=\n";
|
||||
in += "array string \"stringarr/one\"=\"hello\"\n";
|
||||
in += "array string \"stringarr/two\"=\"hello\",\"world\\n\"\n";
|
||||
|
||||
std::istringstream iss(in);
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
ASSERT_EQ(21u, entries().size());
|
||||
ASSERT_EQ(21u, updates().size());
|
||||
|
||||
EXPECT_EQ(*Value::MakeBoolean(true), *storage.GetEntryValue("boolean/true"));
|
||||
EXPECT_EQ(*Value::MakeBoolean(false),
|
||||
*storage.GetEntryValue("boolean/false"));
|
||||
EXPECT_EQ(*Value::MakeDouble(-1.5), *storage.GetEntryValue("double/neg"));
|
||||
EXPECT_EQ(*Value::MakeDouble(0.0), *storage.GetEntryValue("double/zero"));
|
||||
EXPECT_EQ(*Value::MakeDouble(1.3e8), *storage.GetEntryValue("double/big"));
|
||||
EXPECT_EQ(*Value::MakeString(StringRef("")),
|
||||
*storage.GetEntryValue("string/empty"));
|
||||
EXPECT_EQ(*Value::MakeString(StringRef("hello")),
|
||||
*storage.GetEntryValue("string/normal"));
|
||||
EXPECT_EQ(*Value::MakeString(StringRef("\0\3\5\n", 4)),
|
||||
*storage.GetEntryValue("string/special"));
|
||||
EXPECT_EQ(*Value::MakeRaw(StringRef("")),
|
||||
*storage.GetEntryValue("raw/empty"));
|
||||
EXPECT_EQ(*Value::MakeRaw(StringRef("hello")),
|
||||
*storage.GetEntryValue("raw/normal"));
|
||||
EXPECT_EQ(*Value::MakeRaw(StringRef("\0\3\5\n", 4)),
|
||||
*storage.GetEntryValue("raw/special"));
|
||||
EXPECT_EQ(*Value::MakeBooleanArray(std::vector<int>{}),
|
||||
*storage.GetEntryValue("booleanarr/empty"));
|
||||
EXPECT_EQ(*Value::MakeBooleanArray(std::vector<int>{1}),
|
||||
*storage.GetEntryValue("booleanarr/one"));
|
||||
EXPECT_EQ(*Value::MakeBooleanArray(std::vector<int>{1, 0}),
|
||||
*storage.GetEntryValue("booleanarr/two"));
|
||||
EXPECT_EQ(*Value::MakeDoubleArray(std::vector<double>{}),
|
||||
*storage.GetEntryValue("doublearr/empty"));
|
||||
EXPECT_EQ(*Value::MakeDoubleArray(std::vector<double>{0.5}),
|
||||
*storage.GetEntryValue("doublearr/one"));
|
||||
EXPECT_EQ(*Value::MakeDoubleArray(std::vector<double>{0.5, -0.25}),
|
||||
*storage.GetEntryValue("doublearr/two"));
|
||||
EXPECT_EQ(*Value::MakeStringArray(std::vector<std::string>{}),
|
||||
*storage.GetEntryValue("stringarr/empty"));
|
||||
EXPECT_EQ(*Value::MakeStringArray(std::vector<std::string>{"hello"}),
|
||||
*storage.GetEntryValue("stringarr/one"));
|
||||
EXPECT_EQ(
|
||||
*Value::MakeStringArray(std::vector<std::string>{"hello", "world\n"}),
|
||||
*storage.GetEntryValue("stringarr/two"));
|
||||
EXPECT_EQ(*Value::MakeBoolean(true),
|
||||
*storage.GetEntryValue(StringRef("\0\3\5\n", 4)));
|
||||
}
|
||||
|
||||
TEST_F(StorageTest, LoadPersistentWarn) {
|
||||
MockLoadWarn warn;
|
||||
auto warn_func =
|
||||
[&](std::size_t line, const char* msg) { warn.Warn(line, msg); };
|
||||
|
||||
std::istringstream iss(
|
||||
"[NetworkTables Storage 3.0]\nboolean \"foo\"=foo\n");
|
||||
EXPECT_CALL(warn,
|
||||
Warn(2, "unrecognized boolean value, not 'true' or 'false'"));
|
||||
EXPECT_TRUE(storage.LoadPersistent(iss, warn_func));
|
||||
|
||||
ASSERT_TRUE(entries().empty());
|
||||
ASSERT_TRUE(updates().empty());
|
||||
}
|
||||
|
||||
} // namespace nt
|
||||
|
||||
Reference in New Issue
Block a user