1 /*
2 * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstdlib>
17 #include <memory>
18 #include <string>
19 #include "gtest/gtest.h"
20 #define private public
21 #define protected public
22 #include "common/any.h"
23
24 namespace OHOS {
25 namespace Media {
26 namespace Test {
27 using namespace OHOS::Media::Plugin;
CompareFunctionTable(const Any::FunctionTable * ft1,const Any::FunctionTable * ft2)28 bool CompareFunctionTable(const Any::FunctionTable* ft1, const Any::FunctionTable* ft2)
29 {
30 return ft1->type == ft2->type && ft1->destroy == ft2->destroy && ft1->getPtr == ft2->getPtr &&
31 ft1->move == ft2->move && ft1->copy == ft2->copy && ft1->getConstPtr == ft2->getConstPtr;
32 }
33
34 template <typename T, template <class> class U>
UseStorage()35 bool UseStorage()
36 {
37 auto ft1 = Any::GetFunctionTable<T>();
38 Any::FunctionTable ft2 {
39 .type = U<T>::Type,
40 .destroy = U<T>::Destroy,
41 .copy = U<T>::Copy,
42 .move = U<T>::Move,
43 .getPtr = U<T>::GetPtr,
44 .getConstPtr = U<T>::GetConstPtr
45 };
46 return CompareFunctionTable(ft1, &ft2);
47 }
48
49 class NonTrivialCopyable {
50 public:
NonTrivialCopyable(uint8_t a)51 explicit NonTrivialCopyable(uint8_t a) : a_(a)
52 {
53 }
NonTrivialCopyable(const NonTrivialCopyable & a)54 NonTrivialCopyable(const NonTrivialCopyable& a) : a_(a.a_)
55 {
56 }
operator =(const NonTrivialCopyable & other)57 NonTrivialCopyable& operator=(const NonTrivialCopyable& other)
58 {
59 if (this != &other) {
60 this->a_ = other.a_;
61 }
62 return *this;
63 }
64 uint8_t a_;
65 };
66
67 class NonTrivialNonThrowMove {
68 public:
NonTrivialNonThrowMove(uint8_t a)69 explicit NonTrivialNonThrowMove(uint8_t a) : a_(a)
70 {
71 }
NonTrivialNonThrowMove(const NonTrivialNonThrowMove & a)72 explicit NonTrivialNonThrowMove(const NonTrivialNonThrowMove& a) : a_(a.a_)
73 {
74 }
operator =(const NonTrivialNonThrowMove & other)75 NonTrivialNonThrowMove& operator=(const NonTrivialNonThrowMove& other)
76 {
77 if (this != &other) {
78 a_ = other.a_;
79 }
80 return *this;
81 }
NonTrivialNonThrowMove(NonTrivialNonThrowMove && t)82 NonTrivialNonThrowMove(NonTrivialNonThrowMove&& t) noexcept
83 {
84 a_ = t.a_;
85 }
operator =(NonTrivialNonThrowMove && other)86 NonTrivialNonThrowMove& operator=(NonTrivialNonThrowMove&& other)
87 {
88 a_ = other.a_;
89 return *this;
90 }
91 uint8_t a_;
92 };
93
TEST(AnyTest,testAnyUseTrivial)94 TEST(AnyTest, testAnyUseTrivial)
95 {
96 auto tmp = UseStorage<uint8_t, Any::TrivialStackFunctionTable>();
97 ASSERT_TRUE(tmp);
98 tmp = UseStorage<int8_t, Any::TrivialStackFunctionTable>();
99 ASSERT_TRUE(tmp);
100 tmp = UseStorage<uint16_t, Any::TrivialStackFunctionTable>();
101 ASSERT_TRUE(tmp);
102 tmp = UseStorage<int16_t, Any::TrivialStackFunctionTable>();
103 ASSERT_TRUE(tmp);
104 tmp = UseStorage<uint32_t, Any::TrivialStackFunctionTable>();
105 ASSERT_TRUE(tmp);
106 tmp = UseStorage<int32_t, Any::TrivialStackFunctionTable>();
107 ASSERT_TRUE(tmp);
108 tmp = UseStorage<uint64_t, Any::TrivialStackFunctionTable>();
109 ASSERT_TRUE(tmp);
110 tmp = UseStorage<int64_t, Any::TrivialStackFunctionTable>();
111 ASSERT_TRUE(tmp);
112 tmp = UseStorage<NonTrivialCopyable, Any::TrivialStackFunctionTable>();
113 ASSERT_FALSE(tmp);
114 }
115
TEST(AnyTest,testAnyUseStack)116 TEST(AnyTest, testAnyUseStack)
117 {
118 auto tmp = UseStorage<NonTrivialCopyable, Any::StackFunctionTable>();
119 ASSERT_FALSE(tmp);
120 tmp = UseStorage<NonTrivialNonThrowMove, Any::StackFunctionTable>();
121 ASSERT_TRUE(tmp);
122 tmp = UseStorage<std::shared_ptr<int>, Any::StackFunctionTable>();
123 ASSERT_TRUE(tmp);
124 }
125
TEST(AnyTest,testAnyUseHeap)126 TEST(AnyTest, testAnyUseHeap)
127 {
128 auto tmp = UseStorage<NonTrivialCopyable, Any::HeapFunctionTable>();
129 ASSERT_TRUE(tmp);
130 }
131
TEST(AnyTest,testAnyCast)132 TEST(AnyTest, testAnyCast)
133 {
134 const int number = 12;
135 auto a = Any(number);
136 int* i = AnyCast<int>(&a);
137 ASSERT_TRUE(*i == number);
138 a = std::string("hello");
139 auto& ra = AnyCast<std::string&>(a);
140 ra[1] = 'o';
141 const auto& refString = AnyCast<const std::string&>(a);
142 ASSERT_STREQ(refString.c_str(), "hollo");
143 auto copyString = AnyCast<std::string>(a);
144 copyString[1] = 'l';
145 ASSERT_STREQ(refString.c_str(), "hollo");
146 ASSERT_STREQ(copyString.c_str(), "hlllo");
147
148 ASSERT_THROW(AnyCast<std::string>("test"), BadAnyCast);
149 ASSERT_THROW(AnyCast<char*>("test"), BadAnyCast);
150 }
151
152 class Star {
153 std::string name_;
154 int id_;
155
156 public:
Star(std::string name,int id)157 Star(std::string name, int id) : name_ {std::move(name)}, id_ {id}
158 {
159 }
160
operator ==(const Star & other) const161 bool operator==(const Star& other) const
162 {
163 return name_ == other.name_ && id_ == other.id_;
164 }
165 };
166
TEST(AnyTest,testAnyEmplace)167 TEST(AnyTest, testAnyEmplace)
168 {
169 Any celestial;
170 celestial.Emplace<Star>("Procyon", 2943);
171 Star star1("Procyon", 2943);
172 const auto* star = AnyCast<Star>(&celestial);
173 ASSERT_TRUE(star1 == (*star));
174
175 Any av;
176 av.Emplace<std::vector<char>>({'C', '+', '+', '1', '7'});
177 const auto* va = AnyCast<std::vector<char>>(&av);
178 std::vector<char> vector1({'C', '+', '+', '1', '7'});
179 ASSERT_TRUE(vector1 == (*va));
180 }
181
TEST(AnyTest,testMakeAny)182 TEST(AnyTest, testMakeAny)
183 {
184 Star star1("Procyon", 2943);
185 Any celestial = MakeAny<Star, std::string, int32_t>("Procyon", 2943);
186 ASSERT_TRUE(AnyCast<Star>(celestial) == star1);
187
188 std::vector<char> vector1({'C', '+', '+', '1', '7'});
189 Any av = MakeAny<std::vector<char>>({'C', '+', '+', '1', '7'});
190 ASSERT_TRUE(AnyCast<std::vector<char>>(av) == vector1);
191 }
192
TEST(AnyTest,testType)193 TEST(AnyTest, testType)
194 {
195 Any test = "test";
196 ASSERT_TRUE(test.Type() == typeid(const char*));
197 ASSERT_NE(test.Type(), typeid(char*));
198 ASSERT_NE(test.Type(), typeid(char*));
199 }
200
TEST(AnyTest,testSwap)201 TEST(AnyTest, testSwap)
202 {
203 NonTrivialNonThrowMove n1(100);
204 Any a1 = n1;
205 Any a2 = 4;
206 a1.Swap(a2);
207 ASSERT_TRUE(AnyCast<int32_t>(a1) == 4);
208 ASSERT_EQ(AnyCast<NonTrivialNonThrowMove>(a2).a_, n1.a_);
209
210 a2 = "test";
211 const Star star("star", 100);
212 a1 = star;
213 a2.Swap(a1);
214 ASSERT_STREQ(AnyCast<const char*>(a1), "test");
215 ASSERT_TRUE(AnyCast<Star>(a2) == star);
216
217 std::swap(a1, a2);
218 ASSERT_STREQ(AnyCast<const char*>(a2), "test");
219 ASSERT_TRUE(AnyCast<Star>(a1) == star);
220 }
221
TEST(AnyTest,testHasValue_Reset)222 TEST(AnyTest, testHasValue_Reset)
223 {
224 Any a;
225 ASSERT_FALSE(a.HasValue());
226 a = "test";
227 ASSERT_TRUE(a.HasValue());
228 a.Reset();
229 ASSERT_FALSE(a.HasValue());
230 }
231 } // namespace Test
232 } // namespace Media
233 } // namespace OHOS