• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_map.h"
23 #include "ecmascript/js_map_iterator.h"
24 #include "ecmascript/js_object-inl.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 JSMapTest : public BaseTestWithScope<false> {
37 protected:
CreateMap()38     JSMap *CreateMap()
39     {
40         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
41         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
42         JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
43         JSHandle<JSMap> map =
44             JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
45         JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
46         map->SetLinkedMap(thread, hashMap);
47         return *map;
48     }
49 };
50 
HWTEST_F_L0(JSMapTest,MapCreate)51 HWTEST_F_L0(JSMapTest, MapCreate)
52 {
53     JSMap *map = CreateMap();
54     EXPECT_TRUE(map != nullptr);
55 }
56 
HWTEST_F_L0(JSMapTest,AddAndHas)57 HWTEST_F_L0(JSMapTest, AddAndHas)
58 {
59     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
60     // create jsMap
61     JSHandle<JSMap> map(thread, CreateMap());
62 
63     JSHandle<JSTaggedValue> key(factory->NewFromASCII("key"));
64     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
65     JSMap::Set(thread, map, key, value);
66     EXPECT_TRUE(map->Has(thread, key.GetTaggedValue()));
67 }
68 
HWTEST_F_L0(JSMapTest,DeleteAndGet)69 HWTEST_F_L0(JSMapTest, DeleteAndGet)
70 {
71     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
72     // create jsMap
73     JSHandle<JSMap> map(thread, CreateMap());
74 
75     // add 40 keys
76     char keyArray[] = "key0";
77     for (uint32_t i = 0; i < 40; i++) {
78         keyArray[3] = '1' + i;
79         JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyArray));
80         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
81         JSMap::Set(thread, map, key, value);
82         EXPECT_TRUE(map->Has(thread, key.GetTaggedValue()));
83     }
84     EXPECT_EQ(map->GetSize(thread), 40);
85     // whether jsMap has delete key
86     keyArray[3] = '1' + 8;
87     JSHandle<JSTaggedValue> deleteKey(factory->NewFromASCII(keyArray));
88     EXPECT_EQ(map->GetValue(thread, 8), JSTaggedValue(8));
89     JSMap::Delete(thread, map, deleteKey);
90     EXPECT_FALSE(map->Has(thread, deleteKey.GetTaggedValue()));
91     EXPECT_EQ(map->GetSize(thread), 39);
92 }
93 
HWTEST_F_L0(JSMapTest,DeleteAndGet2)94 HWTEST_F_L0(JSMapTest, DeleteAndGet2)
95 {
96     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
97     // create jsMap
98     JSHandle<JSMap> map(thread, CreateMap());
99     JSHandle<JSTaggedValue> mapvalue(map);
100     JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(10);
101     int pointArr[10];
102     for (uint32_t i = 0; i < 10; i++) {
103         JSHandle<JSObject> obj = factory->NewEmptyJSObject(0);
104         auto *nativePointer = pointArr + i;
105         JSHandle<JSNativePointer> pointer = factory->NewJSNativePointer(nativePointer);
106         Barriers::SetObject<true>(thread, *obj, ECMAObject::HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
107         taggedArray->Set(thread, i, obj);
108     }
109     thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC);
110     JSHandle<JSTaggedValue> setfunc =
111         JSObject::GetProperty(thread, mapvalue, thread->GlobalConstants()->GetHandledSetString()).GetValue();
112     JSHandle<JSTaggedValue> getfunc = thread->GetGlobalEnv()->GetMapGet();
113     JSHandle<JSTaggedValue> deletefunc = thread->GetGlobalEnv()->GetMapDelete();
114 
115     for (int i = 0; i < 10; i++) {
116         JSHandle<JSTaggedValue> key(thread, taggedArray->Get(thread, i));
117         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
118         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
119         ecmaRuntimeCallInfo->SetFunction(setfunc.GetTaggedValue());
120         ecmaRuntimeCallInfo->SetThis(map.GetTaggedValue());
121         ecmaRuntimeCallInfo->SetCallArg(key.GetTaggedValue(), value.GetTaggedValue());
122         auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
123         JSFunction::Call(ecmaRuntimeCallInfo);
124         TestHelper::TearDownFrame(thread, prev);
125         JSTaggedValue hashField =
126             JSTaggedValue(Barriers::GetTaggedValue(thread, key->GetTaggedObject(), ECMAObject::HASH_OFFSET));
127         EXPECT_TRUE(hashField.IsTaggedArray());
128     }
129     thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC);
130     for (int i = 0; i < 10; i++) {
131         JSHandle<JSTaggedValue> key(thread, taggedArray->Get(thread, i));
132         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
133         ecmaRuntimeCallInfo->SetFunction(getfunc.GetTaggedValue());
134         ecmaRuntimeCallInfo->SetThis(map.GetTaggedValue());
135         ecmaRuntimeCallInfo->SetCallArg(key.GetTaggedValue());
136         auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
137         auto res = JSFunction::Call(ecmaRuntimeCallInfo);
138         EXPECT_TRUE(res.GetInt() == i);
139         TestHelper::TearDownFrame(thread, prev);
140         JSTaggedValue hashField =
141             JSTaggedValue(Barriers::GetTaggedValue(thread, key->GetTaggedObject(), ECMAObject::HASH_OFFSET));
142         EXPECT_TRUE(hashField.IsTaggedArray());
143     }
144     thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC);
145     for (int i = 0; i < 10; i++) {
146         JSHandle<JSTaggedValue> key(thread, taggedArray->Get(thread, i));
147         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
148         ecmaRuntimeCallInfo->SetFunction(deletefunc.GetTaggedValue());
149         ecmaRuntimeCallInfo->SetThis(map.GetTaggedValue());
150         ecmaRuntimeCallInfo->SetCallArg(key.GetTaggedValue());
151         auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
152         auto res = JSFunction::Call(ecmaRuntimeCallInfo);
153         EXPECT_TRUE(res.IsTrue());
154         TestHelper::TearDownFrame(thread, prev);
155         JSTaggedValue hashField =
156             JSTaggedValue(Barriers::GetTaggedValue(thread, key->GetTaggedObject(), ECMAObject::HASH_OFFSET));
157         EXPECT_TRUE(hashField.IsTaggedArray());
158     }
159 }
160 
HWTEST_F_L0(JSMapTest,Iterator)161 HWTEST_F_L0(JSMapTest, Iterator)
162 {
163     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
164 
165     JSHandle<JSMap> map(thread, CreateMap());
166     for (int i = 0; i < 5; i++) {
167         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
168         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i + 10));
169         JSMap::Set(thread, map, key, value);
170     }
171 
172     JSHandle<JSTaggedValue> keyIter(factory->NewJSMapIterator(map, IterationKind::KEY));
173     JSHandle<JSTaggedValue> valueIter(factory->NewJSMapIterator(map, IterationKind::VALUE));
174     JSHandle<JSTaggedValue> iter(factory->NewJSMapIterator(map, IterationKind::KEY_AND_VALUE));
175 
176     JSHandle<JSTaggedValue> indexKey(thread, JSTaggedValue(0));
177     JSHandle<JSTaggedValue> elementKey(thread, JSTaggedValue(1));
178 
179     JSHandle<JSTaggedValue> keyResult0 = JSIterator::IteratorStep(thread, keyIter);
180     JSHandle<JSTaggedValue> valueResult0 = JSIterator::IteratorStep(thread, valueIter);
181     JSHandle<JSTaggedValue> result0 = JSIterator::IteratorStep(thread, iter);
182 
183     EXPECT_EQ(0, JSIterator::IteratorValue(thread, keyResult0)->GetInt());
184     EXPECT_EQ(10, JSIterator::IteratorValue(thread, valueResult0)->GetInt());
185     JSHandle<JSTaggedValue> result0Handle = JSIterator::IteratorValue(thread, result0);
186     EXPECT_EQ(0, JSObject::GetProperty(thread, result0Handle, indexKey).GetValue()->GetInt());
187     EXPECT_EQ(10, JSObject::GetProperty(thread, result0Handle, elementKey).GetValue()->GetInt());
188 
189     JSHandle<JSTaggedValue> keyResult1 = JSIterator::IteratorStep(thread, keyIter);
190     EXPECT_EQ(1, JSIterator::IteratorValue(thread, keyResult1)->GetInt());
191     for (int i = 0; i < 3; i++) {
192         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
193         JSMap::Delete(thread, map, key);
194     }
195     JSHandle<JSTaggedValue> keyResult2 = JSIterator::IteratorStep(thread, keyIter);
196     EXPECT_EQ(3, JSIterator::IteratorValue(thread, keyResult2)->GetInt());
197     JSHandle<JSTaggedValue> keyResult3 = JSIterator::IteratorStep(thread, keyIter);
198     EXPECT_EQ(4, JSIterator::IteratorValue(thread, keyResult3)->GetInt());
199     JSHandle<JSTaggedValue> key(thread, JSTaggedValue(5));
200     JSMap::Set(thread, map, key, key);
201     JSHandle<JSTaggedValue> keyResult4 = JSIterator::IteratorStep(thread, keyIter);
202 
203     EXPECT_EQ(5, JSIterator::IteratorValue(thread, keyResult4)->GetInt());
204     JSHandle<JSTaggedValue> keyResult5 = JSIterator::IteratorStep(thread, keyIter);
205     EXPECT_EQ(JSTaggedValue::False(), keyResult5.GetTaggedValue());
206 }
207 }  // namespace panda::test
208