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 "plugin/common/any.h"
23 
24 using namespace testing::ext;
25 
26 namespace OHOS {
27 namespace Media {
28 namespace Test {
29 using namespace OHOS::Media::Plugin;
CompareFunctionTable(const Any::FunctionTable * ft1,const Any::FunctionTable * ft2)30 bool CompareFunctionTable(const Any::FunctionTable* ft1, const Any::FunctionTable* ft2)
31 {
32 #ifndef HST_ANY_WITH_NO_RTTI
33     return ft1->type == ft2->type && ft1->destroy == ft2->destroy && ft1->getPtr == ft2->getPtr &&
34            ft1->move == ft2->move && ft1->copy == ft2->copy && ft1->getConstPtr == ft2->getConstPtr;
35 #else
36     return ft1->type_name == ft2->type_name && ft1->destroy == ft2->destroy && ft1->getPtr == ft2->getPtr &&
37            ft1->move == ft2->move && ft1->copy == ft2->copy && ft1->getConstPtr == ft2->getConstPtr;
38 #endif
39 }
40 
41 template <typename T, template <class> class U>
UseStorage()42 bool UseStorage()
43 {
44     auto ft1 = Any::GetFunctionTable<T>();
45     Any::FunctionTable ft2 {
46 #ifndef HST_ANY_WITH_NO_RTTI
47         .type = U<T>::Type,
48 #else
49         .type_name = U<T>::TypeName,
50 #endif
51         .destroy = U<T>::Destroy,
52         .copy = U<T>::Copy,
53         .move = U<T>::Move,
54         .getPtr = U<T>::GetPtr,
55         .getConstPtr = U<T>::GetConstPtr
56     };
57     return CompareFunctionTable(ft1, &ft2);
58 }
59 
60 class NonTrivialCopyable {
61 public:
NonTrivialCopyable(uint8_t a)62    explicit NonTrivialCopyable(uint8_t a) : a_(a)
63     {
64     }
NonTrivialCopyable(const NonTrivialCopyable & a)65     NonTrivialCopyable(const NonTrivialCopyable& a) : a_(a.a_)
66     {
67     }
operator =(const NonTrivialCopyable & other)68     NonTrivialCopyable& operator=(const NonTrivialCopyable& other)
69     {
70         if (this != &other) {
71             this->a_ = other.a_;
72         }
73         return *this;
74     }
75     uint8_t a_;
76 };
77 
78 class NonTrivialNonThrowMove {
79 public:
NonTrivialNonThrowMove(uint8_t a)80     explicit NonTrivialNonThrowMove(uint8_t a) : a_(a)
81     {
82     }
NonTrivialNonThrowMove(const NonTrivialNonThrowMove & a)83     explicit NonTrivialNonThrowMove(const NonTrivialNonThrowMove& a) : a_(a.a_)
84     {
85     }
operator =(const NonTrivialNonThrowMove & other)86     NonTrivialNonThrowMove& operator=(const NonTrivialNonThrowMove& other)
87     {
88         if (this != &other) {
89             a_ = other.a_;
90         }
91         return *this;
92     }
NonTrivialNonThrowMove(NonTrivialNonThrowMove && t)93     NonTrivialNonThrowMove(NonTrivialNonThrowMove&& t) noexcept
94     {
95         a_ = t.a_;
96     }
operator =(NonTrivialNonThrowMove && other)97     NonTrivialNonThrowMove& operator=(NonTrivialNonThrowMove&& other)
98     {
99         a_ = other.a_;
100         return *this;
101     }
102     uint8_t a_;
103 };
104 
105 HWTEST(AnyTest, testAnyUseTrivial, TestSize.Level1)
106 {
107     auto tmp = UseStorage<uint8_t, Any::TrivialStackFunctionTable>();
108     ASSERT_TRUE(tmp);
109     tmp = UseStorage<int8_t, Any::TrivialStackFunctionTable>();
110     ASSERT_TRUE(tmp);
111     tmp = UseStorage<uint16_t, Any::TrivialStackFunctionTable>();
112     ASSERT_TRUE(tmp);
113     tmp = UseStorage<int16_t, Any::TrivialStackFunctionTable>();
114     ASSERT_TRUE(tmp);
115     tmp = UseStorage<uint32_t, Any::TrivialStackFunctionTable>();
116     ASSERT_TRUE(tmp);
117     tmp = UseStorage<int32_t, Any::TrivialStackFunctionTable>();
118     ASSERT_TRUE(tmp);
119     tmp = UseStorage<uint64_t, Any::TrivialStackFunctionTable>();
120     ASSERT_TRUE(tmp);
121     tmp = UseStorage<int64_t, Any::TrivialStackFunctionTable>();
122     ASSERT_TRUE(tmp);
123     tmp = UseStorage<NonTrivialCopyable, Any::TrivialStackFunctionTable>();
124     ASSERT_FALSE(tmp);
125 }
126 
127 HWTEST(AnyTest, testAnyUseStack, TestSize.Level1)
128 {
129     auto tmp = UseStorage<NonTrivialCopyable, Any::StackFunctionTable>();
130     ASSERT_FALSE(tmp);
131     tmp = UseStorage<NonTrivialNonThrowMove, Any::StackFunctionTable>();
132     ASSERT_TRUE(tmp);
133     tmp = UseStorage<std::shared_ptr<int>, Any::StackFunctionTable>();
134     ASSERT_TRUE(tmp);
135 }
136 
137 HWTEST(AnyTest, testAnyUseHeap, TestSize.Level1)
138 {
139     auto tmp = UseStorage<NonTrivialCopyable, Any::HeapFunctionTable>();
140     ASSERT_TRUE(tmp);
141 }
142 
143 HWTEST(AnyTest, testAnyCast, TestSize.Level1)
144 {
145     const int number = 12;
146     auto a = Any(number);
147     int* i = AnyCast<int>(&a);
148     ASSERT_TRUE(*i == number);
149     a = std::string("hello");
150     auto& ra = AnyCast<std::string&>(a);
151     ra[1] = 'o';
152     const auto& refString = AnyCast<const std::string&>(a);
153     ASSERT_STREQ(refString.c_str(), "hollo");
154     auto copyString = AnyCast<std::string>(a);
155     copyString[1] = 'l';
156     ASSERT_STREQ(refString.c_str(), "hollo");
157     ASSERT_STREQ(copyString.c_str(), "hlllo");
158 
159     ASSERT_THROW(AnyCast<std::string>("test"), BadAnyCast);
160     ASSERT_THROW(AnyCast<char*>("test"), BadAnyCast);
161 }
162 
163 class Star {
164     std::string name_;
165     int id_;
166 
167 public:
Star(std::string name,int id)168     Star(std::string name, int id) : name_ {std::move(name)}, id_ {id}
169     {
170     }
171 
operator ==(const Star & other) const172     bool operator==(const Star& other) const
173     {
174         return name_ == other.name_ && id_ == other.id_;
175     }
176 };
177 
178 HWTEST(AnyTest, testAnyEmplace, TestSize.Level1)
179 {
180     Any celestial;
181     celestial.Emplace<Star>("Procyon", 2943);
182     Star star1("Procyon", 2943);
183     const auto* star = AnyCast<Star>(&celestial);
184     ASSERT_TRUE(star1 == (*star));
185 
186     Any av;
187     av.Emplace<std::vector<char>>({'C', '+', '+', '1', '7'});
188     const auto* va = AnyCast<std::vector<char>>(&av);
189     std::vector<char> vector1({'C', '+', '+', '1', '7'});
190     ASSERT_TRUE(vector1 == (*va));
191 }
192 
193 HWTEST(AnyTest, testMakeAny, TestSize.Level1)
194 {
195     Star star1("Procyon", 2943);
196     Any celestial = MakeAny<Star, std::string, int32_t>("Procyon", 2943);
197     ASSERT_TRUE(AnyCast<Star>(celestial) == star1);
198 
199     std::vector<char> vector1({'C', '+', '+', '1', '7'});
200     Any av = MakeAny<std::vector<char>>({'C', '+', '+', '1', '7'});
201     ASSERT_TRUE(AnyCast<std::vector<char>>(av) == vector1);
202 }
203 
204 HWTEST(AnyTest, testSwap, TestSize.Level1)
205 {
206     NonTrivialNonThrowMove n1(100);
207     Any a1 = n1;
208     Any a2 = 4;
209     a1.Swap(a2);
210     ASSERT_TRUE(AnyCast<int32_t>(a1) == 4);
211     ASSERT_EQ(AnyCast<NonTrivialNonThrowMove>(a2).a_, n1.a_);
212 
213     a2 = "test";
214     const Star star("star", 100);
215     a1 = star;
216     a2.Swap(a1);
217     ASSERT_STREQ(AnyCast<const char*>(a1), "test");
218     ASSERT_TRUE(AnyCast<Star>(a2) == star);
219 
220     std::swap(a1, a2);
221     ASSERT_STREQ(AnyCast<const char*>(a2), "test");
222     ASSERT_TRUE(AnyCast<Star>(a1) == star);
223 }
224 
225 HWTEST(AnyTest, testHasValue_Reset, TestSize.Level1)
226 {
227     Any a;
228     ASSERT_FALSE(a.HasValue());
229     a = "test";
230     ASSERT_TRUE(a.HasValue());
231     a.Reset();
232     ASSERT_FALSE(a.HasValue());
233 }
234 } // namespace Test
235 } // namespace Media
236 } // namespace OHOS