Files
allwpilib/test/unit/test_Value.cpp
Peter Johnson 5a0fccc9cf Add unit tests for StringValue and Value.
Add unit test framework to CMakeLists.txt.
Fix a couple of bugs found by unit tests.

Change-Id: I2092a7f0570fae0f19f9e083c4837ccefcc4ca1a
2015-07-11 09:33:33 -07:00

348 lines
10 KiB
C++

#include "Value.h"
#include "gtest/gtest.h"
namespace ntimpl {
class ValueTest : public ::testing::Test {
public:
NT_Value& ToNT(Value& v) { return v; }
};
typedef ValueTest ValueDeathTest;
TEST_F(ValueTest, ConstructEmpty) {
Value v;
ASSERT_EQ(ToNT(v).type, NT_UNASSIGNED);
ASSERT_EQ(ToNT(v).last_change, 0u);
ASSERT_EQ(v.type(), NT_UNASSIGNED);
}
TEST_F(ValueTest, ConstructMove) {
Value v;
v.SetString("hello");
ASSERT_EQ(v.type(), NT_STRING);
Value v2(std::move(v));
ASSERT_EQ(v.type(), NT_UNASSIGNED);
ASSERT_EQ(v2.type(), NT_STRING);
}
TEST_F(ValueTest, AssignMove) {
Value v;
v.SetString("hello");
ASSERT_EQ(v.type(), NT_STRING);
Value v2;
v2.SetDouble(0.5);
ASSERT_EQ(v2.type(), NT_DOUBLE);
v2 = std::move(v);
ASSERT_EQ(v.type(), NT_UNASSIGNED);
ASSERT_EQ(v2.type(), NT_STRING);
}
TEST_F(ValueTest, Boolean) {
Value v;
v.SetBoolean(false);
ASSERT_EQ(ToNT(v).type, NT_BOOLEAN);
ASSERT_EQ(ToNT(v).data.v_boolean, false);
ASSERT_EQ(v.type(), NT_BOOLEAN);
ASSERT_EQ(v.GetBoolean(), false);
v.SetBoolean(true);
ASSERT_EQ(ToNT(v).type, NT_BOOLEAN);
ASSERT_EQ(ToNT(v).data.v_boolean, true);
ASSERT_EQ(v.type(), NT_BOOLEAN);
ASSERT_EQ(v.GetBoolean(), true);
}
TEST_F(ValueTest, Double) {
Value v;
v.SetDouble(0.5);
ASSERT_EQ(ToNT(v).type, NT_DOUBLE);
ASSERT_EQ(ToNT(v).data.v_double, 0.5);
ASSERT_EQ(v.type(), NT_DOUBLE);
ASSERT_EQ(v.GetDouble(), 0.5);
v.SetDouble(0.25);
ASSERT_EQ(ToNT(v).type, NT_DOUBLE);
ASSERT_EQ(ToNT(v).data.v_double, 0.25);
ASSERT_EQ(v.type(), NT_DOUBLE);
ASSERT_EQ(v.GetDouble(), 0.25);
}
TEST_F(ValueTest, String) {
Value v;
v.SetString("hello");
ASSERT_EQ(ToNT(v).type, NT_STRING);
ASSERT_EQ(ToNT(v).data.v_string.str, llvm::StringRef("hello"));
ASSERT_EQ(ToNT(v).data.v_string.len, 5u);
ASSERT_EQ(v.type(), NT_STRING);
ASSERT_EQ(v.GetString(), "hello");
v.SetString("goodbye");
ASSERT_EQ(ToNT(v).type, NT_STRING);
ASSERT_EQ(ToNT(v).data.v_string.str, llvm::StringRef("goodbye"));
ASSERT_EQ(ToNT(v).data.v_string.len, 7u);
ASSERT_EQ(v.type(), NT_STRING);
ASSERT_EQ(v.GetString(), "goodbye");
}
TEST_F(ValueTest, Raw) {
Value v;
v.SetRaw("hello");
ASSERT_EQ(ToNT(v).type, NT_RAW);
ASSERT_EQ(ToNT(v).data.v_string.str, llvm::StringRef("hello"));
ASSERT_EQ(ToNT(v).data.v_string.len, 5u);
ASSERT_EQ(v.type(), NT_RAW);
ASSERT_EQ(v.GetRaw(), "hello");
v.SetRaw("goodbye");
ASSERT_EQ(ToNT(v).type, NT_RAW);
ASSERT_EQ(ToNT(v).data.v_string.str, llvm::StringRef("goodbye"));
ASSERT_EQ(ToNT(v).data.v_string.len, 7u);
ASSERT_EQ(v.type(), NT_RAW);
ASSERT_EQ(v.GetRaw(), "goodbye");
}
TEST_F(ValueTest, BooleanArray) {
Value v;
std::vector<int> vec{1,0,1};
v.SetBooleanArray(vec);
ASSERT_EQ(ToNT(v).type, NT_BOOLEAN_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_boolean.size, 3u);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[0], vec[0]);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[1], vec[1]);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[2], vec[2]);
ASSERT_EQ(v.type(), NT_BOOLEAN_ARRAY);
ASSERT_EQ(v.GetBooleanArray(), llvm::ArrayRef<int>(vec));
// assign with same size
vec = {0,1,0};
v.SetBooleanArray(vec);
ASSERT_EQ(ToNT(v).type, NT_BOOLEAN_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_boolean.size, 3u);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[0], vec[0]);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[1], vec[1]);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[2], vec[2]);
ASSERT_EQ(v.type(), NT_BOOLEAN_ARRAY);
ASSERT_EQ(v.GetBooleanArray(), llvm::ArrayRef<int>(vec));
// assign with different size
vec = {1,0};
v.SetBooleanArray(vec);
ASSERT_EQ(ToNT(v).type, NT_BOOLEAN_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_boolean.size, 2u);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[0], vec[0]);
ASSERT_EQ(ToNT(v).data.arr_boolean.arr[1], vec[1]);
ASSERT_EQ(v.type(), NT_BOOLEAN_ARRAY);
ASSERT_EQ(v.GetBooleanArray(), llvm::ArrayRef<int>(vec));
}
TEST_F(ValueTest, DoubleArray) {
Value v;
std::vector<double> vec{0.5,0.25,0.5};
v.SetDoubleArray(vec);
ASSERT_EQ(ToNT(v).type, NT_DOUBLE_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_double.size, 3u);
ASSERT_EQ(ToNT(v).data.arr_double.arr[0], vec[0]);
ASSERT_EQ(ToNT(v).data.arr_double.arr[1], vec[1]);
ASSERT_EQ(ToNT(v).data.arr_double.arr[2], vec[2]);
ASSERT_EQ(v.type(), NT_DOUBLE_ARRAY);
ASSERT_EQ(v.GetDoubleArray(), llvm::ArrayRef<double>(vec));
// assign with same size
vec = {0.25,0.5,0.25};
v.SetDoubleArray(vec);
ASSERT_EQ(ToNT(v).type, NT_DOUBLE_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_double.size, 3u);
ASSERT_EQ(ToNT(v).data.arr_double.arr[0], vec[0]);
ASSERT_EQ(ToNT(v).data.arr_double.arr[1], vec[1]);
ASSERT_EQ(ToNT(v).data.arr_double.arr[2], vec[2]);
ASSERT_EQ(v.type(), NT_DOUBLE_ARRAY);
ASSERT_EQ(v.GetDoubleArray(), llvm::ArrayRef<double>(vec));
// assign with different size
vec = {0.5,0.25};
v.SetDoubleArray(vec);
ASSERT_EQ(ToNT(v).type, NT_DOUBLE_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_double.size, 2u);
ASSERT_EQ(ToNT(v).data.arr_double.arr[0], vec[0]);
ASSERT_EQ(ToNT(v).data.arr_double.arr[1], vec[1]);
ASSERT_EQ(v.type(), NT_DOUBLE_ARRAY);
ASSERT_EQ(v.GetDoubleArray(), llvm::ArrayRef<double>(vec));
}
TEST_F(ValueTest, StringArray) {
Value v;
std::vector<StringValue> vec;
vec.push_back(StringValue("hello"));
vec.push_back(StringValue("goodbye"));
vec.push_back(StringValue("string"));
v.SetStringArray(vec);
ASSERT_TRUE(vec.empty());
ASSERT_EQ(ToNT(v).type, NT_STRING_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_string.size, 3u);
ASSERT_EQ(ToNT(v).data.arr_string.arr[0].str, llvm::StringRef("hello"));
ASSERT_EQ(ToNT(v).data.arr_string.arr[1].str, llvm::StringRef("goodbye"));
ASSERT_EQ(ToNT(v).data.arr_string.arr[2].str, llvm::StringRef("string"));
ASSERT_EQ(v.type(), NT_STRING_ARRAY);
ASSERT_EQ(v.GetStringArray()[0], llvm::StringRef("hello"));
ASSERT_EQ(v.GetStringArray()[1], llvm::StringRef("goodbye"));
ASSERT_EQ(v.GetStringArray()[2], llvm::StringRef("string"));
// assign with same size
vec.clear();
vec.push_back(StringValue("s1"));
vec.push_back(StringValue("str2"));
vec.push_back(StringValue("string3"));
v.SetStringArray(vec);
ASSERT_TRUE(vec.empty());
ASSERT_EQ(ToNT(v).type, NT_STRING_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_string.size, 3u);
ASSERT_EQ(ToNT(v).data.arr_string.arr[0].str, llvm::StringRef("s1"));
ASSERT_EQ(ToNT(v).data.arr_string.arr[1].str, llvm::StringRef("str2"));
ASSERT_EQ(ToNT(v).data.arr_string.arr[2].str, llvm::StringRef("string3"));
ASSERT_EQ(v.type(), NT_STRING_ARRAY);
ASSERT_EQ(v.GetStringArray()[0], llvm::StringRef("s1"));
ASSERT_EQ(v.GetStringArray()[1], llvm::StringRef("str2"));
ASSERT_EQ(v.GetStringArray()[2], llvm::StringRef("string3"));
// assign with different size
vec.clear();
vec.push_back(StringValue("short"));
vec.push_back(StringValue("er"));
v.SetStringArray(vec);
ASSERT_TRUE(vec.empty());
ASSERT_EQ(ToNT(v).type, NT_STRING_ARRAY);
ASSERT_EQ(ToNT(v).data.arr_string.size, 2u);
ASSERT_EQ(ToNT(v).data.arr_string.arr[0].str, llvm::StringRef("short"));
ASSERT_EQ(ToNT(v).data.arr_string.arr[1].str, llvm::StringRef("er"));
ASSERT_EQ(v.type(), NT_STRING_ARRAY);
ASSERT_EQ(v.GetStringArray()[0], llvm::StringRef("short"));
ASSERT_EQ(v.GetStringArray()[1], llvm::StringRef("er"));
}
TEST_F(ValueDeathTest, GetAssertions) {
Value v;
ASSERT_DEATH(v.GetBoolean(), "NT_Value::type == NT_BOOLEAN");
ASSERT_DEATH(v.GetDouble(), "NT_Value::type == NT_DOUBLE");
ASSERT_DEATH(v.GetString(), "NT_Value::type == NT_STRING");
ASSERT_DEATH(v.GetRaw(), "NT_Value::type == NT_RAW");
ASSERT_DEATH(v.GetBooleanArray(), "NT_Value::type == NT_BOOLEAN_ARRAY");
ASSERT_DEATH(v.GetDoubleArray(), "NT_Value::type == NT_DOUBLE_ARRAY");
ASSERT_DEATH(v.GetStringArray(), "NT_Value::type == NT_STRING_ARRAY");
}
TEST_F(ValueTest, UnassignedComparison) {
Value v1, v2;
ASSERT_EQ(v1, v2);
}
TEST_F(ValueTest, MixedComparison) {
Value v1, v2;
v1.SetBoolean(true);
ASSERT_NE(v1, v2); // unassigned vs boolean
v2.SetDouble(0.5);
ASSERT_NE(v1, v2); // boolean vs double
}
TEST_F(ValueTest, BooleanComparison) {
Value v1, v2;
v1.SetBoolean(true);
v2.SetBoolean(true);
ASSERT_EQ(v1, v2);
v2.SetBoolean(false);
ASSERT_NE(v1, v2);
}
TEST_F(ValueTest, DoubleComparison) {
Value v1, v2;
v1.SetDouble(0.25);
v2.SetDouble(0.25);
ASSERT_EQ(v1, v2);
v2.SetDouble(0.5);
ASSERT_NE(v1, v2);
}
TEST_F(ValueTest, StringComparison) {
Value v1, v2;
v1.SetString("hello");
v2.SetString("hello");
ASSERT_EQ(v1, v2);
v2.SetString("world"); // different contents
ASSERT_NE(v1, v2);
v2.SetString("goodbye"); // different size
ASSERT_NE(v1, v2);
}
TEST_F(ValueTest, BooleanArrayComparison) {
Value v1, v2;
std::vector<int> vec{1,0,1};
v1.SetBooleanArray(vec);
v2.SetBooleanArray(vec);
ASSERT_EQ(v1, v2);
// different contents
vec = {1,1,1};
v2.SetBooleanArray(vec);
ASSERT_NE(v1, v2);
// different size
vec = {1,0};
v2.SetBooleanArray(vec);
ASSERT_NE(v1, v2);
}
TEST_F(ValueTest, DoubleArrayComparison) {
Value v1, v2;
std::vector<double> vec{0.5,0.25,0.5};
v1.SetDoubleArray(vec);
v2.SetDoubleArray(vec);
ASSERT_EQ(v1, v2);
// different contents
vec = {0.5,0.5,0.5};
v2.SetDoubleArray(vec);
ASSERT_NE(v1, v2);
// different size
vec = {0.5,0.25};
v2.SetDoubleArray(vec);
ASSERT_NE(v1, v2);
}
TEST_F(ValueTest, StringArrayComparison) {
Value v1, v2;
std::vector<StringValue> vec;
vec.push_back(StringValue("hello"));
vec.push_back(StringValue("goodbye"));
vec.push_back(StringValue("string"));
v1.SetStringArray(vec);
vec.clear();
vec.push_back(StringValue("hello"));
vec.push_back(StringValue("goodbye"));
vec.push_back(StringValue("string"));
v2.SetStringArray(vec);
ASSERT_EQ(v1, v2);
// different contents
vec.clear();
vec.push_back(StringValue("hello"));
vec.push_back(StringValue("goodby2"));
vec.push_back(StringValue("string"));
v2.SetStringArray(vec);
ASSERT_NE(v1, v2);
// different sized contents
vec.clear();
vec.push_back(StringValue("hello"));
vec.push_back(StringValue("goodbye2"));
vec.push_back(StringValue("string"));
v2.SetStringArray(vec);
ASSERT_NE(v1, v2);
// different size
vec.clear();
vec.push_back(StringValue("hello"));
vec.push_back(StringValue("goodbye"));
v2.SetStringArray(vec);
ASSERT_NE(v1, v2);
}
} // namespace ntimpl