1 /*
2  * Copyright (c) 2023 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 #include "traits.h"
16 
17 #include <gtest/gtest.h>
18 using namespace testing::ext;
19 namespace OHOS::Test {
20 class TraitsTest : public testing::Test {
21 public:
22     class From {
23     public:
From()24         From() {}
25     };
26     class Convertible {
27     public:
28         // Convertible is auto convert type, do not add explicit to stop the type convert.
Convertible(const From &)29         Convertible(const From &) {};
Convertible()30         Convertible() {}
Convertible(Convertible &&)31         Convertible(Convertible &&) noexcept {};
operator =(Convertible &&)32         Convertible &operator=(Convertible &&) noexcept
33         {
34             return *this;
35         }
36         operator From()
37         {
38             return From();
39         }
40     };
SetUpTestCase(void)41     static void SetUpTestCase(void){};
TearDownTestCase(void)42     static void TearDownTestCase(void){};
SetUp()43     void SetUp(){};
TearDown()44     void TearDown() {}
45 };
46 
47 /**
48 * @tc.name: same_index_of_v
49 * @tc.desc:
50 * @tc.type: FUNC
51 * @tc.require:
52 * @tc.author: Sven Wang
53 */
54 HWTEST_F(TraitsTest, same_index_of_v, TestSize.Level0)
55 {
56     auto index = Traits::same_index_of_v<int32_t, int32_t, double, std::vector<uint8_t>>;
57     ASSERT_EQ(index, 0);
58     index = Traits::same_index_of_v<std::string, int32_t, double, std::vector<uint8_t>>;
59     ASSERT_EQ(index, 3);
60     index = Traits::same_index_of_v<std::string>;
61     ASSERT_EQ(index, 0);
62 }
63 
64 /**
65 * @tc.name: same_in_v
66 * @tc.desc:
67 * @tc.type: FUNC
68 * @tc.require:
69 * @tc.author: Sven Wang
70 */
71 HWTEST_F(TraitsTest, same_in_v, TestSize.Level0)
72 {
73     auto exist = Traits::same_in_v<int32_t, int32_t, double, std::vector<uint8_t>>;
74     ASSERT_TRUE(exist);
75     exist = Traits::same_in_v<std::string, int32_t, double, std::vector<uint8_t>>;
76     ASSERT_FALSE(exist);
77     exist = Traits::same_in_v<std::string>;
78     ASSERT_FALSE(exist);
79 }
80 
81 /**
82 * @tc.name: convertible_index_of_v
83 * @tc.desc:
84 * @tc.type: FUNC
85 * @tc.require:
86 * @tc.author: Sven Wang
87 */
88 HWTEST_F(TraitsTest, convertible_index_of_v, TestSize.Level0)
89 {
90     auto index = Traits::convertible_index_of_v<int32_t, int16_t, double, std::vector<uint8_t>>;
91     ASSERT_EQ(index, 0);
92     index = Traits::convertible_index_of_v<std::string, int16_t, const char *, std::vector<uint8_t>>;
93     ASSERT_EQ(index, 1);
94     index = Traits::convertible_index_of_v<std::string, int16_t, std::vector<uint8_t>>;
95     ASSERT_EQ(index, 2);
96     index = Traits::convertible_index_of_v<std::string>;
97     ASSERT_EQ(index, 0);
98 }
99 
100 /**
101 * @tc.name: convertible_in_v
102 * @tc.desc:
103 * @tc.type: FUNC
104 * @tc.require:
105 * @tc.author: Sven Wang
106 */
107 HWTEST_F(TraitsTest, convertible_in_v, TestSize.Level0)
108 {
109     auto convertible = Traits::convertible_in_v<int32_t, int16_t, double, std::vector<uint8_t>>;
110     ASSERT_TRUE(convertible);
111     convertible = Traits::convertible_in_v<std::string, int16_t, const char *, std::vector<uint8_t>>;
112     ASSERT_TRUE(convertible);
113     convertible = Traits::convertible_in_v<std::string, int16_t, std::vector<uint8_t>>;
114     ASSERT_FALSE(convertible);
115     convertible = Traits::convertible_in_v<std::string>;
116     ASSERT_FALSE(convertible);
117 }
118 
119 /**
120 * @tc.name: variant_size_of_v
121 * @tc.desc:
122 * @tc.type: FUNC
123 * @tc.require:
124 * @tc.author: Sven Wang
125 */
126 HWTEST_F(TraitsTest, variant_size_of_v, TestSize.Level0)
127 {
128     std::variant<std::monostate, int64_t, bool, double, std::string, std::vector<uint8_t>> value;
129     auto size = Traits::variant_size_of_v<decltype(value)>;
130     ASSERT_EQ(size, 6);
131     std::variant<int64_t> value2;
132     size = Traits::variant_size_of_v<decltype(value2)>;
133     ASSERT_EQ(size, 1);
134 }
135 
136 /**
137 * @tc.name: variant_index_of_v
138 * @tc.desc:
139 * @tc.type: FUNC
140 * @tc.require:
141 * @tc.author: Sven Wang
142 */
143 HWTEST_F(TraitsTest, variant_index_of_v, TestSize.Level0)
144 {
145     std::variant<std::monostate, int64_t, bool, double, std::string, std::vector<uint8_t>> value;
146     auto index = Traits::variant_index_of_v<std::monostate, decltype(value)>;
147     ASSERT_EQ(index, 0);
148     index = Traits::variant_index_of_v<int64_t, decltype(value)>;
149     ASSERT_EQ(index, 1);
150     index = Traits::variant_index_of_v<bool, decltype(value)>;
151     ASSERT_EQ(index, 2);
152     index = Traits::variant_index_of_v<double, decltype(value)>;
153     ASSERT_EQ(index, 3);
154     index = Traits::variant_index_of_v<std::string, decltype(value)>;
155     ASSERT_EQ(index, 4);
156     index = Traits::variant_index_of_v<std::vector<uint8_t>, decltype(value)>;
157     ASSERT_EQ(index, 5);
158     index = Traits::variant_index_of_v<char *, decltype(value)>;
159     ASSERT_EQ(index, 6);
160 }
161 
162 /**
163 * @tc.name: get_if_same_type
164 * @tc.desc:
165 * @tc.type: FUNC
166 * @tc.require:
167 * @tc.author: Sven Wang
168 */
169 HWTEST_F(TraitsTest, get_if_same_type, TestSize.Level0)
170 {
171     // 1. When the _Tp is a type in the ..._Types, the get_if is equal to the std::get_if.
172     std::variant<std::monostate, int64_t, double, const char *> value;
173     auto *nil = Traits::get_if<std::monostate>(&value);
174     ASSERT_NE(nil, nullptr);
175     auto *number = Traits::get_if<int64_t>(&value);
176     ASSERT_EQ(number, nullptr);
177     value = int64_t(1);
178     number = Traits::get_if<int64_t>(&value);
179     ASSERT_NE(number, nullptr);
180     ASSERT_EQ(*number, 1);
181     value = 1.5;
182     auto *dVal = Traits::get_if<double>(&value);
183     ASSERT_NE(dVal, nullptr);
184     ASSERT_DOUBLE_EQ(*dVal, 1.5);
185     value = "test case";
186     auto *charPtr = Traits::get_if<const char *>(&value);
187     ASSERT_NE(charPtr, nullptr);
188     ASSERT_TRUE(strcmp(*charPtr, "test case") == 0);
189 }
190 /**
191 * @tc.name: get_if_convertible_type
192 * @tc.desc:
193 * @tc.type: FUNC
194 * @tc.require:
195 * @tc.author: Sven Wang
196 */
197 HWTEST_F(TraitsTest, get_if_convertible_type, TestSize.Level0)
198 {
199     // 2. When the _Tp is not a type in the ..._Types but someone in the ...Types can convert to _Tp implicitly,
200     //    the get_if will return it.
201     std::variant<std::monostate, int64_t, double, const char *, From> value;
202     value = int64_t(1);
203     auto *fVal = Traits::get_if<double>(&value);
204     ASSERT_EQ(fVal, nullptr);
205 
206     value = "test case";
207     auto *strVal = Traits::get_if<std::string>(&value);
208     ASSERT_NE(strVal, nullptr);
209     ASSERT_TRUE(strcmp(*strVal, "test case") == 0);
210 
211     value = From();
212     auto *toVal = Traits::get_if<Convertible>(&value);
213     ASSERT_NE(toVal, nullptr);
214 
215     std::variant<std::monostate, int64_t, double, const char *, Convertible> val2;
216     val2 = Convertible();
217     auto *fromVal = Traits::get_if<From>(&val2);
218     ASSERT_NE(fromVal, nullptr);
219 }
220 
221 /**
222 * @tc.name: get_if_invalid_type
223 * @tc.desc:
224 * @tc.type: FUNC
225 * @tc.require:
226 * @tc.author: Sven Wang
227 */
228 HWTEST_F(TraitsTest, get_if_invalid_type, TestSize.Level0)
229 {
230     // 3. When the _Tp is not a type in the ..._Types and can't convert, the get_if will return nullptr.
231     std::variant<std::monostate, int64_t, double, const char *> value;
232     auto *unknown = Traits::get_if<std::vector<uint8_t>>(&value);
233     ASSERT_EQ(unknown, nullptr);
234     value = int64_t(9);
235     unknown = Traits::get_if<std::vector<uint8_t>>(&value);
236     ASSERT_EQ(unknown, nullptr);
237     value = 1.5;
238     unknown = Traits::get_if<std::vector<uint8_t>>(&value);
239     ASSERT_EQ(unknown, nullptr);
240     value = "test case";
241     unknown = Traits::get_if<std::vector<uint8_t>>(&value);
242     ASSERT_EQ(unknown, nullptr);
243 }
244 } // namespace OHOS::Test
245