1 /*
2 * Copyright (c) 2022 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 "ecmascript/js_api/js_api_lightweightset.h"
17 #include "ecmascript/containers/containers_private.h"
18 #include "ecmascript/ecma_string.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_api/js_api_lightweightset_iterator.h"
22 #include "ecmascript/js_function.h"
23 #include "ecmascript/js_handle.h"
24 #include "ecmascript/js_iterator.h"
25 #include "ecmascript/js_object-inl.h"
26 #include "ecmascript/js_tagged_value.h"
27 #include "ecmascript/object_factory.h"
28 #include "ecmascript/tests/ecma_test_common.h"
29
30 using namespace panda;
31 using namespace panda::ecmascript;
32
33 namespace panda::test {
34 class JSAPILightWeightSetTest : public BaseTestWithScope<false> {
35 protected:
CreateLightWeightSet()36 JSAPILightWeightSet *CreateLightWeightSet()
37 {
38 return EcmaContainerCommon::CreateLightWeightSet(thread);
39 }
40 };
41
HWTEST_F_L0(JSAPILightWeightSetTest,LightWeightSetCreate)42 HWTEST_F_L0(JSAPILightWeightSetTest, LightWeightSetCreate)
43 {
44 JSAPILightWeightSet *lightweightSet = CreateLightWeightSet();
45 EXPECT_TRUE(lightweightSet != nullptr);
46 }
47
HWTEST_F_L0(JSAPILightWeightSetTest,AddIncreaseCapacityAddAll)48 HWTEST_F_L0(JSAPILightWeightSetTest, AddIncreaseCapacityAddAll)
49 {
50 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
51 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
52 JSHandle<JSAPILightWeightSet> srcLws(thread, CreateLightWeightSet());
53 JSHandle<JSAPILightWeightSet> destLws(thread, CreateLightWeightSet());
54 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
55
56 // test IncreaseCapacityTo
57 std::string myValue("myvalue");
58 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
59 bool result = JSAPILightWeightSet::Add(thread, lws, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
60 EXPECT_TRUE(result);
61 }
62 EXPECT_EQ(lws->GetSize(), NODE_NUMBERS);
63
64 uint32_t tmp = NODE_NUMBERS * 2; // 2 means the value
65 JSAPILightWeightSet::IncreaseCapacityTo(thread, lws, static_cast<int32_t>(tmp));
66 uint32_t capacity = TaggedArray::Cast(lws->GetValues().GetTaggedObject())->GetLength();
67 EXPECT_EQ(JSTaggedValue(capacity), JSTaggedValue(tmp));
68
69 // test IncreaseCapacityTo exception
70 JSAPILightWeightSet::IncreaseCapacityTo(thread, lws, 0);
71 EXPECT_EXCEPTION();
72 JSAPILightWeightSet::IncreaseCapacityTo(thread, lws, NODE_NUMBERS);
73 EXPECT_EXCEPTION();
74
75 // test AddAll
76 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
77 bool result = JSAPILightWeightSet::Add(thread, destLws, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
78 EXPECT_TRUE(result);
79 }
80
81 for (uint32_t i = 0; i < NODE_NUMBERS + 2; i++) {
82 JSAPILightWeightSet::Add(thread, srcLws, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
83 }
84 bool result = JSAPILightWeightSet::AddAll(thread, destLws, JSHandle<JSTaggedValue>::Cast(srcLws));
85 EXPECT_TRUE(result);
86 tmp = NODE_NUMBERS + 2; // 2 means the value
87 EXPECT_EQ(destLws->GetSize(), tmp);
88 }
89
HWTEST_F_L0(JSAPILightWeightSetTest,EqualClearNotEqual)90 HWTEST_F_L0(JSAPILightWeightSetTest, EqualClearNotEqual)
91 {
92 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
93 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
94 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
95 JSHandle<JSAPILightWeightSet> equalLws(thread, CreateLightWeightSet());
96 JSHandle<JSTaggedValue> jsArray = JSArray::ArrayCreate(thread, JSTaggedNumber(0));
97 JSMutableHandle<JSTaggedValue> value1(thread, JSTaggedValue::Undefined());
98 JSMutableHandle<JSTaggedValue> value2(thread, JSTaggedValue::Undefined());
99 bool result = false;
100
101 // test Equal of two empty lightweightset
102 result = JSAPILightWeightSet::Equal(thread, lws, JSHandle<JSTaggedValue>::Cast(equalLws));
103 EXPECT_FALSE(result);
104 result = JSAPILightWeightSet::Equal(thread, lws, jsArray);
105 EXPECT_FALSE(result);
106
107 // test equal
108 std::string myValue1("myvalue");
109 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
110 std::string iValue = myValue1 + std::to_string(i);
111 value1.Update(factory->NewFromStdString(iValue).GetTaggedValue());
112 result = JSAPILightWeightSet::Add(thread, lws, value1);
113 EXPECT_TRUE(result);
114 }
115 EXPECT_EQ(lws->GetSize(), NODE_NUMBERS);
116
117 std::string myValue2("myvalue");
118 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
119 std::string iValue = myValue2 + std::to_string(i);
120 value2.Update(factory->NewFromStdString(iValue).GetTaggedValue());
121 result = JSAPILightWeightSet::Add(thread, equalLws, value2);
122 EXPECT_TRUE(result);
123 }
124 EXPECT_EQ(equalLws->GetSize(), NODE_NUMBERS);
125 result = JSAPILightWeightSet::Equal(thread, lws, JSHandle<JSTaggedValue>::Cast(equalLws));
126 EXPECT_FALSE(result);
127
128 equalLws->Clear(thread);
129 EXPECT_EQ(equalLws->GetSize(), static_cast<uint32_t>(0)); // 0 means the value
130
131 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
132 std::string iValue = myValue2 + std::to_string(i);
133 if (i == 2) {
134 LOG_ECMA(ERROR) << " {} " << iValue;
135 } else {
136 value2.Update(factory->NewFromStdString(iValue).GetTaggedValue());
137 result = JSAPILightWeightSet::Add(thread, equalLws, value2);
138 EXPECT_TRUE(result);
139 }
140 }
141 EXPECT_EQ(equalLws->GetSize(), NODE_NUMBERS - 1);
142 result = JSAPILightWeightSet::Equal(thread, lws, JSHandle<JSTaggedValue>::Cast(equalLws));
143 EXPECT_FALSE(result);
144 }
145
HWTEST_F_L0(JSAPILightWeightSetTest,IsEmptyHasHasAll)146 HWTEST_F_L0(JSAPILightWeightSetTest, IsEmptyHasHasAll)
147 {
148 constexpr uint32_t NODE_NUMBERS = 8;
149 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
150 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
151 JSHandle<JSAPILightWeightSet> hasAllLws(thread, CreateLightWeightSet());
152 JSMutableHandle<JSTaggedValue> value1(thread, JSTaggedValue::Undefined());
153 JSMutableHandle<JSTaggedValue> value2(thread, JSTaggedValue::Undefined());
154 JSMutableHandle<JSTaggedValue> value3(thread, JSTaggedValue::Undefined());
155 bool result = false;
156 std::string tValue;
157 // test IsEmpty
158 result = lws->IsEmpty();
159 EXPECT_TRUE(result);
160 // test Has
161 std::string myValue1("myvalue");
162 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
163 std::string iValue = myValue1 + std::to_string(i);
164 value1.Update(factory->NewFromStdString(iValue).GetTaggedValue());
165 result = JSAPILightWeightSet::Add(thread, lws, value1);
166 EXPECT_TRUE(result);
167 }
168 EXPECT_EQ(lws->GetSize(), NODE_NUMBERS);
169
170 tValue = myValue1 + std::to_string(5);
171 value1.Update(factory->NewFromStdString(tValue).GetTaggedValue());
172 result = lws->Has(thread, value1);
173 EXPECT_TRUE(result);
174 tValue = myValue1 + std::to_string(NODE_NUMBERS);
175 value1.Update(factory->NewFromStdString(tValue).GetTaggedValue());
176 result = lws->Has(thread, value1);
177 EXPECT_FALSE(result);
178
179 std::string myValue2("myvalue");
180 for (uint32_t i = 0; i < NODE_NUMBERS - 5; i++) {
181 if (i == 1) {
182 std::string myValue3("destValue");
183 std::string iValue3 = myValue3 + std::to_string(i);
184 value3.Update(factory->NewFromStdString(iValue3).GetTaggedValue());
185 result = JSAPILightWeightSet::Add(thread, hasAllLws, value3);
186 } else {
187 std::string iValue = myValue2 + std::to_string(i);
188 value2.Update(factory->NewFromStdString(iValue).GetTaggedValue());
189 result = JSAPILightWeightSet::Add(thread, hasAllLws, value2);
190 EXPECT_TRUE(result);
191 }
192 }
193 EXPECT_EQ(hasAllLws->GetSize(), NODE_NUMBERS - 5); // 5 means the value
194 result = lws->HasAll(JSHandle<JSTaggedValue>::Cast(hasAllLws));
195 EXPECT_FALSE(result);
196 result = hasAllLws->HasAll(JSHandle<JSTaggedValue>::Cast(lws));
197 EXPECT_FALSE(result);
198 }
199
HWTEST_F_L0(JSAPILightWeightSetTest,GetIndexOfRemoveRemoveAtGetValueAt)200 HWTEST_F_L0(JSAPILightWeightSetTest, GetIndexOfRemoveRemoveAtGetValueAt)
201 {
202 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
203 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
204 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
205 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
206 bool result = false;
207
208 // test GetSize
209 std::string myValue("myvalue");
210 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
211 std::string iValue = myValue + std::to_string(i);
212 value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
213 result = JSAPILightWeightSet::Add(thread, lws, value);
214 }
215 EXPECT_EQ(lws->GetSize(), NODE_NUMBERS);
216
217 // test GetIndexOf
218 std::string tValue("myvalue5");
219 value.Update(factory->NewFromStdString(tValue).GetTaggedValue());
220 int32_t index = lws->GetIndexOf(thread, value);
221 EXPECT_EQ(index, 5); // 5 means the value
222
223 // test GetValueAt
224 JSTaggedValue jsValue = lws->GetValueAt(5); // 5 means the value
225 EXPECT_EQ(value.GetTaggedValue(), jsValue);
226
227 // test Remove
228 jsValue = lws->Remove(thread, value);
229 EXPECT_EQ(value.GetTaggedValue(), jsValue);
230 jsValue = lws->Remove(thread, value);
231 EXPECT_EQ(jsValue, JSTaggedValue::Undefined());
232
233 // test RemoveAt
234 result = lws->RemoveAt(thread, 4); // 4 means the value
235 EXPECT_EQ(lws->GetSize(), NODE_NUMBERS - 2); // 2 means the value
236 EXPECT_TRUE(result);
237 result = lws->RemoveAt(thread, -1);
238 EXPECT_FALSE(result);
239 result = lws->RemoveAt(thread, static_cast<int32_t>(NODE_NUMBERS));
240 EXPECT_FALSE(result);
241 }
242
HWTEST_F_L0(JSAPILightWeightSetTest,Iterator)243 HWTEST_F_L0(JSAPILightWeightSetTest, Iterator)
244 {
245 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
246 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
247 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
248
249 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
250 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
251 value.Update(JSTaggedValue(i));
252 JSAPILightWeightSet::Add(thread, lws, value);
253 }
254
255 JSHandle<JSTaggedValue> valueIter(factory->NewJSAPILightWeightSetIterator(lws, IterationKind::VALUE));
256 JSMutableHandle<JSTaggedValue> valueIterResult(thread, JSTaggedValue::Undefined());
257 for (int i = 0; i < static_cast<int>(NODE_NUMBERS); i++) {
258 valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue());
259 int v = JSIterator::IteratorValue(thread, valueIterResult)->GetInt();
260 EXPECT_TRUE(v == i);
261 }
262 }
263
HWTEST_F_L0(JSAPILightWeightSetTest,RBTreeGetHashIndex)264 HWTEST_F_L0(JSAPILightWeightSetTest, RBTreeGetHashIndex)
265 {
266 std::vector<int> hashCollisionVector = {4307, 5135, 5903, 6603, 6780, 8416, 1224, 1285, 1463, 9401, 9740};
267 uint32_t NODE_NUMBERS = static_cast<uint32_t>(hashCollisionVector.size());
268 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
269
270 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
271 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
272 value.Update(JSTaggedValue(hashCollisionVector[i]));
273 JSAPILightWeightSet::Add(thread, lws, value);
274 }
275 int32_t size = static_cast<uint32_t>(lws->GetLength());
276 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
277 value.Update(JSTaggedValue(hashCollisionVector[i]));
278 int32_t index = lws->GetHashIndex(thread, value, size);
279 EXPECT_TRUE(0 <= index && index < size);
280 }
281 }
282
HWTEST_F_L0(JSAPILightWeightSetTest,SpecialReturnTestEnsureCapacityGetValueAtGetHashAt)283 HWTEST_F_L0(JSAPILightWeightSetTest, SpecialReturnTestEnsureCapacityGetValueAtGetHashAt)
284 {
285 constexpr uint32_t NODE_NUMBERS = 8;
286 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
287
288 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
289 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
290 value.Update(JSTaggedValue(i));
291 JSAPILightWeightSet::Add(thread, lws, value);
292 }
293
294 // test special return of EnsureCapacity
295 JSHandle<TaggedArray> array(thread, lws->GetValues());
296 JSAPILightWeightSet::EnsureCapacity(thread, lws, 0);
297 JSHandle<TaggedArray> newArray(thread, lws->GetValues());
298 EXPECT_TRUE(array->GetLength() == newArray->GetLength());
299
300 // test special return of GetValueAt
301 JSTaggedValue result1 = lws->GetValueAt(-1);
302 EXPECT_EQ(result1, JSTaggedValue::Undefined());
303 JSTaggedValue result2 = lws->GetValueAt(static_cast<int32_t>(NODE_NUMBERS * 2));
304 EXPECT_EQ(result2, JSTaggedValue::Undefined());
305
306 // test special return of GetHashAt
307 JSTaggedValue result3 = lws->GetHashAt(-1);
308 EXPECT_EQ(result3, JSTaggedValue::Undefined());
309 JSTaggedValue result4 = lws->GetHashAt(static_cast<int32_t>(NODE_NUMBERS * 2));
310 EXPECT_EQ(result4, JSTaggedValue::Undefined());
311 }
312
HWTEST_F_L0(JSAPILightWeightSetTest,GetHashAtHasHash)313 HWTEST_F_L0(JSAPILightWeightSetTest, GetHashAtHasHash)
314 {
315 constexpr uint32_t NODE_NUMBERS = 8;
316 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
317
318 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
319 JSMutableHandle<JSTaggedValue> hash(thread, JSTaggedValue::Undefined());
320 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
321 value.Update(JSTaggedValue(i));
322 JSAPILightWeightSet::Add(thread, lws, value);
323 }
324
325 // test GetHashAt
326 int32_t size = static_cast<int32_t>(lws->GetLength());
327 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
328 hash.Update(JSTaggedValue(lws->Hash(thread, JSTaggedValue(i))));
329 int32_t index = lws->GetHashIndex(thread, hash, size);
330 JSTaggedValue getHash= lws->GetHashAt(index);
331 EXPECT_EQ(getHash, hash.GetTaggedValue());
332 }
333
334 // test HasHash
335 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
336 hash.Update(JSTaggedValue(lws->Hash(thread, JSTaggedValue(i))));
337 EXPECT_TRUE(lws->HasHash(hash));
338 }
339 hash.Update(JSTaggedValue(lws->Hash(thread, JSTaggedValue(NODE_NUMBERS))));
340 EXPECT_FALSE(lws->HasHash(hash));
341 }
342
HWTEST_F_L0(JSAPILightWeightSetTest,ToString)343 HWTEST_F_L0(JSAPILightWeightSetTest, ToString)
344 {
345 constexpr uint32_t NODE_NUMBERS = 3;
346 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
347
348 JSHandle<JSAPILightWeightSet> lws(thread, CreateLightWeightSet());
349 JSTaggedValue result1 = JSAPILightWeightSet::ToString(thread, lws);
350 JSHandle<EcmaString> resultHandle1(thread, result1);
351 JSHandle<EcmaString> det = thread->GetEcmaVM()->GetFactory()->NewFromASCII("");
352 ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle1, det), 0);
353 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
354 value.Update(JSTaggedValue(i));
355 JSAPILightWeightSet::Add(thread, lws, value);
356 }
357 JSHandle<EcmaString> str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0,1,2");
358 JSTaggedValue result = JSAPILightWeightSet::ToString(thread, lws);
359 JSHandle<EcmaString> resultHandle(thread, result);
360 ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0);
361 }
362 } // namespace panda::test
363