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/builtins/builtins_weak_set.h" 17 18#include "ecmascript/ecma_string.h" 19#include "ecmascript/ecma_vm.h" 20#include "ecmascript/global_env.h" 21#include "ecmascript/js_array.h" 22#include "ecmascript/js_handle.h" 23#include "ecmascript/js_hclass.h" 24#include "ecmascript/js_object-inl.h" 25#include "ecmascript/js_set_iterator.h" 26#include "ecmascript/js_tagged_value.h" 27#include "ecmascript/js_thread.h" 28#include "ecmascript/js_weak_container.h" 29#include "ecmascript/object_factory.h" 30#include "ecmascript/tests/test_helper.h" 31 32using namespace panda::ecmascript; 33using namespace panda::ecmascript::builtins; 34 35namespace panda::test { 36using BuiltinsWeakSet = ecmascript::builtins::BuiltinsWeakSet; 37using JSWeakSet = ecmascript::JSWeakSet; 38 39class BuiltinsWeakSetTest : public BaseTestWithScope<false> { 40}; 41 42static JSObject *JSObjectTestCreate(JSThread *thread) 43{ 44 [[maybe_unused]] EcmaHandleScope scope(thread); 45 EcmaVM *ecmaVM = thread->GetEcmaVM(); 46 JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv(); 47 JSHandle<JSTaggedValue> jsFunc = globalEnv->GetObjectFunction(); 48 JSHandle<JSObject> newObj = 49 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc), jsFunc); 50 return *newObj; 51} 52 53JSWeakSet *CreateBuiltinsWeakSet(JSThread *thread) 54{ 55 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 56 JSHandle<JSFunction> newTarget(env->GetBuiltinsWeakSetFunction()); 57 58 // 4 : test case 59 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 4); 60 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue()); 61 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); 62 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 63 JSTaggedValue result = BuiltinsWeakSet::WeakSetConstructor(ecmaRuntimeCallInfo); 64 TestHelper::TearDownFrame(thread, prev); 65 66 EXPECT_TRUE(result.IsECMAObject()); 67 JSWeakSet *jsWeakSet = JSWeakSet::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData())); 68 return jsWeakSet; 69} 70 71HWTEST_F_L0(BuiltinsWeakSetTest, CreateAndGetSize) 72{ 73 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 74 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 75 JSHandle<JSFunction> newTarget(env->GetBuiltinsWeakSetFunction()); 76 JSHandle<JSWeakSet> weakSet(thread, CreateBuiltinsWeakSet(thread)); 77 78 JSHandle<TaggedArray> array(factory->NewTaggedArray(5)); 79 for (int i = 0; i < 5; i++) { 80 JSHandle<JSTaggedValue> key(thread, JSObjectTestCreate(thread)); 81 array->Set(thread, i, key.GetTaggedValue()); 82 } 83 84 JSHandle<JSArray> values = JSArray::CreateArrayFromList(thread, array); 85 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); 86 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue()); 87 ecmaRuntimeCallInfo->SetThis(weakSet.GetTaggedValue()); 88 ecmaRuntimeCallInfo->SetCallArg(0, values.GetTaggedValue()); 89 ecmaRuntimeCallInfo->SetNewTarget(newTarget.GetTaggedValue()); 90 91 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 92 93 JSTaggedValue result1 = BuiltinsWeakSet::WeakSetConstructor(ecmaRuntimeCallInfo); 94 TestHelper::TearDownFrame(thread, prev); 95 JSHandle<JSWeakSet> weakSetResult(thread, 96 JSWeakSet::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData()))); 97 EXPECT_EQ(weakSetResult->GetSize(), 5); 98} 99 100HWTEST_F_L0(BuiltinsWeakSetTest, AddAndHas) 101{ 102 // create jsWeakSet 103 JSHandle<JSWeakSet> weakSet(thread, CreateBuiltinsWeakSet(thread)); 104 JSHandle<JSTaggedValue> key(thread, JSObjectTestCreate(thread)); 105 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); 106 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); 107 ecmaRuntimeCallInfo->SetThis(weakSet.GetTaggedValue()); 108 ecmaRuntimeCallInfo->SetCallArg(0, key.GetTaggedValue()); 109 110 JSWeakSet *jsWeakSet; 111 { 112 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 113 JSTaggedValue result1 = BuiltinsWeakSet::Has(ecmaRuntimeCallInfo); 114 TestHelper::TearDownFrame(thread, prev); 115 116 EXPECT_EQ(result1.GetRawData(), JSTaggedValue::False().GetRawData()); 117 118 // test Add() 119 JSTaggedValue result2 = BuiltinsWeakSet::Add(ecmaRuntimeCallInfo); 120 EXPECT_TRUE(result2.IsECMAObject()); 121 jsWeakSet = JSWeakSet::Cast(reinterpret_cast<TaggedObject *>(result2.GetRawData())); 122 EXPECT_EQ(jsWeakSet->GetSize(), 1); 123 } 124 125 // test Has() 126 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); 127 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); 128 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(jsWeakSet)); 129 ecmaRuntimeCallInfo1->SetCallArg(0, key.GetTaggedValue()); 130 { 131 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); 132 JSTaggedValue result3 = BuiltinsWeakSet::Has(ecmaRuntimeCallInfo1); 133 TestHelper::TearDownFrame(thread, prev); 134 135 EXPECT_EQ(result3.GetRawData(), JSTaggedValue::True().GetRawData()); 136 } 137} 138 139void AddCommon(JSThread* thread, JSHandle<JSWeakSet>& weakSet, JSHandle<JSTaggedValue>& key, int i) 140{ 141 auto ecmaRuntimeCallInfo = 142 TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means 1 call arg 143 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); 144 ecmaRuntimeCallInfo->SetThis(weakSet.GetTaggedValue()); 145 ecmaRuntimeCallInfo->SetCallArg(0, key.GetTaggedValue()); 146 147 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 148 // add 149 JSTaggedValue result1 = BuiltinsWeakSet::Add(ecmaRuntimeCallInfo); 150 TestHelper::TearDownFrame(thread, prev); 151 152 EXPECT_TRUE(result1.IsECMAObject()); 153 JSWeakSet *jsWeakSet = JSWeakSet::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData())); 154 EXPECT_EQ(jsWeakSet->GetSize(), i + 1); 155} 156 157void HasAndDeleteCommon(JSThread* thread, JSHandle<JSWeakSet>& weakSet, JSTaggedValue& lastKey) 158{ 159 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); 160 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); 161 ecmaRuntimeCallInfo1->SetThis(weakSet.GetTaggedValue()); 162 ecmaRuntimeCallInfo1->SetCallArg(0, lastKey); 163 164 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); 165 JSTaggedValue result2 = BuiltinsWeakSet::Has(ecmaRuntimeCallInfo1); 166 TestHelper::TearDownFrame(thread, prev); 167 168 EXPECT_EQ(result2.GetRawData(), JSTaggedValue::True().GetRawData()); 169 170 // delete 171 JSTaggedValue result3 = BuiltinsWeakSet::Delete(ecmaRuntimeCallInfo1); 172 173 EXPECT_EQ(result3.GetRawData(), JSTaggedValue::True().GetRawData()); 174 175 // check deleteKey is deleted 176 JSTaggedValue result4 = BuiltinsWeakSet::Has(ecmaRuntimeCallInfo1); 177 178 EXPECT_EQ(result4.GetRawData(), JSTaggedValue::False().GetRawData()); 179} 180 181HWTEST_F_L0(BuiltinsWeakSetTest, DeleteAndRemove) 182{ 183 // create jsSet 184 JSHandle<JSWeakSet> weakSet(thread, CreateBuiltinsWeakSet(thread)); 185 186 // add 40 keys 187 JSTaggedValue lastKey(JSTaggedValue::Undefined()); 188 for (int i = 0; i < 40; i++) { 189 JSHandle<JSTaggedValue> key(thread, JSObjectTestCreate(thread)); 190 191 AddCommon(thread, weakSet, key, i); 192 lastKey = key.GetTaggedValue(); 193 } 194 // whether jsWeakSet has delete lastKey 195 196 HasAndDeleteCommon(thread, weakSet, lastKey); 197} 198 199HWTEST_F_L0(BuiltinsWeakSetTest, SymbolKey) 200{ 201 // create jsSet 202 JSHandle<JSWeakSet> weakSet(thread, CreateBuiltinsWeakSet(thread)); 203 204 // add 2 keys 205 JSTaggedValue lastKey(JSTaggedValue::Undefined()); 206 for (int i = 0; i < 2; i++) { 207 JSHandle<JSSymbol> symbolKey = thread->GetEcmaVM()->GetFactory()->NewJSSymbol(); 208 JSHandle<JSTaggedValue> key(symbolKey); 209 210 AddCommon(thread, weakSet, key, i); 211 lastKey = key.GetTaggedValue(); 212 } 213 // whether jsWeakSet has delete lastKey 214 215 HasAndDeleteCommon(thread, weakSet, lastKey); 216} 217} // namespace panda::test 218