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