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
16#include <cstdio>
17
18#include "assembler/assembly-emitter.h"
19#include "assembler/assembly-parser.h"
20#include "libpandafile/class_data_accessor-inl.h"
21#include "libziparchive/zip_archive.h"
22#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
23#include "ecmascript/tests/test_helper.h"
24
25using namespace panda::ecmascript;
26
27namespace panda::test {
28class JsStackInfoTest : public testing::Test {
29public:
30    static void SetUpTestCase()
31    {
32        GTEST_LOG_(INFO) << "SetUpTestCase";
33    }
34
35    static void TearDownTestCase()
36    {
37        GTEST_LOG_(INFO) << "TearDownCase";
38    }
39
40    void SetUp() override
41    {
42        TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
43        instance->SetEnableForceGC(false);
44    }
45
46    void TearDown() override
47    {
48        TestHelper::DestroyEcmaVMWithScope(instance, scope);
49    }
50
51    EcmaVM *instance {nullptr};
52    EcmaHandleScope *scope {nullptr};
53    JSThread *thread {nullptr};
54};
55
56uintptr_t ToUintPtr(FrameType frame)
57{
58    return static_cast<uintptr_t>(frame);
59}
60
61bool ReadMemFunc([[maybe_unused]] void *ctx, uintptr_t addr, uintptr_t *value)
62{
63    *value = *(reinterpret_cast<uintptr_t *>(addr));
64    return true;
65}
66
67/**
68 * @tc.name: ArkFrameCheck
69 * @tc.desc: Check whether the result returned through "ArkFrameCheck" function is within expectations.
70 * @tc.type: FUNC
71 * @tc.require:
72 */
73HWTEST_F_L0(JsStackInfoTest, TestArkFrameCheck)
74{
75    for (uintptr_t i = 0; i < 25; i++) {
76        bool ret = ArkFrameCheck(i);
77        if (i == ToUintPtr(FrameType::OPTIMIZED_ENTRY_FRAME) ||
78            i == ToUintPtr(FrameType::ASM_INTERPRETER_ENTRY_FRAME)) {
79            EXPECT_TRUE(ret == true);
80        } else {
81            EXPECT_TRUE(ret == false);
82        }
83    }
84}
85
86/**
87 * @tc.name: IsJsFunctionFrame
88 * @tc.desc: Check whether the result returned through "IsJsFunctionFrame" function is within expectations.
89 * @tc.type: FUNC
90 * @tc.require:
91 */
92HWTEST_F_L0(JsStackInfoTest, TestIsJsFunctionFrame)
93{
94    for (uintptr_t i = 0; i < 25; i++) {
95        bool ret = IsJsFunctionFrame(i);
96        if (i == ToUintPtr(FrameType::ASM_INTERPRETER_FRAME) ||
97            i == ToUintPtr(FrameType::INTERPRETER_CONSTRUCTOR_FRAME) ||
98            i == ToUintPtr(FrameType::INTERPRETER_FRAME) ||
99            i == ToUintPtr(FrameType::INTERPRETER_FAST_NEW_FRAME)) {
100            EXPECT_TRUE(ret == true);
101        } else {
102            EXPECT_TRUE(ret == false);
103        }
104    }
105}
106
107/**
108 * @tc.name: IsFastJitFunctionFrame
109 * @tc.desc: Check whether the result returned through "IsFastJitFunctionFrame" function is within expectations.
110 * @tc.type: FUNC
111 * @tc.require:
112 */
113HWTEST_F_L0(JsStackInfoTest, TestIsFastJitFunctionFrame)
114{
115    for (uintptr_t i = 0; i < 25; i++) {
116        bool ret = IsFastJitFunctionFrame(i);
117        if (i == ToUintPtr(FrameType::FASTJIT_FUNCTION_FRAME) ||
118            i == ToUintPtr(FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME)) {
119            EXPECT_TRUE(ret == true);
120        } else {
121            EXPECT_TRUE(ret == false);
122        }
123    }
124}
125
126/**
127 * @tc.name: IsNativeFunctionFrame
128 * @tc.desc: Check whether the result returned through "IsNativeFunctionFrame" function is within expectations.
129 * @tc.type: FUNC
130 * @tc.require:
131 */
132HWTEST_F_L0(JsStackInfoTest, TestIsNativeFunctionFrame)
133{
134    for (uintptr_t i = 0; i < 25; i++) {
135        bool ret = IsNativeFunctionFrame(i);
136        if (i == ToUintPtr(FrameType::OPTIMIZED_FRAME) ||
137            i == ToUintPtr(FrameType::BASELINE_BUILTIN_FRAME) ||
138            i == ToUintPtr(FrameType::ASM_BRIDGE_FRAME) ||
139            i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME) ||
140            i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME) ||
141            i == ToUintPtr(FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME) ||
142            i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_FRAME) ||
143            i == ToUintPtr(FrameType::LEAVE_FRAME) ||
144            i == ToUintPtr(FrameType::LEAVE_FRAME_WITH_ARGV) ||
145            i == ToUintPtr(FrameType::BUILTIN_CALL_LEAVE_FRAME) ||
146            i == ToUintPtr(FrameType::BUILTIN_FRAME) ||
147            i == ToUintPtr(FrameType::BUILTIN_ENTRY_FRAME) ||
148            i == ToUintPtr(FrameType::BUILTIN_FRAME_WITH_ARGV) ||
149            i == ToUintPtr(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME) ||
150            i == ToUintPtr(FrameType::ASM_INTERPRETER_BRIDGE_FRAME)) {
151            EXPECT_TRUE(ret == true);
152        } else {
153            EXPECT_TRUE(ret == false);
154        }
155    }
156}
157
158/**
159 * @tc.name: IsAotFunctionFrame
160 * @tc.desc: Check whether the result returned through "IsAotFunctionFrame" function is within expectations.
161 * @tc.type: FUNC
162 * @tc.require:
163 */
164HWTEST_F_L0(JsStackInfoTest, TestIsAotFunctionFrame)
165{
166    for (uintptr_t i = 0; i < 25; i++) {
167        bool ret = IsAotFunctionFrame(i);
168        if (i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_FRAME) ||
169            i == ToUintPtr(FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME)) {
170            EXPECT_TRUE(ret == true);
171        } else {
172            EXPECT_TRUE(ret == false);
173        }
174    }
175}
176
177/**
178 * @tc.name: ReadMethodInfo
179 * @tc.desc: Check whether the result returned through "ReadMethodInfo" function is within expectations.
180 * @tc.type: FUNC
181 * @tc.require:
182 */
183HWTEST_F_L0(JsStackInfoTest, TestReadMethodInfo)
184{
185    const char *filename = "__JSPandaFileManagerTest1.pa";
186    const char *data = R"(
187        .function void foo() {
188            return
189        }
190    )";
191    pandasm::Parser parser;
192    auto res = parser.Parse(data);
193    auto file = pandasm::AsmEmitter::Emit(res.Value());
194    auto jsPandaFile = std::make_shared<JSPandaFile>(file.release(), CString(filename));
195    EXPECT_TRUE(jsPandaFile != nullptr);
196    CVector<MethodInfo> result;
197    const panda_file::File *pf = jsPandaFile->GetPandaFile();
198    Span<const uint32_t> classIndexes = jsPandaFile->GetClasses();
199    for (const uint32_t index : classIndexes) {
200        panda_file::File::EntityId classId(index);
201        if (jsPandaFile->IsExternal(classId)) {
202            continue;
203        }
204        panda_file::ClassDataAccessor cda(*pf, classId);
205        cda.EnumerateMethods([&result, jsPandaFile](panda_file::MethodDataAccessor &mda) {
206            auto info = JSStackTrace::ReadMethodInfo(mda);
207            if (!info) {
208                return;
209            }
210            result.push_back(info.value());
211        });
212    }
213    EXPECT_TRUE(result.size() > 0);
214}
215
216/**
217 * @tc.name: ReadAllMethodInfos
218 * @tc.desc: Check whether the result returned through "ReadAllMethodInfos" function is within expectations.
219 * @tc.type: FUNC
220 * @tc.require:
221 */
222HWTEST_F_L0(JsStackInfoTest, TestReadAllMethodInfos)
223{
224    const char *filename = "__JsStackInfoTest.pa";
225    const char *data = R"(
226        .function void foo() {
227            return
228        }
229    )";
230    pandasm::Parser parser;
231    auto res = parser.Parse(data);
232    auto file = pandasm::AsmEmitter::Emit(res.Value());
233    auto pf = std::make_shared<JSPandaFile>(file.release(), CString(filename));
234    EXPECT_TRUE(pf != nullptr);
235    auto methods = JSStackTrace::ReadAllMethodInfos(pf);
236    EXPECT_TRUE(methods.size() > 0);
237    pf = nullptr;
238    methods = JSStackTrace::ReadAllMethodInfos(pf);
239    EXPECT_TRUE(methods.size() == 0);
240}
241
242/**
243 * @tc.name: TranslateByteCodePc
244 * @tc.desc: Check whether the result returned through "TranslateByteCodePc" function is within expectations.
245 * @tc.type: FUNC
246 * @tc.require:
247 */
248HWTEST_F_L0(JsStackInfoTest, TestTranslateByteCodePc)
249{
250    CVector<MethodInfo> vec = {
251        {0, 0, 24},
252        {1, 24, 30},
253        {2, 54, 56},
254        {3, 110, 60}
255    };
256    uintptr_t realPc = 115;
257
258    auto ret = JSStackTrace::TranslateByteCodePc(realPc, vec);
259    EXPECT_TRUE(ret != std::nullopt);
260
261    vec.clear();
262    ret = JSStackTrace::TranslateByteCodePc(realPc, vec);
263    EXPECT_TRUE(ret == std::nullopt);
264
265    vec.push_back({2, 54, 56});
266    ret = JSStackTrace::TranslateByteCodePc(realPc, vec);
267    EXPECT_TRUE(ret == std::nullopt);
268}
269
270/**
271 * @tc.name: ParseJsFrameInfo
272 * @tc.desc: Check whether the result returned through "ParseJsFrameInfo" function is within expectations.
273 * @tc.type: FUNC
274 * @tc.require:
275 */
276HWTEST_F_L0(JsStackInfoTest, TestParseJsFrameInfo)
277{
278    const char *filename = "__JsStackInfoTest.pa";
279    const char *data = R"(
280        .function void foo() {
281            return
282        }
283    )";
284    pandasm::Parser parser;
285    auto res = parser.Parse(data);
286    auto file = pandasm::AsmEmitter::Emit(res.Value());
287    auto jsPandaFile = std::make_shared<JSPandaFile>(file.release(), CString(filename));
288    EXPECT_TRUE(jsPandaFile != nullptr);
289    auto debugExtractor = std::make_unique<DebugInfoExtractor>(jsPandaFile.get());
290    auto methods = JSStackTrace::ReadAllMethodInfos(jsPandaFile);
291    uintptr_t offset = 0;
292    JsFunction jsFunction;
293    ParseJsFrameInfo(jsPandaFile.get(), debugExtractor.get(), EntityId(methods[0].methodId), offset, jsFunction);
294    EXPECT_TRUE(std::string(jsFunction.functionName) == "foo");
295}
296
297/**
298 * @tc.name: ArkParseJsFrameInfo
299 * @tc.desc: Check whether the result returned through "ArkCreateJSSymbolExtractor" function is within expectations;
300 *           Check whether the result returned through "ArkParseJsFrameInfo" function is within expectations;
301 *           Check whether the result returned through "ArkDestoryJSSymbolExtractor" function is within expectations.
302 * @tc.type: FUNC
303 * @tc.require:
304 */
305HWTEST_F_L0(JsStackInfoTest, TestArkParseJsFrameInfo)
306{
307    const char *filename1 = "__JsStackInfoTest1.pa";
308    const char *filename2 = "__JsStackInfoTest2.pa";
309    const char *pfdata1 = R"(
310        .function void foo() {
311            return
312        }
313    )";
314    const char *pfdata2 = R"(
315        .language ECMAScript
316        .function any func_main_0(any a0, any a1, any a2) {
317            ldai 1
318            return
319        }
320    )";
321    pandasm::Parser parser1;
322    pandasm::Parser parser2;
323    auto res1 = parser1.Parse(pfdata1);
324    auto res2 = parser2.Parse(pfdata2);
325    auto file1 = pandasm::AsmEmitter::Emit(res1.Value());
326    auto file2 = pandasm::AsmEmitter::Emit(res2.Value());
327    auto jsPandaFile1 = std::make_shared<JSPandaFile>(file1.release(), CString(filename1));
328    auto jsPandaFile2 = std::make_shared<JSPandaFile>(file2.release(), CString(filename2));
329    EXPECT_TRUE(jsPandaFile1 != nullptr);
330    EXPECT_TRUE(jsPandaFile2 != nullptr);
331    auto debugExtractor1 = std::make_unique<DebugInfoExtractor>(jsPandaFile1.get());
332    auto debugExtractor2 = std::make_unique<DebugInfoExtractor>(jsPandaFile2.get());
333    auto methods1 = JSStackTrace::ReadAllMethodInfos(jsPandaFile1);
334    auto methods2 = JSStackTrace::ReadAllMethodInfos(jsPandaFile2);
335
336    uintptr_t byteCodePc1 = methods1[0].codeBegin;
337    uintptr_t byteCodePc2 = methods2[0].codeBegin;
338    uintptr_t methodId1 = methods1[0].methodId;
339    uintptr_t methodId2 = methods2[0].methodId;
340    uintptr_t mapBase1 = reinterpret_cast<uintptr_t>(jsPandaFile1->GetHeader());
341    uintptr_t mapBase2 = reinterpret_cast<uintptr_t>(jsPandaFile2->GetHeader());
342    uintptr_t loadOffset1 = 0;
343    uintptr_t loadOffset2 = 0;
344    const uint8_t* data1 = jsPandaFile1->GetPandaFile()->GetBase();
345    const uint8_t* data2 = jsPandaFile2->GetPandaFile()->GetBase();
346    uint64_t dataSize1 = jsPandaFile1->GetFileSize();
347    uint64_t dataSize2 = jsPandaFile2->GetFileSize();
348    uintptr_t extractorptr1 = 0;
349    uintptr_t extractorptr2 = 0;
350    JsFunction jsFunction1;
351    JsFunction jsFunction2;
352
353    auto ret = ark_create_js_symbol_extractor(&extractorptr1);
354    EXPECT_TRUE(ret == 1);
355    EXPECT_TRUE(extractorptr1 != 0);
356    ret = ark_create_js_symbol_extractor(&extractorptr2);
357    EXPECT_TRUE(ret == 1);
358    EXPECT_TRUE(extractorptr2 != 0);
359
360    ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1,
361        reinterpret_cast<uint8_t *>(const_cast<char*>(pfdata1)),
362        strlen(pfdata1) + 1, extractorptr1, &jsFunction1);
363    EXPECT_TRUE(ret == -1);
364
365    ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1,
366        const_cast<uint8_t*>(data1), dataSize1, extractorptr1, &jsFunction1);
367    EXPECT_TRUE(ret == 1);
368    EXPECT_TRUE(std::string(jsFunction1.functionName) == "foo");
369
370    ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1,
371        const_cast<uint8_t*>(data1), dataSize1 + 1, 0, &jsFunction1);
372    EXPECT_TRUE(ret == -1);
373
374    ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1,
375        nullptr, 0, extractorptr1, &jsFunction1);
376    EXPECT_TRUE(ret == -1);
377
378    ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1,
379        const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
380    EXPECT_TRUE(ret == -1);
381
382    ret = ark_parse_js_frame_info(byteCodePc2, methodId1, mapBase1, loadOffset1,
383        const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
384    EXPECT_TRUE(ret == -1);
385
386    ret = ark_parse_js_frame_info(byteCodePc2, methodId2, mapBase1, loadOffset1,
387        const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
388    EXPECT_TRUE(ret == -1);
389
390    ret = ark_parse_js_frame_info(byteCodePc2, methodId2, mapBase2, loadOffset2,
391        const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction2);
392    EXPECT_TRUE(ret == 1);
393    EXPECT_TRUE(std::string(jsFunction2.functionName) == "func_main_0");
394
395    ret = ark_destory_js_symbol_extractor(extractorptr1);
396    EXPECT_TRUE(ret == 1);
397
398    ret = ark_destory_js_symbol_extractor(extractorptr2);
399    EXPECT_TRUE(ret == 1);
400}
401
402/**
403 * @tc.name: BuildJsStackInfo
404 * @tc.desc: Check whether the result returned through "BuildJsStackInfo" function is within expectations;
405 * @tc.type: FUNC
406 * @tc.require:
407 */
408HWTEST_F_L0(JsStackInfoTest, TestBuildJsStackInfo)
409{
410    auto jsFrame = JsStackInfo::BuildJsStackInfo(thread);
411    EXPECT_TRUE(jsFrame.empty());
412}
413
414/**
415 * @tc.name: ark_destory_local
416 * @tc.desc: Check whether the result returned through "ark_destory_local" function is within expectations;
417 * @tc.type: FUNC
418 * @tc.require:
419 */
420HWTEST_F_L0(JsStackInfoTest, TestArkDestoryLocal)
421{
422    auto ret = ark_destory_local(); // Direct destruct without creating Pointers
423    EXPECT_TRUE(ret);
424    auto trace = JSStackTrace::GetInstance();
425    EXPECT_TRUE(trace != nullptr);
426    ret = ark_destory_local(); // destory
427    EXPECT_TRUE(ret);
428    ret = ark_destory_local(); // multiple destory
429    EXPECT_TRUE(ret);
430
431    // Create and destruct multiple times within the process
432    trace = JSStackTrace::GetInstance();
433    EXPECT_TRUE(trace != nullptr);
434    ret = ark_destory_local();
435    EXPECT_TRUE(ret);
436}
437
438HWTEST_F_L0(JsStackInfoTest, TestStepArk__001)
439{
440    void *ctx = nullptr;
441    uintptr_t sp = 0;
442    uintptr_t pc = 0;
443    bool isJsFrame = true;
444    uintptr_t frame[10][3];
445    uintptr_t fp[10];
446    for (int i = 0; i < 10; i++) {
447        frame[i][0] = 0;
448        frame[i][1] = 0;
449    }
450    fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8;
451    for (int i = 1; i < 10; i++) {
452        fp[i] = fp[i-1] + 24;
453    }
454    frame[0][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
455    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[0], &sp, &pc, nullptr, &isJsFrame));
456    frame[1][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_FAST_NEW_FRAME);
457    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[1], &sp, &pc, nullptr, &isJsFrame));
458    frame[2][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME);
459    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[2], &sp, &pc, nullptr, &isJsFrame));
460    frame[3][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME);
461    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[3], &sp, &pc, nullptr, &isJsFrame));
462    frame[4][2] = static_cast<uintptr_t>(FrameType::BUILTIN_ENTRY_FRAME);
463    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[4], &sp, &pc, nullptr, &isJsFrame));
464    frame[5][2] = static_cast<uintptr_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME);
465    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[5], &sp, &pc, nullptr, &isJsFrame));
466    frame[6][2] = static_cast<uintptr_t>(FrameType::BASELINE_BUILTIN_FRAME);
467    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[6], &sp, &pc, nullptr, &isJsFrame));
468    frame[7][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME);
469    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[7], &sp, &pc, nullptr, &isJsFrame));
470    frame[8][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME);
471    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[8], &sp, &pc, nullptr, &isJsFrame));
472    frame[9][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME_WITH_ARGV);
473    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[9], &sp, &pc, nullptr, &isJsFrame));
474}
475
476HWTEST_F_L0(JsStackInfoTest, TestStepArk__002)
477{
478    void *ctx = nullptr;
479    uintptr_t sp = 0;
480    uintptr_t pc = 0;
481    bool isJsFrame = true;
482    uintptr_t frame[30][3];
483    uintptr_t fp[30];
484    for (int i = 0; i < 30; i++) {
485        frame[i][0] = 0;
486        frame[i][1] = 0;
487    }
488    fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8;
489    for (int i = 1; i < 30; i++) {
490        fp[i] = fp[i-1] + 24;
491    }
492    frame[0][2] = static_cast<uintptr_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME);
493    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[0], &sp, &pc, nullptr, &isJsFrame));
494    frame[1][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_FRAME);
495    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[1], &sp, &pc, nullptr, &isJsFrame));
496    frame[2][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME);
497    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[2], &sp, &pc, nullptr, &isJsFrame));
498    frame[3][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME);
499    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[3], &sp, &pc, nullptr, &isJsFrame));
500    frame[4][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
501    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[4], &sp, &pc, nullptr, &isJsFrame));
502    frame[5][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_ENTRY_FRAME);
503    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[5], &sp, &pc, nullptr, &isJsFrame));
504    frame[6][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME);
505    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[6], &sp, &pc, nullptr, &isJsFrame));
506    frame[7][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME);
507    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[7], &sp, &pc, nullptr, &isJsFrame));
508    frame[8][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
509    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[8], &sp, &pc, nullptr, &isJsFrame));
510    frame[9][2] = 100;
511    ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[9], &sp, &pc, nullptr, &isJsFrame));
512}
513}  // namespace panda::test