aboutsummaryrefslogtreecommitdiffstats
path: root/brillo/any_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'brillo/any_unittest.cc')
-rw-r--r--brillo/any_unittest.cc306
1 files changed, 306 insertions, 0 deletions
diff --git a/brillo/any_unittest.cc b/brillo/any_unittest.cc
new file mode 100644
index 0000000..4fd23d7
--- /dev/null
+++ b/brillo/any_unittest.cc
@@ -0,0 +1,306 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <brillo/any.h>
+#include <gtest/gtest.h>
+
+using brillo::Any;
+
+TEST(Any, Empty) {
+ Any val;
+ EXPECT_TRUE(val.IsEmpty());
+
+ Any val2 = val;
+ EXPECT_TRUE(val.IsEmpty());
+ EXPECT_TRUE(val2.IsEmpty());
+
+ Any val3 = std::move(val);
+ EXPECT_TRUE(val.IsEmpty());
+ EXPECT_TRUE(val3.IsEmpty());
+}
+
+TEST(Any, SimpleTypes) {
+ Any val(20);
+ EXPECT_FALSE(val.IsEmpty());
+ EXPECT_TRUE(val.IsTypeCompatible<int>());
+ EXPECT_EQ(20, val.Get<int>());
+
+ Any val2(3.1415926);
+ EXPECT_FALSE(val2.IsEmpty());
+ EXPECT_TRUE(val2.IsTypeCompatible<double>());
+ EXPECT_FALSE(val2.IsTypeCompatible<int>());
+ EXPECT_DOUBLE_EQ(3.1415926, val2.Get<double>());
+
+ Any val3(std::string("blah"));
+ EXPECT_TRUE(val3.IsTypeCompatible<std::string>());
+ EXPECT_EQ("blah", val3.Get<std::string>());
+}
+
+TEST(Any, Clear) {
+ Any val('x');
+ EXPECT_FALSE(val.IsEmpty());
+ EXPECT_EQ('x', val.Get<char>());
+
+ val.Clear();
+ EXPECT_TRUE(val.IsEmpty());
+}
+
+TEST(Any, Assignments) {
+ Any val(20);
+ EXPECT_EQ(20, val.Get<int>());
+
+ val = 3.1415926;
+ EXPECT_FALSE(val.IsEmpty());
+ EXPECT_TRUE(val.IsTypeCompatible<double>());
+ EXPECT_DOUBLE_EQ(3.1415926, val.Get<double>());
+
+ val = std::string("blah");
+ EXPECT_EQ("blah", val.Get<std::string>());
+
+ Any val2;
+ EXPECT_TRUE(val2.IsEmpty());
+ val2 = val;
+ EXPECT_FALSE(val.IsEmpty());
+ EXPECT_FALSE(val2.IsEmpty());
+ EXPECT_EQ("blah", val.Get<std::string>());
+ EXPECT_EQ("blah", val2.Get<std::string>());
+ val.Clear();
+ EXPECT_TRUE(val.IsEmpty());
+ EXPECT_EQ("blah", val2.Get<std::string>());
+ val2.Clear();
+ EXPECT_TRUE(val2.IsEmpty());
+
+ val = std::vector<int>{100, 20, 3};
+ auto v = val.Get<std::vector<int>>();
+ EXPECT_EQ(100, v[0]);
+ EXPECT_EQ(20, v[1]);
+ EXPECT_EQ(3, v[2]);
+
+ val2 = std::move(val);
+ EXPECT_TRUE(val.IsEmpty());
+ EXPECT_TRUE(val2.IsTypeCompatible<std::vector<int>>());
+ EXPECT_EQ(3, val2.Get<std::vector<int>>().size());
+
+ val = val2;
+ EXPECT_TRUE(val.IsTypeCompatible<std::vector<int>>());
+ EXPECT_TRUE(val2.IsTypeCompatible<std::vector<int>>());
+ EXPECT_EQ(3, val.Get<std::vector<int>>().size());
+ EXPECT_EQ(3, val2.Get<std::vector<int>>().size());
+}
+
+TEST(Any, Enums) {
+ enum class Dummy { foo, bar, baz };
+ Any val(Dummy::bar);
+ EXPECT_FALSE(val.IsEmpty());
+ EXPECT_TRUE(val.IsConvertibleToInteger());
+ EXPECT_EQ(Dummy::bar, val.Get<Dummy>());
+ EXPECT_EQ(1, val.GetAsInteger());
+
+ val = Dummy::baz;
+ EXPECT_EQ(2, val.GetAsInteger());
+
+ val = Dummy::foo;
+ EXPECT_EQ(0, val.GetAsInteger());
+}
+
+TEST(Any, Integers) {
+ Any val(14);
+ EXPECT_TRUE(val.IsConvertibleToInteger());
+ EXPECT_EQ(14, val.Get<int>());
+ EXPECT_EQ(14, val.GetAsInteger());
+
+ val = '\x40';
+ EXPECT_TRUE(val.IsConvertibleToInteger());
+ EXPECT_EQ(64, val.Get<char>());
+ EXPECT_EQ(64, val.GetAsInteger());
+
+ val = static_cast<uint16_t>(65535);
+ EXPECT_TRUE(val.IsConvertibleToInteger());
+ EXPECT_EQ(65535, val.Get<uint16_t>());
+ EXPECT_EQ(65535, val.GetAsInteger());
+
+ val = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL);
+ EXPECT_TRUE(val.IsConvertibleToInteger());
+ EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, val.Get<uint64_t>());
+ EXPECT_EQ(-1, val.GetAsInteger());
+
+ val = "abc";
+ EXPECT_FALSE(val.IsConvertibleToInteger());
+
+ int a = 5;
+ val = &a;
+ EXPECT_FALSE(val.IsConvertibleToInteger());
+}
+
+TEST(Any, Pointers) {
+ Any val("abc"); // const char*
+ EXPECT_FALSE(val.IsTypeCompatible<char*>());
+ EXPECT_TRUE(val.IsTypeCompatible<const char*>());
+ EXPECT_FALSE(val.IsTypeCompatible<volatile char*>());
+ EXPECT_TRUE(val.IsTypeCompatible<volatile const char*>());
+ EXPECT_STREQ("abc", val.Get<const char*>());
+
+ int a = 10;
+ val = &a;
+ EXPECT_TRUE(val.IsTypeCompatible<int*>());
+ EXPECT_TRUE(val.IsTypeCompatible<const int*>());
+ EXPECT_TRUE(val.IsTypeCompatible<volatile int*>());
+ EXPECT_TRUE(val.IsTypeCompatible<volatile const int*>());
+ EXPECT_EQ(10, *val.Get<const int*>());
+ *val.Get<int*>() = 3;
+ EXPECT_EQ(3, a);
+}
+
+TEST(Any, Arrays) {
+ // The following test are here to validate the array-to-pointer decay rules.
+ // Since Any does not store the contents of a C-style array, just a pointer
+ // to the data, putting array data into Any could be dangerous.
+ // Make sure the array's lifetime exceeds that of an Any containing the
+ // pointer to the array data.
+ // If you want to store the array with data, use corresponding value types
+ // such as std::vector or a struct containing C-style array as a member.
+
+ int int_array[] = {1, 2, 3}; // int*
+ Any val = int_array;
+ EXPECT_TRUE(val.IsTypeCompatible<int*>());
+ EXPECT_TRUE(val.IsTypeCompatible<const int*>());
+ EXPECT_TRUE(val.IsTypeCompatible<int[]>());
+ EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
+ EXPECT_EQ(3, val.Get<int*>()[2]);
+
+ const int const_int_array[] = {10, 20, 30}; // const int*
+ val = const_int_array;
+ EXPECT_FALSE(val.IsTypeCompatible<int*>());
+ EXPECT_TRUE(val.IsTypeCompatible<const int*>());
+ EXPECT_FALSE(val.IsTypeCompatible<int[]>());
+ EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
+ EXPECT_EQ(30, val.Get<const int*>()[2]);
+}
+
+TEST(Any, References) {
+ // Passing references to object via Any might be error-prone or the
+ // semantics could be unfamiliar to other developers. In many cases,
+ // using pointers instead of references are more conventional and easier
+ // to understand. Even though the cases of passing references are quite
+ // explicit on both storing and retrieving ends, you might want to
+ // use pointers instead anyway.
+
+ int a = 5;
+ Any val(std::ref(a)); // int&
+ EXPECT_EQ(5, val.Get<std::reference_wrapper<int>>().get());
+ val.Get<std::reference_wrapper<int>>().get() = 7;
+ EXPECT_EQ(7, val.Get<std::reference_wrapper<int>>().get());
+ EXPECT_EQ(7, a);
+
+ Any val2(std::cref(a)); // const int&
+ EXPECT_EQ(7, val2.Get<std::reference_wrapper<const int>>().get());
+
+ a = 10;
+ EXPECT_EQ(10, val.Get<std::reference_wrapper<int>>().get());
+ EXPECT_EQ(10, val2.Get<std::reference_wrapper<const int>>().get());
+}
+
+TEST(Any, CustomTypes) {
+ struct Person {
+ std::string name;
+ int age;
+ };
+ Any val(Person{"Jack", 40});
+ Any val2 = val;
+ EXPECT_EQ("Jack", val.Get<Person>().name);
+ val.GetPtr<Person>()->name = "Joe";
+ val.GetPtr<Person>()->age /= 2;
+ EXPECT_EQ("Joe", val.Get<Person>().name);
+ EXPECT_EQ(20, val.Get<Person>().age);
+ EXPECT_EQ("Jack", val2.Get<Person>().name);
+ EXPECT_EQ(40, val2.Get<Person>().age);
+}
+
+TEST(Any, Swap) {
+ Any val(12);
+ Any val2(2.7);
+ EXPECT_EQ(12, val.Get<int>());
+ EXPECT_EQ(2.7, val2.Get<double>());
+
+ val.Swap(val2);
+ EXPECT_EQ(2.7, val.Get<double>());
+ EXPECT_EQ(12, val2.Get<int>());
+
+ std::swap(val, val2);
+ EXPECT_EQ(12, val.Get<int>());
+ EXPECT_EQ(2.7, val2.Get<double>());
+}
+
+TEST(Any, TypeMismatch) {
+ Any val(12);
+ EXPECT_DEATH(val.Get<double>(),
+ "Requesting value of type 'double' from variant containing "
+ "'int'");
+
+ val = std::string("123");
+ EXPECT_DEATH(val.GetAsInteger(),
+ "Unable to convert value of type 'std::string' to integer");
+
+ Any empty;
+ EXPECT_DEATH(empty.GetAsInteger(), "Must not be called on an empty Any");
+}
+
+TEST(Any, TryGet) {
+ Any val(12);
+ Any empty;
+ EXPECT_EQ("dummy", val.TryGet<std::string>("dummy"));
+ EXPECT_EQ(12, val.TryGet<int>(17));
+ EXPECT_EQ(17, empty.TryGet<int>(17));
+}
+
+TEST(Any, Compare_Int) {
+ Any int1{12};
+ Any int2{12};
+ Any int3{20};
+ EXPECT_EQ(int1, int2);
+ EXPECT_NE(int2, int3);
+}
+
+TEST(Any, Compare_String) {
+ Any str1{std::string{"foo"}};
+ Any str2{std::string{"foo"}};
+ Any str3{std::string{"bar"}};
+ EXPECT_EQ(str1, str2);
+ EXPECT_NE(str2, str3);
+}
+
+TEST(Any, Compare_Array) {
+ Any vec1{std::vector<int>{1, 2}};
+ Any vec2{std::vector<int>{1, 2}};
+ Any vec3{std::vector<int>{1, 2, 3}};
+ EXPECT_EQ(vec1, vec2);
+ EXPECT_NE(vec2, vec3);
+}
+
+TEST(Any, Compare_Empty) {
+ Any empty1;
+ Any empty2;
+ Any int1{1};
+ EXPECT_EQ(empty1, empty2);
+ EXPECT_NE(int1, empty1);
+ EXPECT_NE(empty2, int1);
+}
+
+TEST(Any, Compare_NonComparable) {
+ struct Person {
+ std::string name;
+ int age;
+ };
+ Any person1(Person{"Jack", 40});
+ Any person2 = person1;
+ Any person3(Person{"Jill", 20});
+ EXPECT_NE(person1, person2);
+ EXPECT_NE(person1, person3);
+ EXPECT_NE(person2, person3);
+}