1/*
2 * Copyright (c) 2024 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#include <fcntl.h>
16#include <unistd.h>
17#include <chrono>
18#include "ecmascript/dfx/hprof/heap_snapshot.h"
19#include "ecmascript/dfx/hprof/heap_profiler.h"
20#include "ecmascript/dfx/hprof/heap_root_visitor.h"
21#include "ecmascript/global_env.h"
22#include "ecmascript/jspandafile/js_pandafile_manager.h"
23#include "ecmascript/js_api/js_api_arraylist.h"
24#include "ecmascript/js_api/js_api_arraylist_iterator.h"
25#include "ecmascript/js_api/js_api_deque.h"
26#include "ecmascript/js_api/js_api_hashmap.h"
27#include "ecmascript/js_api/js_api_hashset.h"
28#include "ecmascript/js_api/js_api_lightweightmap.h"
29#include "ecmascript/js_api/js_api_lightweightset.h"
30#include "ecmascript/js_api/js_api_linked_list.h"
31#include "ecmascript/js_api/js_api_list.h"
32#include "ecmascript/js_api/js_api_plain_array.h"
33#include "ecmascript/js_api/js_api_queue.h"
34#include "ecmascript/js_api/js_api_stack.h"
35#include "ecmascript/js_api/js_api_tree_map.h"
36#include "ecmascript/js_api/js_api_tree_set.h"
37#include "ecmascript/js_api/js_api_vector.h"
38#include "ecmascript/js_date.h"
39#include "ecmascript/js_iterator.h"
40#include "ecmascript/js_map.h"
41#include "ecmascript/js_primitive_ref.h"
42#include "ecmascript/js_promise.h"
43#include "ecmascript/js_regexp.h"
44#include "ecmascript/js_set.h"
45#include "ecmascript/js_string_iterator.h"
46#include "ecmascript/js_typed_array.h"
47#include "ecmascript/js_weak_container.h"
48#include "ecmascript/linked_hash_table.h"
49#include "ecmascript/napi/include/jsnapi.h"
50#include "ecmascript/shared_objects/js_shared_array.h"
51#include "ecmascript/shared_objects/js_shared_map.h"
52#include "ecmascript/shared_objects/js_shared_set.h"
53#include "ecmascript/tagged_hash_array.h"
54#include "ecmascript/tagged_tree.h"
55#include "ecmascript/tests/test_helper.h"
56
57namespace panda::test {
58using namespace panda::ecmascript;
59using ErrorType = base::ErrorType;
60
61class HeapDumpTest : public testing::Test {
62public:
63    void SetUp() override
64    {
65        TestHelper::CreateEcmaVMWithScope(ecmaVm_, thread_, scope_);
66        ecmaVm_->SetEnableForceGC(false);
67    }
68
69    void TearDown() override
70    {
71        TestHelper::DestroyEcmaVMWithScope(ecmaVm_, scope_);
72    }
73
74    EcmaVM *ecmaVm_ {nullptr};
75    EcmaHandleScope *scope_ {nullptr};
76    JSThread *thread_ {nullptr};
77};
78
79class HeapDumpTestHelper {
80public:
81    explicit HeapDumpTestHelper(EcmaVM *vm) : instance(vm) {}
82
83    ~HeapDumpTestHelper()
84    {
85        HeapProfilerInterface::Destroy(instance);
86    }
87
88    size_t GenerateSnapShot(const std::string &filePath)
89    {
90        // first generate this file of filePath if not exist,
91        // so the function `realpath` of FileStream can not failed on arm/arm64.
92        fstream outputString(filePath, std::ios::out);
93        outputString.close();
94        outputString.clear();
95        FileStream stream(filePath.c_str());
96        HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
97        DumpSnapShotOption dumpOption;
98        dumpOption.dumpFormat = DumpFormat::JSON;
99        heapProfile->DumpHeapSnapshot(&stream, dumpOption);
100        return heapProfile->GetIdCount();
101    }
102
103    bool GenerateRawHeapSnashot(const std::string &filePath)
104    {
105        HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
106        DumpSnapShotOption dumpOption;
107        dumpOption.dumpFormat = DumpFormat::BINARY;
108        dumpOption.isDumpOOM = true;
109        fstream outputString(filePath, std::ios::out);
110        outputString.close();
111        outputString.clear();
112        int fd = open(filePath.c_str(), O_RDWR | O_CREAT);
113        FileDescriptorStream stream(fd);
114        auto ret = heapProfile->DumpHeapSnapshot(&stream, dumpOption);
115        stream.EndOfStream();
116        return ret;
117    }
118
119    bool DecodeRawHeapSnashot(std::string &inputPath, std::string &outputPath)
120    {
121        HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
122        fstream outputString(outputPath, std::ios::out);
123        outputString.close();
124        outputString.clear();
125        auto ret = heapProfile->GenerateHeapSnapshot(inputPath, outputPath);
126        return ret;
127    }
128
129    bool MatchHeapDumpString(const std::string &filePath, std::string targetStr)
130    {
131        std::string line;
132        std::ifstream inputStream(filePath);
133        std::size_t lineNum = 0;
134        while (getline(inputStream, line)) {
135            lineNum = line.find(targetStr);
136            if (lineNum != line.npos) {
137                return true;
138            }
139        }
140        GTEST_LOG_(INFO) << "_______________" << targetStr << std::to_string(lineNum) <<"_______________ not found";
141        return false;  // Lost the Line
142    }
143
144    JSHandle<JSTypedArray> CreateNumberTypedArray(JSType jsType)
145    {
146        JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
147        ObjectFactory *factory = instance->GetFactory();
148        JSHandle<JSTaggedValue> handleTagValFunc = env->GetInt8ArrayFunction();
149        switch (jsType) {
150            case JSType::JS_INT8_ARRAY:
151                break;
152            case JSType::JS_UINT8_ARRAY:
153                handleTagValFunc = env->GetUint8ArrayFunction();
154                break;
155            case JSType::JS_UINT8_CLAMPED_ARRAY:
156                handleTagValFunc = env->GetUint8ClampedArrayFunction();
157                break;
158            case JSType::JS_INT16_ARRAY:
159                handleTagValFunc = env->GetInt16ArrayFunction();
160                break;
161            case JSType::JS_UINT16_ARRAY:
162                handleTagValFunc = env->GetUint16ArrayFunction();
163                break;
164            case JSType::JS_INT32_ARRAY:
165                handleTagValFunc = env->GetInt32ArrayFunction();
166                break;
167            case JSType::JS_UINT32_ARRAY:
168                handleTagValFunc = env->GetUint32ArrayFunction();
169                break;
170            case JSType::JS_FLOAT32_ARRAY:
171                handleTagValFunc = env->GetFloat32ArrayFunction();
172                break;
173            case JSType::JS_FLOAT64_ARRAY:
174                handleTagValFunc = env->GetFloat64ArrayFunction();
175                break;
176            case JSType::JS_BIGINT64_ARRAY:
177                handleTagValFunc = env->GetBigInt64ArrayFunction();
178                break;
179            case JSType::JS_BIGUINT64_ARRAY:
180                handleTagValFunc = env->GetBigUint64ArrayFunction();
181                break;
182            default:
183                ASSERT_PRINT(false, "wrong jsType used in CreateNumberTypedArray function");
184                break;
185        }
186        return JSHandle<JSTypedArray>::Cast(
187            factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(handleTagValFunc), handleTagValFunc));
188    }
189
190    JSHandle<JSObject> NewObject(uint32_t size, JSType type, JSHandle<JSTaggedValue> proto)
191    {
192        ObjectFactory *factory = instance->GetFactory();
193        JSHandle<JSHClass> hclass = factory->NewEcmaHClass(size, type, proto);
194        return factory->NewJSObjectWithInit(hclass);
195    }
196
197    JSHandle<JSObject> NewSObject(uint32_t size, JSType type, JSHandle<JSTaggedValue> proto)
198    {
199        ObjectFactory *factory = instance->GetFactory();
200        auto emptySLayout = instance->GetJSThread()->GlobalConstants()->GetHandledEmptySLayoutInfo();
201        JSHandle<JSHClass> hclass = factory->NewSEcmaHClass(size, 0, type, proto, emptySLayout);
202        return factory->NewJSObjectWithInit(hclass);
203    }
204
205    // JS_SET
206    JSHandle<JSSet> NewJSSet()
207    {
208        JSThread *thread = instance->GetJSThread();
209        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
210        JSHandle<JSObject> jsSetObject = NewObject(JSSet::SIZE, JSType::JS_SET, proto);
211        JSHandle<JSSet> jsSet = JSHandle<JSSet>::Cast(jsSetObject);
212        JSHandle<LinkedHashSet> linkedSet(LinkedHashSet::Create(thread));
213        jsSet->SetLinkedSet(thread, linkedSet);
214        return jsSet;
215    }
216
217    // JS_SHARED_SET
218    JSHandle<JSSharedSet> NewJSSharedSet()
219    {
220        JSThread *thread = instance->GetJSThread();
221        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetSFunctionPrototype();
222        JSHandle<JSObject> jsSSetObject = NewSObject(JSSharedSet::SIZE, JSType::JS_SHARED_SET, proto);
223        JSHandle<JSSharedSet> jsSSet = JSHandle<JSSharedSet>::Cast(jsSSetObject);
224        JSHandle<LinkedHashSet> linkedSet(
225            LinkedHashSet::Create(thread, LinkedHashSet::MIN_CAPACITY, MemSpaceKind::SHARED));
226        jsSSet->SetLinkedSet(thread, linkedSet);
227        jsSSet->SetModRecord(0);
228        return jsSSet;
229    }
230
231    // JS_MAP
232    JSHandle<JSMap> NewJSMap()
233    {
234        JSThread *thread = instance->GetJSThread();
235        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
236        JSHandle<JSObject> jsMapObject = NewObject(JSMap::SIZE, JSType::JS_MAP, proto);
237        JSHandle<JSMap> jsMap = JSHandle<JSMap>::Cast(jsMapObject);
238        JSHandle<LinkedHashMap> linkedMap(LinkedHashMap::Create(thread));
239        jsMap->SetLinkedMap(thread, linkedMap);
240        return jsMap;
241    }
242
243    // JS_SHARED_MAP
244    JSHandle<JSSharedMap> NewJSSharedMap()
245    {
246        JSThread *thread = instance->GetJSThread();
247        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetSFunctionPrototype();
248        JSHandle<JSObject> jsSMapObject = NewSObject(JSSharedMap::SIZE, JSType::JS_SHARED_MAP, proto);
249        JSHandle<JSSharedMap> jsSMap = JSHandle<JSSharedMap>::Cast(jsSMapObject);
250        JSHandle<LinkedHashMap> linkedMap(
251            LinkedHashMap::Create(thread, LinkedHashMap::MIN_CAPACITY, MemSpaceKind::SHARED));
252        jsSMap->SetLinkedMap(thread, linkedMap);
253        jsSMap->SetModRecord(0);
254        return jsSMap;
255    }
256
257    //JS_WEAK_SET
258    JSHandle<JSWeakSet> NewJSWeakSet()
259    {
260        JSThread *thread = instance->GetJSThread();
261        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
262        JSHandle<JSObject> jsWeakSetObject = NewObject(JSWeakSet::SIZE, JSType::JS_WEAK_SET, proto);
263        JSHandle<JSWeakSet> jsWeakSet = JSHandle<JSWeakSet>::Cast(jsWeakSetObject);
264        JSHandle<LinkedHashSet> weakLinkedSet(LinkedHashSet::Create(thread));
265        jsWeakSet->SetLinkedSet(thread, weakLinkedSet);
266        return jsWeakSet;
267    }
268
269    //JS_WEAK_MAP
270    JSHandle<JSWeakMap> NewJSWeakMap()
271    {
272        JSThread *thread = instance->GetJSThread();
273        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
274        JSHandle<JSObject> jsWeakMapObject = NewObject(JSWeakMap::SIZE, JSType::JS_WEAK_MAP, proto);
275        JSHandle<JSWeakMap> jsWeakMap = JSHandle<JSWeakMap>::Cast(jsWeakMapObject);
276        JSHandle<LinkedHashMap> weakLinkedMap(LinkedHashMap::Create(thread));
277        jsWeakMap->SetLinkedMap(thread, weakLinkedMap);
278        return jsWeakMap;
279    }
280
281    // JS_PROXY
282    JSHandle<JSProxy> NewJSProxy()
283    {
284        JSThread *thread = instance->GetJSThread();
285        ObjectFactory *factory = instance->GetFactory();
286        JSFunction *newTarget = instance->GetGlobalEnv()->GetObjectFunction().GetObject<JSFunction>();
287        JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
288        JSHandle<JSObject> jsObject =
289            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(newTargetHandle), newTargetHandle);
290        JSHandle<JSTaggedValue> emptyObj(thread, jsObject.GetTaggedValue());
291        return factory->NewJSProxy(emptyObj, emptyObj);
292    }
293
294    // JS_FORIN_ITERATOR
295    JSHandle<JSForInIterator> NewJSForInIterator()
296    {
297        JSThread *thread = instance->GetJSThread();
298        ObjectFactory *factory = instance->GetFactory();
299        JSHandle<JSTaggedValue> arrayEmpty(thread, factory->NewJSArray().GetTaggedValue());
300        JSHandle<JSTaggedValue> keys(thread, factory->EmptyArray().GetTaggedValue());
301        JSHandle<JSTaggedValue> hclass(thread, JSTaggedValue::Undefined());
302        return factory->NewJSForinIterator(arrayEmpty, keys, hclass);
303    }
304
305    // JS_REG_EXP_ITERATOR
306    JSHandle<JSRegExpIterator> NewJSRegExpIterator()
307    {
308        ObjectFactory *factory = instance->GetFactory();
309        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
310        JSHandle<EcmaString> emptyString = factory->GetEmptyString();
311        JSHandle<JSTaggedValue> jsRegExp(NewObject(JSRegExp::SIZE, JSType::JS_REG_EXP, proto));
312        return factory->NewJSRegExpIterator(jsRegExp, emptyString, false, false);
313    }
314
315    // PROMISE_ITERATOR_RECORD
316    JSHandle<PromiseIteratorRecord> NewPromiseIteratorRecord()
317    {
318        JSThread *thread = instance->GetJSThread();
319        ObjectFactory *factory = instance->GetFactory();
320        JSFunction *newTarget = instance->GetGlobalEnv()->GetObjectFunction().GetObject<JSFunction>();
321        JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
322        JSHandle<JSObject> jsObject =
323            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(newTargetHandle), newTargetHandle);
324        JSHandle<JSTaggedValue> emptyObj(thread, jsObject.GetTaggedValue());
325        return factory->NewPromiseIteratorRecord(emptyObj, false);
326    }
327
328    // JS_API_ARRAY_LIST
329    JSHandle<JSAPIArrayList> NewJSAPIArrayList()
330    {
331        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
332        JSHandle<JSObject> jsAPIArrayListObject = NewObject(JSAPIArrayList::SIZE, JSType::JS_API_ARRAY_LIST, proto);
333        JSHandle<JSAPIArrayList> jsAPIArrayList = JSHandle<JSAPIArrayList>::Cast(jsAPIArrayListObject);
334        jsAPIArrayList->SetLength(instance->GetJSThread(), JSTaggedValue(0));
335        return jsAPIArrayList;
336    }
337
338    // JS_API_HASH_MAP
339    JSHandle<JSAPIHashMap> NewJSAPIHashMap()
340    {
341        JSThread *thread = instance->GetJSThread();
342        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
343        JSHandle<JSObject> jsAPIHashMapObject = NewObject(JSAPIHashMap::SIZE, JSType::JS_API_HASH_MAP, proto);
344        JSHandle<JSAPIHashMap> jsAPIHashMap = JSHandle<JSAPIHashMap>::Cast(jsAPIHashMapObject);
345        jsAPIHashMap->SetTable(thread, TaggedHashArray::Create(thread));
346        jsAPIHashMap->SetSize(0);
347        return jsAPIHashMap;
348    }
349
350    // JS_API_HASH_SET
351    JSHandle<JSAPIHashSet> NewJSAPIHashSet()
352    {
353        JSThread *thread = instance->GetJSThread();
354        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
355        JSHandle<JSObject> jsAPIHashSetObject = NewObject(JSAPIHashSet::SIZE, JSType::JS_API_HASH_SET, proto);
356        JSHandle<JSAPIHashSet> jsAPIHashSet = JSHandle<JSAPIHashSet>::Cast(jsAPIHashSetObject);
357        jsAPIHashSet->SetTable(thread, TaggedHashArray::Create(thread));
358        jsAPIHashSet->SetSize(0);
359        return jsAPIHashSet;
360    }
361
362    // JS_API_LIGHT_WEIGHT_MAP
363    JSHandle<JSAPILightWeightMap> NewJSAPILightWeightMap()
364    {
365        JSThread *thread = instance->GetJSThread();
366        ObjectFactory *factory = instance->GetFactory();
367        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
368        JSHandle<JSObject> jsAPILightWeightMapObject =
369            NewObject(JSAPILightWeightMap::SIZE, JSType::JS_API_LIGHT_WEIGHT_MAP, proto);
370        JSHandle<JSAPILightWeightMap> jsAPILightWeightMap =
371            JSHandle<JSAPILightWeightMap>::Cast(jsAPILightWeightMapObject);
372        JSHandle<JSTaggedValue> hashArray =
373            JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
374        JSHandle<JSTaggedValue> keyArray =
375            JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
376        JSHandle<JSTaggedValue> valueArray =
377            JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
378        jsAPILightWeightMap->SetHashes(thread, hashArray);
379        jsAPILightWeightMap->SetKeys(thread, keyArray);
380        jsAPILightWeightMap->SetValues(thread, valueArray);
381        jsAPILightWeightMap->SetLength(0);
382        return jsAPILightWeightMap;
383    }
384
385    // JS_API_LIGHT_WEIGHT_SET
386    JSHandle<JSAPILightWeightSet> NewJSAPILightWeightSet()
387    {
388        JSThread *thread = instance->GetJSThread();
389        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
390        JSHandle<JSObject> jsAPILightWeightSetObject =
391            NewObject(JSAPILightWeightSet::SIZE, JSType::JS_API_LIGHT_WEIGHT_SET, proto);
392        JSHandle<JSAPILightWeightSet> jsAPILightWeightSet =
393            JSHandle<JSAPILightWeightSet>::Cast(jsAPILightWeightSetObject);
394        JSHandle<TaggedArray> hashes =
395            JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
396        JSHandle<TaggedArray> values =
397            JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
398        jsAPILightWeightSet->SetHashes(thread, hashes);
399        jsAPILightWeightSet->SetValues(thread, values);
400        jsAPILightWeightSet->SetLength(0);
401        return jsAPILightWeightSet;
402    }
403
404    // JS_API_TREE_MAP
405    JSHandle<JSAPITreeMap> NewJSAPITreeMap()
406    {
407        JSThread *thread = instance->GetJSThread();
408        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
409        JSHandle<JSObject> jsAPITreeMapObject = NewObject(JSAPITreeMap::SIZE, JSType::JS_API_TREE_MAP, proto);
410        JSHandle<JSAPITreeMap> jsAPITreeMap = JSHandle<JSAPITreeMap>::Cast(jsAPITreeMapObject);
411        JSHandle<TaggedTreeMap> treeMap(thread, TaggedTreeMap::Create(thread));
412        jsAPITreeMap->SetTreeMap(thread, treeMap);
413        return jsAPITreeMap;
414    }
415
416    // JS_API_TREE_SET
417    JSHandle<JSAPITreeSet> NewJSAPITreeSet()
418    {
419        JSThread *thread = instance->GetJSThread();
420        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
421        JSHandle<JSObject> jsAPITreeSetObject = NewObject(JSAPITreeSet::SIZE, JSType::JS_API_TREE_SET, proto);
422        JSHandle<JSAPITreeSet> jsAPITreeSet = JSHandle<JSAPITreeSet>::Cast(jsAPITreeSetObject);
423        JSHandle<TaggedTreeSet> treeSet(thread, TaggedTreeSet::Create(thread));
424        jsAPITreeSet->SetTreeSet(thread, treeSet);
425        return jsAPITreeSet;
426    }
427
428    // JS_API_QUEUE
429    JSHandle<JSAPIQueue> NewJSAPIQueue()
430    {
431        JSThread *thread = instance->GetJSThread();
432        ObjectFactory *factory = instance->GetFactory();
433        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
434        JSHandle<JSObject> jsAPIQueueObject = NewObject(JSAPIQueue::SIZE, JSType::JS_API_QUEUE, proto);
435        JSHandle<JSAPIQueue> jsAPIQueue = JSHandle<JSAPIQueue>::Cast(jsAPIQueueObject);
436        JSHandle<TaggedArray> newElements = factory->NewTaggedArray(JSAPIQueue::DEFAULT_CAPACITY_LENGTH);
437        jsAPIQueue->SetLength(thread, JSTaggedValue(0));
438        jsAPIQueue->SetFront(0);
439        jsAPIQueue->SetTail(0);
440        jsAPIQueue->SetElements(thread, newElements);
441        return jsAPIQueue;
442    }
443    // JS_API_DEQUE
444    JSHandle<JSAPIDeque> NewJSAPIDeque()
445    {
446        ObjectFactory *factory = instance->GetFactory();
447        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
448        JSHandle<JSObject> jsAPIDequeObject = NewObject(JSAPIDeque::SIZE, JSType::JS_API_DEQUE, proto);
449        JSHandle<JSAPIDeque> jsAPIDeque = JSHandle<JSAPIDeque>::Cast(jsAPIDequeObject);
450        JSHandle<TaggedArray> newElements = factory->NewTaggedArray(JSAPIDeque::DEFAULT_CAPACITY_LENGTH);
451        jsAPIDeque->SetFirst(0);
452        jsAPIDeque->SetLast(0);
453        jsAPIDeque->SetElements(instance->GetJSThread(), newElements);
454        return jsAPIDeque;
455    }
456    // JS_API_STACK
457    JSHandle<JSAPIStack> NewJSAPIStack()
458    {
459        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
460        JSHandle<JSObject> jsAPIStackObject = NewObject(JSAPIStack::SIZE, JSType::JS_API_STACK, proto);
461        JSHandle<JSAPIStack> jsAPIStack = JSHandle<JSAPIStack>::Cast(jsAPIStackObject);
462        jsAPIStack->SetTop(0);
463        return jsAPIStack;
464    }
465
466    // JS_API_PLAIN_ARRAY
467    JSHandle<JSAPIPlainArray> NewJSAPIPlainArray()
468    {
469        JSThread *thread = instance->GetJSThread();
470        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
471        JSHandle<JSObject> jsAPIPlainArrayObject = NewObject(JSAPIPlainArray::SIZE, JSType::JS_API_PLAIN_ARRAY, proto);
472        JSHandle<JSAPIPlainArray> jsAPIPlainArray = JSHandle<JSAPIPlainArray>::Cast(jsAPIPlainArrayObject);
473        JSHandle<TaggedArray> keys =
474                JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
475        JSHandle<TaggedArray> values =
476                JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
477        jsAPIPlainArray->SetKeys(thread, keys);
478        jsAPIPlainArray->SetValues(thread, values);
479        jsAPIPlainArray->SetLength(0);
480        return jsAPIPlainArray;
481    }
482
483    // JS_API_LIST
484    JSHandle<JSAPIList> NewJSAPIList()
485    {
486        JSThread *thread = instance->GetJSThread();
487        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
488        JSHandle<JSObject> jsAPIListObject = NewObject(JSAPIList::SIZE, JSType::JS_API_LIST, proto);
489        JSHandle<JSAPIList> jsAPIList = JSHandle<JSAPIList>::Cast(jsAPIListObject);
490        JSHandle<JSTaggedValue> taggedSingleList(thread, TaggedSingleList::Create(thread));
491        jsAPIList->SetSingleList(thread, taggedSingleList);
492        return jsAPIList;
493    }
494
495    // JS_API_LINKED_LIST
496    JSHandle<JSAPILinkedList> NewJSAPILinkedList()
497    {
498        JSThread *thread = instance->GetJSThread();
499        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
500        JSHandle<JSObject> jsAPILinkedListObject = NewObject(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, proto);
501        JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(jsAPILinkedListObject);
502        JSHandle<JSTaggedValue> linkedlist(thread, TaggedDoubleList::Create(thread));
503        jsAPILinkedList->SetDoubleList(thread, linkedlist);
504        return jsAPILinkedList;
505    }
506
507    // JS_API_VECTOR
508    JSHandle<JSAPIVector> NewJSAPIVector()
509    {
510        JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
511        JSHandle<JSObject> jsAPIVectorObject = NewObject(JSAPIVector::SIZE, JSType::JS_API_VECTOR, proto);
512        JSHandle<JSAPIVector> jsAPIVector = JSHandle<JSAPIVector>::Cast(jsAPIVectorObject);
513        jsAPIVector->SetLength(0);
514        return jsAPIVector;
515    }
516
517private:
518    EcmaVM *instance {nullptr};
519};
520
521class MockHeapProfiler : public HeapProfilerInterface {
522public:
523    NO_MOVE_SEMANTIC(MockHeapProfiler);
524    NO_COPY_SEMANTIC(MockHeapProfiler);
525    explicit MockHeapProfiler(HeapProfilerInterface *profiler) : profiler_(profiler) {}
526    ~MockHeapProfiler() override
527    {
528        allocEvtObj_.clear();
529    };
530
531    void AllocationEvent(TaggedObject *address, size_t size) override
532    {
533        allocEvtObj_.emplace(address, true);
534        profiler_->AllocationEvent(address, size);
535    }
536
537    void MoveEvent(uintptr_t address, TaggedObject *forwardAddress, size_t size) override
538    {
539        return profiler_->MoveEvent(address, forwardAddress, size);
540    }
541
542    bool DumpHeapSnapshot(Stream *stream, const DumpSnapShotOption &dumpOption, Progress *progress = nullptr) override
543    {
544        return profiler_->DumpHeapSnapshot(stream, dumpOption, progress);
545    }
546
547    void DumpHeapSnapshot(const DumpSnapShotOption &dumpOption) override
548    {
549        profiler_->DumpHeapSnapshot(dumpOption);
550    }
551
552    bool GenerateHeapSnapshot(std::string &inputFilePath, std::string &outputPath) override
553    {
554        return profiler_->GenerateHeapSnapshot(inputFilePath, outputPath);
555    }
556
557    bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr,
558                           bool traceAllocation = false, bool newThread = true) override
559    {
560        return profiler_->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
561    }
562
563    bool StopHeapTracking(Stream *stream, Progress *progress = nullptr, bool newThread = true) override
564    {
565        return profiler_->StopHeapTracking(stream, progress, newThread);
566    }
567
568    bool UpdateHeapTracking(Stream *stream) override
569    {
570        return profiler_->UpdateHeapTracking(stream);
571    }
572
573    bool StartHeapSampling(uint64_t samplingInterval, int stackDepth = 128) override
574    {
575        return profiler_->StartHeapSampling(samplingInterval, stackDepth);
576    }
577
578    void StopHeapSampling() override
579    {
580        profiler_->StopHeapSampling();
581    }
582
583    const struct SamplingInfo *GetAllocationProfile() override
584    {
585        return profiler_->GetAllocationProfile();
586    }
587
588    size_t GetIdCount() override
589    {
590        return profiler_->GetIdCount();
591    }
592
593    std::unordered_map<TaggedObject *, bool> allocEvtObj_;
594    HeapProfilerInterface *profiler_ {nullptr};
595};
596
597HWTEST_F_L0(HeapDumpTest, TestAllocationEvent)
598{
599    const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"heapdump.abc";
600    const std::string jsFileName = HPROF_TEST_JS_FILES_DIR"heapdump.js";
601    MockHeapProfiler mockHeapProfiler(ecmaVm_->GetOrNewHeapProfile());
602    ecmaVm_->SetHeapProfile(&mockHeapProfiler);
603
604    std::unordered_map<TaggedObject *, bool> ObjBeforeExecute;
605    std::unordered_map<TaggedObject *, bool> *ObjMap = &ObjBeforeExecute;
606    auto heap = ecmaVm_->GetHeap();
607    ASSERT_NE(heap, nullptr);
608    auto countCb = [&ObjMap](TaggedObject *obj) {
609        ObjMap->emplace(obj, true);
610    };
611    heap->IterateOverObjects(countCb);
612    RootVisitor rootVisitor = [&countCb]([[maybe_unused]] Root type, ObjectSlot slot) {
613        JSTaggedValue value((slot).GetTaggedType());
614        if (!value.IsHeapObject()) {
615            return;
616        }
617        TaggedObject *root = value.GetTaggedObject();
618        countCb(root);
619    };
620    RootRangeVisitor rangeVisitor = [&rootVisitor]([[maybe_unused]] Root type,
621                                    ObjectSlot start, ObjectSlot end) {
622        for (ObjectSlot slot = start; slot < end; slot++) {
623            rootVisitor(type, slot);
624        }
625    };
626    RootBaseAndDerivedVisitor derivedVisitor = []
627        ([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived,
628         [[maybe_unused]] uintptr_t baseOldObject) {};
629    ecmaVm_->Iterate(rootVisitor, rangeVisitor, VMRootVisitType::HEAP_SNAPSHOT);
630    thread_->Iterate(rootVisitor, rangeVisitor, derivedVisitor);
631
632    bool result = JSNApi::Execute(ecmaVm_, abcFileName, "heapdump");
633    EXPECT_TRUE(result);
634
635    std::unordered_map<TaggedObject *, bool> ObjAfterExecute;
636    ObjMap = &ObjAfterExecute;
637    heap->IterateOverObjects(countCb);
638    ecmaVm_->Iterate(rootVisitor, rangeVisitor, VMRootVisitType::HEAP_SNAPSHOT);
639    thread_->Iterate(rootVisitor, rangeVisitor, derivedVisitor);
640    ecmaVm_->SetHeapProfile(mockHeapProfiler.profiler_);
641
642    std::unordered_map<std::string, int> noTraceObjCheck =
643       {{"TaggedArray", 1}, {"AsyncFunction", 2}, {"LexicalEnv", 2}, {"Array", 3}, {"Function", 7}, {"Map", 1},
644       {"Object", 1}, {"Uint8 Clamped Array", 1}, {"Uint32 Array", 1}, {"Float32 Array", 1}, {"Int32 Array", 1},
645       {"Int16 Array", 1}, {"BigUint64 Array", 1}, {"Uint8 Array", 1}, {"Float64 Array", 1}, {"ByteArray", 11},
646       {"Int8 Array", 1}, {"BigInt64 Array", 1}, {"Uint16 Array", 1}};
647    bool pass = true;
648    std::unordered_map<std::string, int> noTraceObj;
649    for (auto o = ObjAfterExecute.begin(); o != ObjAfterExecute.end(); o++) {
650        if (ObjBeforeExecute.find(o->first) != ObjBeforeExecute.end()) {
651            continue;
652        }
653        if (mockHeapProfiler.allocEvtObj_.find(o->first) != mockHeapProfiler.allocEvtObj_.end()) {
654            continue;
655        }
656        auto objType = o->first->GetClass()->GetObjectType();
657        std::string typeName = ConvertToStdString(JSHClass::DumpJSType(objType));
658        if (noTraceObjCheck.size() == 0) {
659            LOG_ECMA(ERROR) << "Object not traced, Addr=" << o->first << ", TypeName=" << typeName;
660            pass = false;
661        }
662        if (noTraceObj.find(typeName) == noTraceObj.end()) {
663            noTraceObj.emplace(typeName, 0);
664        }
665        noTraceObj[typeName] += 1;
666    }
667    for (auto o = noTraceObj.begin(); o != noTraceObj.end(); o++) {
668        if (noTraceObjCheck.find(o->first) == noTraceObjCheck.end()) {
669            LOG_ECMA(ERROR) << "Object not traced, TypeName=" << o->first << ", count=" << o->second;
670            pass = false;
671        }
672    }
673    ASSERT_TRUE(pass);
674}
675
676HWTEST_F_L0(HeapDumpTest, TestHeapDumpFunctionUrl)
677{
678    const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"heapdump.abc";
679
680    bool result = JSNApi::Execute(ecmaVm_, abcFileName, "heapdump");
681    EXPECT_TRUE(result);
682
683    HeapDumpTestHelper tester(ecmaVm_);
684    tester.GenerateSnapShot("testFunctionUrl.heapsnapshot");
685
686    // match function url
687    std::string line;
688    std::ifstream inputStream("testFunctionUrl.heapsnapshot");
689    bool strMatched = false;
690    bool funcTempMatched = false;
691    while (getline(inputStream, line)) {
692        if (strMatched && funcTempMatched) {
693            break;
694        }
695        if (line == "\"heapdump greet(line:98)\",") {
696            strMatched = true;
697            continue;
698        }
699        if (line == "\"ArkInternalFunctionTemplate\",") {
700            funcTempMatched = true;
701            continue;
702        }
703    }
704    ASSERT_TRUE(strMatched);
705    ASSERT_TRUE(funcTempMatched);
706}
707
708HWTEST_F_L0(HeapDumpTest, DISABLED_TestAllocationMassiveMoveNode)
709{
710    const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"allocation.abc";
711    HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(ecmaVm_);
712
713    // start allocation
714    bool start = heapProfile->StartHeapTracking(50);
715    EXPECT_TRUE(start);
716
717    auto currentTime = std::chrono::system_clock::now();
718    auto currentTimeBeforeMs =
719        std::chrono::time_point_cast<std::chrono::milliseconds>(currentTime).time_since_epoch().count();
720
721    bool result = JSNApi::Execute(ecmaVm_, abcFileName, "allocation");
722
723    currentTime = std::chrono::system_clock::now();
724    auto currentTimeAfterMs =
725        std::chrono::time_point_cast<std::chrono::milliseconds>(currentTime).time_since_epoch().count();
726    EXPECT_TRUE(result);
727
728    std::string fileName = "test.allocationtime";
729    fstream outputString(fileName, std::ios::out);
730    outputString.close();
731    outputString.clear();
732
733    // stop allocation
734    FileStream stream(fileName.c_str());
735    bool stop = heapProfile->StopHeapTracking(&stream, nullptr);
736    EXPECT_TRUE(stop);
737    HeapProfilerInterface::Destroy(ecmaVm_);
738
739    auto timeSpent = currentTimeAfterMs - currentTimeBeforeMs;
740    long long int limitedTimeMs = 30000;
741    ASSERT_TRUE(timeSpent < limitedTimeMs);
742}
743
744HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName1)
745{
746    JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
747    ObjectFactory *factory = ecmaVm_->GetFactory();
748    HeapDumpTestHelper tester(ecmaVm_);
749
750    // TAGGED_ARRAY
751    factory->NewTaggedArray(10);
752    // LEXICAL_ENV
753    factory->NewLexicalEnv(10);
754    // CONSTANT_POOL
755    factory->NewConstantPool(10);
756    // PROFILE_TYPE_INFO
757    factory->NewProfileTypeInfo(10);
758    // TAGGED_DICTIONARY
759    factory->NewDictionaryArray(10);
760    // AOT_LITERAL_INFO
761    factory->NewAOTLiteralInfo(10);
762    // VTABLE
763    factory->NewVTable(10);
764    // COW_TAGGED_ARRAY
765    factory->NewCOWTaggedArray(10);
766    // HCLASS
767    JSHandle<JSTaggedValue> proto = env->GetFunctionPrototype();
768    factory->NewEcmaHClass(JSHClass::SIZE, JSType::HCLASS, proto);
769    // LINKED_NODE
770    JSHandle<LinkedNode> linkedNode(thread_, JSTaggedValue::Hole());
771    factory->NewLinkedNode(1, JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()),
772        JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()), linkedNode);
773    // JS_NATIVE_POINTER
774    auto newData = ecmaVm_->GetNativeAreaAllocator()->AllocateBuffer(8);
775    factory->NewJSNativePointer(newData);
776
777    tester.GenerateSnapShot("testGenerateNodeName_1.heapsnapshot");
778    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalArray["));
779    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"LexicalEnv["));
780    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalConstantPool["));
781    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalProfileTypeInfo["));
782    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalDict["));
783    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalAOTLiteralInfo["));
784    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalVTable["));
785    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalCOWArray["));
786    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"HiddenClass(NonMovable)"));
787    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"LinkedNode\""));
788    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"JSNativePointer\""));
789    // Test Not Found
790    ASSERT_TRUE(!tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "*#@failed case"));
791}
792
793HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName2)
794{
795    ObjectFactory *factory = ecmaVm_->GetFactory();
796    HeapDumpTestHelper tester(ecmaVm_);
797
798    // JS_ERROR
799    JSHandle<EcmaString> handleMessage(thread_, EcmaStringAccessor::CreateEmptyString(ecmaVm_));
800    factory->NewJSError(ErrorType::ERROR, handleMessage);
801    // JS_EVAL_ERROR
802    factory->NewJSError(ErrorType::EVAL_ERROR, handleMessage);
803    // JS_RANGE_ERROR
804    factory->NewJSError(ErrorType::RANGE_ERROR, handleMessage);
805    // JS_TYPE_ERROR
806    factory->NewJSError(ErrorType::TYPE_ERROR, handleMessage);
807    // JS_AGGREGATE_ERROR
808    factory->NewJSAggregateError();
809    // JS_REFERENCE_ERROR
810    factory->NewJSError(ErrorType::REFERENCE_ERROR, handleMessage);
811    // JS_URI_ERROR
812    factory->NewJSError(ErrorType::URI_ERROR, handleMessage);
813    // JS_SYNTAX_ERROR
814    factory->NewJSError(ErrorType::SYNTAX_ERROR, handleMessage);
815    // JS_OOM_ERROR
816    factory->NewJSError(ErrorType::OOM_ERROR, handleMessage);
817    // JS_TERMINATION_ERROR
818    factory->NewJSError(ErrorType::TERMINATION_ERROR, handleMessage);
819
820    tester.GenerateSnapShot("testGenerateNodeName_2.heapsnapshot");
821    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Error\""));
822    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Eval Error\""));
823    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Range Error\""));
824    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Type Error\""));
825    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Aggregate Error\""));
826    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Reference Error\""));
827    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Uri Error\""));
828    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Syntax Error\""));
829    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"OutOfMemory Error\""));
830    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Termination Error\""));
831}
832
833HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName3)
834{
835    HeapDumpTestHelper tester(ecmaVm_);
836
837    // JS_INT8_ARRAY
838    tester.CreateNumberTypedArray(JSType::JS_INT8_ARRAY);
839    // JS_UINT8_ARRAY
840    tester.CreateNumberTypedArray(JSType::JS_UINT8_ARRAY);
841    // JS_UINT8_CLAMPED_ARRAY
842    tester.CreateNumberTypedArray(JSType::JS_UINT8_CLAMPED_ARRAY);
843    // JS_INT16_ARRAY
844    tester.CreateNumberTypedArray(JSType::JS_INT16_ARRAY);
845    // JS_UINT16_ARRAY
846    tester.CreateNumberTypedArray(JSType::JS_UINT16_ARRAY);
847    // JS_INT32_ARRAY
848    tester.CreateNumberTypedArray(JSType::JS_INT32_ARRAY);
849    // JS_UINT32_ARRAY
850    tester.CreateNumberTypedArray(JSType::JS_UINT32_ARRAY);
851    // JS_FLOAT32_ARRAY
852    tester.CreateNumberTypedArray(JSType::JS_FLOAT32_ARRAY);
853    // JS_FLOAT64_ARRAY
854    tester.CreateNumberTypedArray(JSType::JS_FLOAT64_ARRAY);
855    // JS_BIGINT64_ARRAY
856    tester.CreateNumberTypedArray(JSType::JS_BIGINT64_ARRAY);
857    // JS_BIGUINT64_ARRAY
858    tester.CreateNumberTypedArray(JSType::JS_BIGUINT64_ARRAY);
859
860    tester.GenerateSnapShot("testGenerateNodeName_3.heapsnapshot");
861    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int8 Array\""));
862    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint8 Array\""));
863    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint8 Clamped Array\""));
864    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int16 Array\""));
865    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint16 Array\""));
866    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int32 Array\""));
867    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint32 Array\""));
868    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Float32 Array\""));
869    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Float64 Array\""));
870    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"BigInt64 Array\""));
871    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"BigUint64 Array\""));
872}
873
874HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName4)
875{
876    ObjectFactory *factory = ecmaVm_->GetFactory();
877    HeapDumpTestHelper tester(ecmaVm_);
878
879    JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
880    // JS_SET
881    tester.NewJSSet();
882    // JS_SHARED_SET
883    tester.NewJSSharedSet();
884    // JS_MAP
885    tester.NewJSMap();
886    // JS_SHARED_MAP
887    tester.NewJSSharedMap();
888    // JS_WEAK_SET
889    tester.NewJSWeakSet();
890    // JS_WEAK_MAP
891    tester.NewJSWeakMap();
892    // JS_ARRAY
893    factory->NewJSArray();
894    // JS_TYPED_ARRAY
895    tester.NewObject(JSTypedArray::SIZE, JSType::JS_TYPED_ARRAY, proto);
896    tester.GenerateSnapShot("testGenerateNodeName_4.heapsnapshot");
897
898    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Set\""));
899    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedSet\""));
900    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Map\""));
901    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedMap\""));
902    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakSet\""));
903    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakMap\""));
904    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"JSArray\""));
905    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Typed Array\""));
906}
907
908HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName5)
909{
910    ObjectFactory *factory = ecmaVm_->GetFactory();
911    HeapDumpTestHelper tester(ecmaVm_);
912
913    JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
914    // JS_REG_EXP
915    tester.NewObject(JSRegExp::SIZE, JSType::JS_REG_EXP, proto);
916    // JS_DATE
917    tester.NewObject(JSDate::SIZE, JSType::JS_DATE, proto);
918    // JS_ARGUMENTS
919    factory->NewJSArguments();
920    // JS_PROXY
921    tester.NewJSProxy();
922    // JS_PRIMITIVE_REF
923    tester.NewObject(JSPrimitiveRef::SIZE, JSType::JS_PRIMITIVE_REF, proto);
924    // JS_DATA_VIEW
925    factory->NewJSDataView(factory->NewJSArrayBuffer(10), 5, 5);
926
927    tester.GenerateSnapShot("testGenerateNodeName_5.heapsnapshot");
928    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Regexp\""));
929    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Date\""));
930    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Arguments\""));
931    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Proxy\""));
932    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Primitive\""));
933    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"DataView\""));
934}
935
936HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName6)
937{
938    ObjectFactory *factory = ecmaVm_->GetFactory();
939    HeapDumpTestHelper tester(ecmaVm_);
940
941    // JS_FORIN_ITERATOR
942    tester.NewJSForInIterator();
943    // JS_MAP_ITERATOR
944    factory->NewJSMapIterator(tester.NewJSMap(), IterationKind::KEY);
945    // JS_SHARED_MAP_ITERATOR
946    factory->NewJSMapIterator(tester.NewJSSharedMap(), IterationKind::KEY);
947    // JS_SET_ITERATOR
948    factory->NewJSSetIterator(tester.NewJSSet(), IterationKind::KEY);
949    // JS_SHARED_SET_ITERATOR
950    factory->NewJSSetIterator(tester.NewJSSharedSet(), IterationKind::KEY);
951    // JS_REG_EXP_ITERATOR
952    tester.NewJSRegExpIterator();
953    // JS_ARRAY_ITERATOR
954    factory->NewJSArrayIterator(JSHandle<JSObject>::Cast(factory->NewJSArray()), IterationKind::KEY);
955    // JS_STRING_ITERATOR
956    JSStringIterator::CreateStringIterator(thread_, factory->GetEmptyString());
957
958    tester.GenerateSnapShot("testGenerateNodeName_6.heapsnapshot");
959    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"ForinInterator\""));
960    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"MapIterator\""));
961    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SharedMapIterator\""));
962    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SetIterator\""));
963    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SharedSetIterator\""));
964    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"RegExpIterator\""));
965    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"ArrayIterator\""));
966    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"StringIterator\""));
967}
968
969HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName7)
970{
971    ObjectFactory *factory = ecmaVm_->GetFactory();
972    HeapDumpTestHelper tester(ecmaVm_);
973    // JS_ARRAY_BUFFER
974    factory->NewJSArrayBuffer(10);
975    // JS_SHARED_ARRAY_BUFFER
976    factory->NewJSSharedArrayBuffer(10);
977    // PROMISE_REACTIONS
978    factory->NewPromiseReaction();
979    // PROMISE_CAPABILITY
980    factory->NewPromiseCapability();
981    // PROMISE_ITERATOR_RECORD
982    tester.NewPromiseIteratorRecord();
983    // PROMISE_RECORD
984    factory->NewPromiseRecord();
985    // RESOLVING_FUNCTIONS_RECORD
986    factory->NewResolvingFunctionsRecord();
987    // JS_PROMISE
988    JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
989    tester.NewObject(JSPromise::SIZE, JSType::JS_PROMISE, proto);
990    // ASYNC_GENERATOR_REQUEST
991    factory->NewAsyncGeneratorRequest();
992
993    tester.GenerateSnapShot("testGenerateNodeName_7.heapsnapshot");
994    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"ArrayBuffer\""));
995    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"SharedArrayBuffer\""));
996    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseReaction\""));
997    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseCapability\""));
998    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseIteratorRecord\""));
999    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseRecord\""));
1000    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"ResolvingFunctionsRecord\""));
1001    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"Promise\""));
1002    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"AsyncGeneratorRequest\""));
1003}
1004
1005HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName8)
1006{
1007    auto factory = ecmaVm_->GetFactory();
1008    HeapDumpTestHelper tester(ecmaVm_);
1009    // JS_API_ARRAY_LIST
1010    auto jsAPIArrayList = tester.NewJSAPIArrayList();
1011    // JS_API_ARRAYLIST_ITERATOR
1012    factory->NewJSAPIArrayListIterator(jsAPIArrayList);
1013    // JS_API_HASH_MAP
1014    auto jsAPIHashMap = tester.NewJSAPIHashMap();
1015    // JS_API_HASHMAP_ITERATOR
1016    factory->NewJSAPIHashMapIterator(jsAPIHashMap, IterationKind::KEY);
1017    // JS_API_HASH_SET
1018    auto jsAPIHashSet = tester.NewJSAPIHashSet();
1019    // JS_API_HASHSET_ITERATOR
1020    factory->NewJSAPIHashSetIterator(jsAPIHashSet, IterationKind::KEY);
1021    // JS_API_LIGHT_WEIGHT_MAP
1022    auto jsAPILightWeightMap = tester.NewJSAPILightWeightMap();
1023    // JS_API_LIGHT_WEIGHT_MAP_ITERATOR
1024    factory->NewJSAPILightWeightMapIterator(jsAPILightWeightMap, IterationKind::KEY);
1025    // JS_API_LIGHT_WEIGHT_SET
1026    auto jsAPILightWeightSet = tester.NewJSAPILightWeightSet();
1027    // JS_API_LIGHT_WEIGHT_SET_ITERATOR
1028    factory->NewJSAPILightWeightSetIterator(jsAPILightWeightSet, IterationKind::KEY);
1029
1030    tester.GenerateSnapShot("testGenerateNodeName_8.heapsnapshot");
1031    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"ArrayList\""));
1032    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"ArrayListIterator\""));
1033    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashMap\""));
1034    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashSet\""));
1035    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashMapIterator\""));
1036    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashSetIterator\""));
1037    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightMap\""));
1038    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightMapIterator\""));
1039    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightSet\""));
1040    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightSetIterator\""));
1041}
1042
1043HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName9)
1044{
1045    auto factory = ecmaVm_->GetFactory();
1046    HeapDumpTestHelper tester(ecmaVm_);
1047    // JS_API_TREE_MAP
1048    auto jsAPITreeMap = tester.NewJSAPITreeMap();
1049    // JS_API_TREEMAP_ITERATOR
1050    factory->NewJSAPITreeMapIterator(jsAPITreeMap, IterationKind::KEY);
1051    // JS_API_TREE_SET
1052    auto jsAPITreeSet = tester.NewJSAPITreeSet();
1053    // JS_API_TREESET_ITERATOR
1054    factory->NewJSAPITreeSetIterator(jsAPITreeSet, IterationKind::KEY);
1055    // JS_API_VECTOR
1056    auto jsAPIVector = tester.NewJSAPIVector();
1057    // JS_API_VECTOR_ITERATOR
1058    factory->NewJSAPIVectorIterator(jsAPIVector);
1059    // JS_API_QUEUE
1060    auto jsAPIQueue = tester.NewJSAPIQueue();
1061    // JS_API_QUEUE_ITERATOR
1062    factory->NewJSAPIQueueIterator(jsAPIQueue);
1063    // JS_API_DEQUE
1064    auto jsAPIDeque = tester.NewJSAPIDeque();
1065    // JS_API_DEQUE_ITERATOR
1066    factory->NewJSAPIDequeIterator(jsAPIDeque);
1067    // JS_API_STACK
1068    auto jsAPIStack = tester.NewJSAPIStack();
1069    // JS_API_STACK_ITERATOR
1070    factory->NewJSAPIStackIterator(jsAPIStack);
1071    // JS_API_LIST
1072    tester.NewJSAPIList();
1073    // JS_API_LINKED_LIST
1074    tester.NewJSAPILinkedList();
1075    // JS_API_PLAIN_ARRAY
1076    auto jsAPIPlainArray = tester.NewJSAPIPlainArray();
1077    // JS_API_PLAIN_ARRAY_ITERATOR
1078    factory->NewJSAPIPlainArrayIterator(jsAPIPlainArray, IterationKind::KEY);
1079
1080    tester.GenerateSnapShot("testGenerateNodeName_9.heapsnapshot");
1081    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeMap\""));
1082    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeMapIterator\""));
1083    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeSet\""));
1084    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeSetIterator\""));
1085    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Vector\""));
1086    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"VectorIterator\""));
1087    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Queue\""));
1088    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"QueueIterator\""));
1089    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Deque\""));
1090    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"DequeIterator\""));
1091    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Stack\""));
1092    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"StackIterator\""));
1093    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"List\""));
1094    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"LinkedList\""));
1095    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"PlainArray\""));
1096    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"PlainArrayIterator\""));
1097}
1098
1099HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDump)
1100{
1101    ObjectFactory *factory = ecmaVm_->GetFactory();
1102    HeapDumpTestHelper tester(ecmaVm_);
1103    // PROMISE_ITERATOR_RECORD
1104    tester.NewPromiseIteratorRecord();
1105    // PROMISE_RECORD
1106    factory->NewPromiseRecord();
1107    // JS_ARRAY_BUFFER
1108    factory->NewJSArrayBuffer(10);
1109    // JS_SHARED_ARRAY_BUFFER
1110    factory->NewJSSharedArrayBuffer(10);
1111    // PROMISE_REACTIONS
1112    factory->NewPromiseReaction();
1113    // PROMISE_CAPABILITY
1114    factory->NewPromiseCapability();
1115    // RESOLVING_FUNCTIONS_RECORD
1116    factory->NewResolvingFunctionsRecord();
1117    // JS_PROMISE
1118    JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
1119    tester.NewObject(JSPromise::SIZE, JSType::JS_PROMISE, proto);
1120    // ASYNC_GENERATOR_REQUEST
1121    factory->NewAsyncGeneratorRequest();
1122    // JS_WEAK_SET
1123    tester.NewJSWeakSet();
1124    // JS_WEAK_MAP
1125    tester.NewJSWeakMap();
1126    std::string rawHeapPath("test_binary_dump.raw");
1127    bool ret = tester.GenerateRawHeapSnashot(rawHeapPath);
1128    ASSERT_TRUE(ret);
1129    std::ifstream file(rawHeapPath, std::ios::binary);
1130    std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
1131    ASSERT_TRUE(content.size() > 0);
1132    auto u64Ptr = reinterpret_cast<const uint64_t *>(content.c_str());
1133    ASSERT_TRUE(*u64Ptr > 0);
1134    std::string snapshotPath("test_binary_dump.heapsnapshot");
1135    ret = tester.DecodeRawHeapSnashot(rawHeapPath, snapshotPath);
1136    ASSERT_TRUE(ret);
1137    ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"SharedArrayBuffer\""));
1138    ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"WeakSet\""));
1139    ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"WeakMap\""));
1140}
1141
1142HWTEST_F_L0(HeapDumpTest, TestSharedFullGCInHeapDump)
1143{
1144    ObjectFactory *factory = ecmaVm_->GetFactory();
1145    HeapDumpTestHelper tester(ecmaVm_);
1146
1147    JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
1148    // JS_SET
1149    tester.NewJSSet();
1150    // JS_SHARED_SET
1151    tester.NewJSSharedSet();
1152    // JS_MAP
1153    tester.NewJSMap();
1154    // JS_SHARED_MAP
1155    tester.NewJSSharedMap();
1156    // JS_WEAK_SET
1157    tester.NewJSWeakSet();
1158    // JS_WEAK_MAP
1159    tester.NewJSWeakMap();
1160    // JS_ARRAY
1161    factory->NewJSArray();
1162    // JS_TYPED_ARRAY
1163    tester.NewObject(JSTypedArray::SIZE, JSType::JS_TYPED_ARRAY, proto);
1164    tester.GenerateSnapShot("testGenerateNodeName_4.heapsnapshot");
1165
1166    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Set\""));
1167    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedSet\""));
1168    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Map\""));
1169    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedMap\""));
1170    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakSet\""));
1171    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakMap\""));
1172    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"JSArray\""));
1173    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Typed Array\""));
1174
1175    auto sHeap = SharedHeap::GetInstance();
1176    sHeap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::OTHER>(thread_);
1177
1178    tester.GenerateSnapShot("testGenerateNodeName_4.heapsnapshot");
1179
1180    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Set\""));
1181    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedSet\""));
1182    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Map\""));
1183    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedMap\""));
1184    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakSet\""));
1185    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakMap\""));
1186    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"JSArray\""));
1187    ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Typed Array\""));
1188}
1189}
1190