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 30using namespace panda; 31using namespace panda::ecmascript; 32 33namespace panda::test { 34class JSAPILightWeightSetTest : public BaseTestWithScope<false> { 35protected: 36 JSAPILightWeightSet *CreateLightWeightSet() 37 { 38 return EcmaContainerCommon::CreateLightWeightSet(thread); 39 } 40}; 41 42HWTEST_F_L0(JSAPILightWeightSetTest, LightWeightSetCreate) 43{ 44 JSAPILightWeightSet *lightweightSet = CreateLightWeightSet(); 45 EXPECT_TRUE(lightweightSet != nullptr); 46} 47 48HWTEST_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 90HWTEST_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 146HWTEST_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 200HWTEST_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 243HWTEST_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 264HWTEST_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 283HWTEST_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 313HWTEST_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 343HWTEST_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