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