1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <string>
6
7 #include <brillo/any.h>
8 #include <gtest/gtest.h>
9
10 using brillo::internal_details::Buffer;
11 using brillo::GetTypeTag;
12
TEST(Buffer,Empty)13 TEST(Buffer, Empty) {
14 Buffer buffer;
15 EXPECT_TRUE(buffer.IsEmpty());
16 EXPECT_EQ(Buffer::kExternal, buffer.storage_);
17 EXPECT_EQ(nullptr, buffer.GetDataPtr());
18 }
19
TEST(Buffer,Store_Int)20 TEST(Buffer, Store_Int) {
21 Buffer buffer;
22 buffer.Assign(2);
23 EXPECT_FALSE(buffer.IsEmpty());
24 EXPECT_EQ(Buffer::kContained, buffer.storage_);
25 EXPECT_STREQ(GetTypeTag<int>(), buffer.GetDataPtr()->GetTypeTag());
26 }
27
TEST(Buffer,Store_Double)28 TEST(Buffer, Store_Double) {
29 Buffer buffer;
30 buffer.Assign(2.3);
31 EXPECT_FALSE(buffer.IsEmpty());
32 EXPECT_EQ(Buffer::kContained, buffer.storage_);
33 EXPECT_STREQ(GetTypeTag<double>(), buffer.GetDataPtr()->GetTypeTag());
34 }
35
TEST(Buffer,Store_Pointers)36 TEST(Buffer, Store_Pointers) {
37 Buffer buffer;
38 // nullptr
39 buffer.Assign(nullptr);
40 EXPECT_FALSE(buffer.IsEmpty());
41 EXPECT_EQ(Buffer::kContained, buffer.storage_);
42 EXPECT_STREQ(GetTypeTag<std::nullptr_t>(),
43 buffer.GetDataPtr()->GetTypeTag());
44
45 // char *
46 buffer.Assign("abcd");
47 EXPECT_FALSE(buffer.IsEmpty());
48 EXPECT_EQ(Buffer::kContained, buffer.storage_);
49 EXPECT_STREQ(GetTypeTag<const char*>(), buffer.GetDataPtr()->GetTypeTag());
50
51 // pointer to non-trivial object
52 class NonTrivial {
53 public:
54 virtual ~NonTrivial() {}
55 } non_trivial;
56 buffer.Assign(&non_trivial);
57 EXPECT_FALSE(buffer.IsEmpty());
58 EXPECT_EQ(Buffer::kContained, buffer.storage_);
59 EXPECT_STREQ(GetTypeTag<NonTrivial*>(), buffer.GetDataPtr()->GetTypeTag());
60 }
61
TEST(Buffer,Store_NonTrivialObjects)62 TEST(Buffer, Store_NonTrivialObjects) {
63 class NonTrivial {
64 public:
65 virtual ~NonTrivial() {}
66 } non_trivial;
67 Buffer buffer;
68 buffer.Assign(non_trivial);
69 EXPECT_FALSE(buffer.IsEmpty());
70 EXPECT_EQ(Buffer::kExternal, buffer.storage_);
71 EXPECT_STREQ(GetTypeTag<NonTrivial>(), buffer.GetDataPtr()->GetTypeTag());
72 }
73
TEST(Buffer,Store_Objects)74 TEST(Buffer, Store_Objects) {
75 Buffer buffer;
76
77 struct Small {
78 double d;
79 } small = {};
80 buffer.Assign(small);
81 EXPECT_FALSE(buffer.IsEmpty());
82 EXPECT_EQ(Buffer::kContained, buffer.storage_);
83 EXPECT_STREQ(GetTypeTag<Small>(), buffer.GetDataPtr()->GetTypeTag());
84
85 struct Large {
86 char c[20];
87 } large = {};
88 buffer.Assign(large);
89 EXPECT_FALSE(buffer.IsEmpty());
90 EXPECT_EQ(Buffer::kExternal, buffer.storage_);
91 EXPECT_STREQ(GetTypeTag<Large>(), buffer.GetDataPtr()->GetTypeTag());
92 }
93
TEST(Buffer,Copy)94 TEST(Buffer, Copy) {
95 Buffer buffer1;
96 Buffer buffer2;
97
98 buffer1.Assign(30);
99 buffer1.CopyTo(&buffer2);
100 EXPECT_FALSE(buffer1.IsEmpty());
101 EXPECT_FALSE(buffer2.IsEmpty());
102 EXPECT_STREQ(GetTypeTag<int>(), buffer1.GetDataPtr()->GetTypeTag());
103 EXPECT_STREQ(GetTypeTag<int>(), buffer2.GetDataPtr()->GetTypeTag());
104 EXPECT_EQ(30, buffer1.GetData<int>());
105 EXPECT_EQ(30, buffer2.GetData<int>());
106
107 buffer1.Assign(std::string("abc"));
108 buffer1.CopyTo(&buffer2);
109 EXPECT_FALSE(buffer1.IsEmpty());
110 EXPECT_FALSE(buffer2.IsEmpty());
111 EXPECT_STREQ(GetTypeTag<std::string>(), buffer1.GetDataPtr()->GetTypeTag());
112 EXPECT_STREQ(GetTypeTag<std::string>(), buffer2.GetDataPtr()->GetTypeTag());
113 EXPECT_EQ("abc", buffer1.GetData<std::string>());
114 EXPECT_EQ("abc", buffer2.GetData<std::string>());
115 }
116
TEST(Buffer,Move)117 TEST(Buffer, Move) {
118 // Move operations essentially leave the source object in a state that is
119 // guaranteed to be safe for reuse or destruction. There is no other explicit
120 // guarantees on the exact state of the source after move (e.g. that the
121 // source Any will be Empty after the move is complete).
122 Buffer buffer1;
123 Buffer buffer2;
124
125 buffer1.Assign(30);
126 buffer1.MoveTo(&buffer2);
127 // Contained types aren't flushed, so the source Any doesn't become empty.
128 // The contained value is just moved, but for scalars this just copies
129 // the data and any retains the actual type.
130 EXPECT_FALSE(buffer1.IsEmpty());
131 EXPECT_FALSE(buffer2.IsEmpty());
132 EXPECT_STREQ(GetTypeTag<int>(), buffer2.GetDataPtr()->GetTypeTag());
133 EXPECT_EQ(30, buffer2.GetData<int>());
134
135 buffer1.Assign(std::string("abc"));
136 buffer1.MoveTo(&buffer2);
137 // External types are moved by just moving the pointer value from src to dest.
138 // This will make the source object effectively "Empty".
139 EXPECT_TRUE(buffer1.IsEmpty());
140 EXPECT_FALSE(buffer2.IsEmpty());
141 EXPECT_STREQ(GetTypeTag<std::string>(), buffer2.GetDataPtr()->GetTypeTag());
142 EXPECT_EQ("abc", buffer2.GetData<std::string>());
143 }
144