1 /* 2 * Copyright (c) 2021 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/ecma_string.h" 17 #include "ecmascript/ecma_vm.h" 18 #include "ecmascript/global_env.h" 19 #include "ecmascript/js_function.h" 20 #include "ecmascript/js_handle.h" 21 #include "ecmascript/js_iterator.h" 22 #include "ecmascript/js_object-inl.h" 23 #include "ecmascript/js_set.h" 24 #include "ecmascript/js_set_iterator.h" 25 #include "ecmascript/js_tagged_value.h" 26 #include "ecmascript/linked_hash_table.h" 27 #include "ecmascript/object_factory.h" 28 #include "ecmascript/tagged_hash_table.h" 29 #include "ecmascript/tests/test_helper.h" 30 31 using namespace panda; 32 33 using namespace panda::ecmascript; 34 35 namespace panda::test { 36 class JSSetTest : public testing::Test { 37 public: SetUpTestCase()38 static void SetUpTestCase() 39 { 40 GTEST_LOG_(INFO) << "SetUpTestCase"; 41 } 42 TearDownTestCase()43 static void TearDownTestCase() 44 { 45 GTEST_LOG_(INFO) << "TearDownCase"; 46 } 47 SetUp()48 void SetUp() override 49 { 50 TestHelper::CreateEcmaVMWithScope(instance, thread, scope); 51 } 52 TearDown()53 void TearDown() override 54 { 55 TestHelper::DestroyEcmaVMWithScope(instance, scope); 56 } 57 58 EcmaVM *instance {nullptr}; 59 EcmaHandleScope *scope {nullptr}; 60 JSThread *thread {nullptr}; 61 62 protected: CreateSet()63 JSSet *CreateSet() 64 { 65 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 66 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 67 68 JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction(); 69 JSHandle<JSSet> set = 70 JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor)); 71 JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread); 72 set->SetLinkedSet(thread, hashSet); 73 return JSSet::Cast(set.GetTaggedValue().GetTaggedObject()); 74 } 75 }; 76 HWTEST_F_L0(JSSetTest,SetCreate)77 HWTEST_F_L0(JSSetTest, SetCreate) 78 { 79 JSSet *set = CreateSet(); 80 EXPECT_TRUE(set != nullptr); 81 } 82 HWTEST_F_L0(JSSetTest,AddAndHas)83 HWTEST_F_L0(JSSetTest, AddAndHas) 84 { 85 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 86 // create jsSet 87 JSHandle<JSSet> set(thread, CreateSet()); 88 89 JSHandle<JSTaggedValue> key(factory->NewFromASCII("key")); 90 JSSet::Add(thread, set, key); 91 EXPECT_TRUE(set->Has(key.GetTaggedValue())); 92 } 93 HWTEST_F_L0(JSSetTest,DeleteAndGet)94 HWTEST_F_L0(JSSetTest, DeleteAndGet) 95 { 96 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 97 // create jsSet 98 JSHandle<JSSet> set(thread, CreateSet()); 99 100 // add 40 keys 101 char keyArray[] = "key0"; 102 for (uint32_t i = 0; i < 40; i++) { 103 keyArray[3] = '1' + i; 104 JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyArray)); 105 JSSet::Add(thread, set, key); 106 EXPECT_TRUE(set->Has(key.GetTaggedValue())); 107 } 108 EXPECT_EQ(set->GetSize(), 40); 109 // whether jsSet has delete key 110 keyArray[3] = '1' + 8; 111 JSHandle<JSTaggedValue> deleteKey(factory->NewFromASCII(keyArray)); 112 JSSet::Delete(thread, set, deleteKey); 113 EXPECT_FALSE(set->Has(deleteKey.GetTaggedValue())); 114 EXPECT_EQ(set->GetSize(), 39); 115 } 116 HWTEST_F_L0(JSSetTest,Iterator)117 HWTEST_F_L0(JSSetTest, Iterator) 118 { 119 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 120 JSHandle<JSSet> set(thread, CreateSet()); 121 for (int i = 0; i < 5; i++) { 122 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i)); 123 JSSet::Add(thread, set, key); 124 } 125 126 JSHandle<JSTaggedValue> keyIter(factory->NewJSSetIterator(set, IterationKind::KEY)); 127 JSHandle<JSTaggedValue> valueIter(factory->NewJSSetIterator(set, IterationKind::VALUE)); 128 129 JSHandle<JSTaggedValue> keyResult0 = JSIterator::IteratorStep(thread, keyIter); 130 JSHandle<JSTaggedValue> valueResult0 = JSIterator::IteratorStep(thread, valueIter); 131 132 EXPECT_EQ(0, JSIterator::IteratorValue(thread, keyResult0)->GetInt()); 133 EXPECT_EQ(0, JSIterator::IteratorValue(thread, valueResult0)->GetInt()); 134 135 JSHandle<JSTaggedValue> keyResult1 = JSIterator::IteratorStep(thread, keyIter); 136 EXPECT_EQ(1, JSIterator::IteratorValue(thread, keyResult1)->GetInt()); 137 138 for (int i = 0; i < 3; i++) { 139 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i)); 140 JSSet::Delete(thread, set, key); 141 } 142 143 JSHandle<JSTaggedValue> keyResult2 = JSIterator::IteratorStep(thread, keyIter); 144 EXPECT_EQ(3, JSIterator::IteratorValue(thread, keyResult2)->GetInt()); 145 JSHandle<JSTaggedValue> keyResult3 = JSIterator::IteratorStep(thread, keyIter); 146 EXPECT_EQ(4, JSIterator::IteratorValue(thread, keyResult3)->GetInt()); 147 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(5)); 148 JSSet::Add(thread, set, key); 149 JSHandle<JSTaggedValue> keyResult4 = JSIterator::IteratorStep(thread, keyIter); 150 EXPECT_EQ(5, JSIterator::IteratorValue(thread, keyResult4)->GetInt()); 151 JSHandle<JSTaggedValue> keyResult5 = JSIterator::IteratorStep(thread, keyIter); 152 EXPECT_EQ(JSTaggedValue::False(), keyResult5.GetTaggedValue()); 153 } 154 } // namespace panda::test 155