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/containers/containers_private.h" 17#include "ecmascript/ecma_string.h" 18#include "ecmascript/ecma_vm.h" 19#include "ecmascript/global_env.h" 20#include "ecmascript/js_api/js_api_tree_set.h" 21#include "ecmascript/js_api/js_api_tree_set_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/tagged_tree.h" 29#include "ecmascript/tests/ecma_test_common.h" 30 31using namespace panda; 32 33using namespace panda::ecmascript; 34 35namespace panda::test { 36class JSAPITreeSetTest : public BaseTestWithScope<false> { 37protected: 38 JSAPITreeSet *CreateTreeSet() 39 { 40 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 41 auto result = TestCommon::CreateContainerTaggedValue(thread, containers::ContainerTag::TreeSet); 42 JSHandle<JSTaggedValue> constructor(thread, result); 43 JSHandle<JSAPITreeSet> set(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor)); 44 JSTaggedValue internal = TaggedTreeSet::Create(thread); 45 set->SetTreeSet(thread, internal); 46 return *set; 47 } 48 49 JSHandle<JSAPITreeSet> TestCommon(JSMutableHandle<JSTaggedValue>& key, std::string& myKey, uint32_t nums) 50 { 51 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 52 // test JSAPITreeSet 53 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet()); 54 for (int i = 0; i < nums; i++) { 55 std::string ikey = myKey + std::to_string(i); 56 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 57 JSAPITreeSet::Add(thread, tset, key); 58 } 59 EXPECT_EQ(tset->GetSize(), nums); 60 return tset; 61 } 62}; 63 64HWTEST_F_L0(JSAPITreeSetTest, TreeSetCreate) 65{ 66 JSAPITreeSet *set = CreateTreeSet(); 67 EXPECT_TRUE(set != nullptr); 68} 69 70HWTEST_F_L0(JSAPITreeSetTest, TreeSetAddAndHas) 71{ 72 constexpr int NODE_NUMBERS = 8; 73 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 74 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 75 76 // test JSAPITreeSet 77 std::string myKey("mykey"); 78 auto tset = TestCommon(key, myKey, NODE_NUMBERS); 79 80 // test Add exception 81 key.Update(JSTaggedValue::Hole()); 82 JSAPITreeSet::Add(thread, tset, key); 83 EXPECT_EXCEPTION(); 84 85 for (int i = 0; i < NODE_NUMBERS; i++) { 86 std::string ikey = myKey + std::to_string(i); 87 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 88 89 // test has 90 bool has = JSAPITreeSet::Has(thread, tset, key); 91 EXPECT_EQ(has, true); 92 } 93} 94 95HWTEST_F_L0(JSAPITreeSetTest, TreeSetDeleteAndHas) 96{ 97 constexpr int NODE_NUMBERS = 64; 98 constexpr int REMOVE_SIZE = 48; 99 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 100 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 101 102 // test JSAPITreeSet 103 std::string myKey("mykey"); 104 auto tset = TestCommon(key, myKey, NODE_NUMBERS); 105 106 // test delete 107 { 108 std::string ikey = myKey + std::to_string(NODE_NUMBERS); 109 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 110 bool success = JSAPITreeSet::Delete(thread, tset, key); 111 EXPECT_EQ(success, false); 112 } 113 114 for (int i = 0; i < REMOVE_SIZE; i++) { 115 std::string ikey = myKey + std::to_string(i); 116 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 117 bool success = JSAPITreeSet::Delete(thread, tset, key); 118 EXPECT_EQ(success, true); 119 } 120 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - REMOVE_SIZE); 121 122 for (int i = 0; i < REMOVE_SIZE; i++) { 123 std::string ikey = myKey + std::to_string(i); 124 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 125 126 // test has 127 bool has = JSAPITreeSet::Has(thread, tset, key); 128 EXPECT_EQ(has, false); 129 } 130 131 for (int i = REMOVE_SIZE; i < NODE_NUMBERS; i++) { 132 std::string ikey = myKey + std::to_string(i); 133 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 134 135 // test has 136 bool has = JSAPITreeSet::Has(thread, tset, key); 137 EXPECT_EQ(has, true); 138 } 139} 140 141HWTEST_F_L0(JSAPITreeSetTest, TreeSetClear) 142{ 143 constexpr int NODE_NUMBERS = 8; 144 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 145 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 146 147 // test TaggedTreeSet 148 std::string myKey("mykey"); 149 auto tset = TestCommon(key, myKey, NODE_NUMBERS); 150 151 JSAPITreeSet::Clear(thread, tset); 152 EXPECT_EQ(tset->GetSize(), 0); 153 for (int i = 0; i < NODE_NUMBERS; i++) { 154 std::string ikey = myKey + std::to_string(i); 155 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 156 157 // test has 158 bool has = JSAPITreeSet::Has(thread, tset, key); 159 EXPECT_EQ(has, false); 160 } 161} 162 163HWTEST_F_L0(JSAPITreeSetTest, TreeSetPop) 164{ 165 constexpr int NODE_NUMBERS = 8; 166 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 167 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 168 169 // test TaggedTreeSet 170 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet()); 171 172 // test popFirst and popLast of empty treeset 173 JSTaggedValue fvalue1 = JSAPITreeSet::PopFirst(thread, tset); 174 EXPECT_EQ(fvalue1, JSTaggedValue::Undefined()); 175 JSTaggedValue lvalue1 = JSAPITreeSet::PopFirst(thread, tset); 176 EXPECT_EQ(lvalue1, JSTaggedValue::Undefined()); 177 178 std::string myKey("mykey"); 179 for (int i = 0; i < NODE_NUMBERS; i++) { 180 std::string ikey = myKey + std::to_string(i); 181 key.Update(factory->NewFromStdString(ikey).GetTaggedValue()); 182 JSAPITreeSet::Add(thread, tset, key); 183 } 184 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS); 185 186 // test popFirst 187 std::string fkey = myKey + std::to_string(0); 188 key.Update(factory->NewFromStdString(fkey).GetTaggedValue()); 189 JSTaggedValue fvalue = JSAPITreeSet::PopFirst(thread, tset); 190 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - 1); 191 EXPECT_EQ(fvalue, key.GetTaggedValue()); 192 bool has = JSAPITreeSet::Has(thread, tset, key); 193 EXPECT_EQ(has, false); 194 195 // test popLast 196 std::string lkey = myKey + std::to_string(NODE_NUMBERS - 1); 197 key.Update(factory->NewFromStdString(lkey).GetTaggedValue()); 198 JSTaggedValue lvalue = JSAPITreeSet::PopLast(thread, tset); 199 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - 2); 200 EXPECT_EQ(lvalue, key.GetTaggedValue()); 201 has = JSAPITreeSet::Has(thread, tset, key); 202 EXPECT_EQ(has, false); 203} 204 205HWTEST_F_L0(JSAPITreeSetTest, JSAPITreeSetIterator) 206{ 207 constexpr int NODE_NUMBERS = 8; 208 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 209 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet()); 210 211 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 212 for (int i = 0; i < NODE_NUMBERS; i++) { 213 key.Update(JSTaggedValue(i)); 214 JSAPITreeSet::Add(thread, tset, key); 215 } 216 217 // test key or value 218 JSHandle<JSTaggedValue> keyIter(factory->NewJSAPITreeSetIterator(tset, IterationKind::KEY)); 219 JSHandle<JSTaggedValue> valueIter(factory->NewJSAPITreeSetIterator(tset, IterationKind::VALUE)); 220 JSMutableHandle<JSTaggedValue> keyIterResult(thread, JSTaggedValue::Undefined()); 221 JSMutableHandle<JSTaggedValue> valueIterResult(thread, JSTaggedValue::Undefined()); 222 for (int i = 0; i < NODE_NUMBERS / 2; i++) { 223 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue()); 224 valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue()); 225 EXPECT_EQ(i, JSIterator::IteratorValue(thread, keyIterResult)->GetInt()); 226 EXPECT_EQ(i, JSIterator::IteratorValue(thread, valueIterResult)->GetInt()); 227 } 228 229 // test key and value 230 JSHandle<JSTaggedValue> indexKey(thread, JSTaggedValue(0)); 231 JSHandle<JSTaggedValue> elementKey(thread, JSTaggedValue(1)); 232 JSHandle<JSTaggedValue> iter(factory->NewJSAPITreeSetIterator(tset, IterationKind::KEY_AND_VALUE)); 233 JSMutableHandle<JSTaggedValue> iterResult(thread, JSTaggedValue::Undefined()); 234 JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined()); 235 for (int i = 0; i < NODE_NUMBERS; i++) { 236 iterResult.Update(JSIterator::IteratorStep(thread, iter).GetTaggedValue()); 237 result.Update(JSIterator::IteratorValue(thread, iterResult).GetTaggedValue()); 238 EXPECT_EQ(i, JSObject::GetProperty(thread, result, indexKey).GetValue()->GetInt()); 239 EXPECT_EQ(i, JSObject::GetProperty(thread, result, elementKey).GetValue()->GetInt()); 240 } 241 242 // test delete 243 key.Update(JSTaggedValue(NODE_NUMBERS / 2)); 244 bool success = JSAPITreeSet::Delete(thread, tset, key); 245 EXPECT_EQ(success, true); 246 for (int i = NODE_NUMBERS / 2 + 1; i < NODE_NUMBERS; i++) { 247 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue()); 248 valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue()); 249 EXPECT_EQ(i, JSIterator::IteratorValue(thread, keyIterResult)->GetInt()); 250 EXPECT_EQ(i, JSIterator::IteratorValue(thread, valueIterResult)->GetInt()); 251 } 252 253 // test set 254 key.Update(JSTaggedValue(NODE_NUMBERS)); 255 JSAPITreeSet::Add(thread, tset, key); 256 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue()); 257 EXPECT_EQ(NODE_NUMBERS, JSIterator::IteratorValue(thread, keyIterResult)->GetInt()); 258 259 // test end 260 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue()); 261 EXPECT_EQ(JSTaggedValue::False(), keyIterResult.GetTaggedValue()); 262} 263 264HWTEST_F_L0(JSAPITreeSetTest, TreeSetGetKey) 265{ 266 constexpr int NODE_NUMBERS = 8; 267 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 268 269 // init treeset 270 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet()); 271 for (int i = 0; i < NODE_NUMBERS; i++) { 272 key.Update(JSTaggedValue(i)); 273 JSAPITreeSet::Add(thread, tset, key); 274 } 275 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS); 276 277 // test GetKey 278 for (int i = 0; i < NODE_NUMBERS; i++) { 279 EXPECT_EQ(tset->GetKey(i), JSTaggedValue(i)); 280 } 281 EXPECT_EQ(tset->GetKey(-1), JSTaggedValue::Undefined()); 282} 283} // namespace panda::test 284