• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 using namespace panda::ecmascript;
26 
27 namespace panda::test {
28 class JsStackInfoTest : public testing::Test {
29 public:
SetUpTestCase()30     static void SetUpTestCase()
31     {
32         GTEST_LOG_(INFO) << "SetUpTestCase";
33     }
34 
TearDownTestCase()35     static void TearDownTestCase()
36     {
37         GTEST_LOG_(INFO) << "TearDownCase";
38     }
39 
SetUp()40     void SetUp() override
41     {
42         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
43         instance->SetEnableForceGC(false);
44     }
45 
TearDown()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 
ToUintPtr(FrameType frame)56 uintptr_t ToUintPtr(FrameType frame)
57 {
58     return static_cast<uintptr_t>(frame);
59 }
60 
ReadMemFunc(void * ctx,uintptr_t addr,uintptr_t * value)61 bool 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  */
HWTEST_F_L0(JsStackInfoTest,TestArkFrameCheck)73 HWTEST_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  */
HWTEST_F_L0(JsStackInfoTest,TestIsJsFunctionFrame)92 HWTEST_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  */
HWTEST_F_L0(JsStackInfoTest,TestIsFastJitFunctionFrame)113 HWTEST_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  */
HWTEST_F_L0(JsStackInfoTest,TestIsNativeFunctionFrame)132 HWTEST_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  */
HWTEST_F_L0(JsStackInfoTest,TestIsAotFunctionFrame)164 HWTEST_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  */
HWTEST_F_L0(JsStackInfoTest,TestReadMethodInfo)183 HWTEST_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), CreateMode::DFX);
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  */
HWTEST_F_L0(JsStackInfoTest,TestReadAllMethodInfos)222 HWTEST_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), CreateMode::DFX);
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  */
HWTEST_F_L0(JsStackInfoTest,TestTranslateByteCodePc)248 HWTEST_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  */
HWTEST_F_L0(JsStackInfoTest,TestParseJsFrameInfo)276 HWTEST_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), CreateMode::DFX);
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  */
HWTEST_F_L0(JsStackInfoTest,TestArkParseJsFrameInfo)305 HWTEST_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), CreateMode::DFX);
328     auto jsPandaFile2 = std::make_shared<JSPandaFile>(file2.release(), CString(filename2), CreateMode::DFX);
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 mapBase1 = reinterpret_cast<uintptr_t>(jsPandaFile1->GetHeader());
339     uintptr_t mapBase2 = reinterpret_cast<uintptr_t>(jsPandaFile2->GetHeader());
340     uintptr_t loadOffset1 = 0;
341     uintptr_t loadOffset2 = 0;
342     const uint8_t* data1 = jsPandaFile1->GetPandaFile()->GetBase();
343     const uint8_t* data2 = jsPandaFile2->GetPandaFile()->GetBase();
344     uint64_t dataSize1 = jsPandaFile1->GetFileSize();
345     uint64_t dataSize2 = jsPandaFile2->GetFileSize();
346     uintptr_t extractorptr1 = 0;
347     uintptr_t extractorptr2 = 0;
348     JsFunction jsFunction1;
349     JsFunction jsFunction2;
350 
351     auto ret = ark_create_js_symbol_extractor(&extractorptr1);
352     EXPECT_TRUE(ret == 1);
353     EXPECT_TRUE(extractorptr1 != 0);
354     ret = ark_create_js_symbol_extractor(&extractorptr2);
355     EXPECT_TRUE(ret == 1);
356     EXPECT_TRUE(extractorptr2 != 0);
357 
358     ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
359         reinterpret_cast<uint8_t *>(const_cast<char*>(pfdata1)),
360         strlen(pfdata1) + 1, extractorptr1, &jsFunction1);
361     EXPECT_TRUE(ret == -1);
362 
363     ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
364         const_cast<uint8_t*>(data1), dataSize1, extractorptr1, &jsFunction1);
365     EXPECT_TRUE(ret == 1);
366     EXPECT_TRUE(std::string(jsFunction1.functionName) == "foo");
367 
368     ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
369         const_cast<uint8_t*>(data1), dataSize1 + 1, 0, &jsFunction1);
370     EXPECT_TRUE(ret == -1);
371 
372     ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
373         nullptr, 0, extractorptr1, &jsFunction1);
374     EXPECT_TRUE(ret == -1);
375 
376     ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
377         const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
378     EXPECT_TRUE(ret == -1);
379 
380     ret = ark_parse_js_frame_info(byteCodePc2, mapBase1, loadOffset1,
381         const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
382     EXPECT_TRUE(ret == -1);
383 
384     ret = ark_parse_js_frame_info(byteCodePc2, mapBase1, loadOffset1,
385         const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
386     EXPECT_TRUE(ret == -1);
387 
388     ret = ark_parse_js_frame_info(byteCodePc2, mapBase2, loadOffset2,
389         const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction2);
390     EXPECT_TRUE(ret == 1);
391     EXPECT_TRUE(std::string(jsFunction2.functionName) == "func_main_0");
392 
393     ret = ark_destory_js_symbol_extractor(extractorptr1);
394     EXPECT_TRUE(ret == 1);
395 
396     ret = ark_destory_js_symbol_extractor(extractorptr2);
397     EXPECT_TRUE(ret == 1);
398 }
399 
400 /**
401  * @tc.name: BuildJsStackInfo
402  * @tc.desc: Check whether the result returned through "BuildJsStackInfo" function is within expectations;
403  * @tc.type: FUNC
404  * @tc.require:
405  */
HWTEST_F_L0(JsStackInfoTest,TestBuildJsStackInfo)406 HWTEST_F_L0(JsStackInfoTest, TestBuildJsStackInfo)
407 {
408     auto jsFrame = JsStackInfo::BuildJsStackInfo(thread);
409     EXPECT_TRUE(jsFrame.empty());
410 }
411 
412 /**
413  * @tc.name: ark_destory_local
414  * @tc.desc: Check whether the result returned through "ark_destory_local" function is within expectations;
415  * @tc.type: FUNC
416  * @tc.require:
417  */
HWTEST_F_L0(JsStackInfoTest,TestArkDestoryLocal)418 HWTEST_F_L0(JsStackInfoTest, TestArkDestoryLocal)
419 {
420     auto ret = ark_destroy_local(); // Direct destruct without creating Pointers
421     EXPECT_TRUE(ret);
422     ret = ark_create_local(); // ref count = 1
423     ret = ark_create_local(); // ref count = 2
424     EXPECT_TRUE(ret);
425     auto trace = JSStackTrace::GetInstance();
426     EXPECT_TRUE(trace != nullptr);
427     ret = ark_destroy_local(); // ref count = 1
428     trace = JSStackTrace::GetInstance();
429     EXPECT_TRUE(trace != nullptr);
430     ret = ark_destroy_local(); // ref count = 0
431     trace = JSStackTrace::GetInstance();
432     EXPECT_TRUE(trace == nullptr);
433     EXPECT_TRUE(ret);
434     ret = ark_destroy_local(); // multiple destory
435     EXPECT_TRUE(ret);
436 
437     // Create and destruct multiple times within the process
438     ret = ark_create_local(); // ref count = 1
439     trace = JSStackTrace::GetInstance();
440     EXPECT_TRUE(trace != nullptr);
441     ret = ark_destroy_local();
442     EXPECT_TRUE(ret);
443 }
444 
HWTEST_F_L0(JsStackInfoTest,TestStepArk__001)445 HWTEST_F_L0(JsStackInfoTest, TestStepArk__001)
446 {
447     void *ctx = nullptr;
448     uintptr_t sp = 0;
449     uintptr_t pc = 0;
450     bool isJsFrame = true;
451     uintptr_t frame[10][3];
452     uintptr_t fp[10];
453     for (int i = 0; i < 10; i++) {
454         frame[i][0] = 0;
455         frame[i][1] = 0;
456     }
457     fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8;
458     for (int i = 1; i < 10; i++) {
459         fp[i] = fp[i-1] + 24;
460     }
461     ArkStepParam arkStepParam{ &fp[0], &sp, &pc, &isJsFrame };
462     frame[0][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
463     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
464     frame[1][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_FAST_NEW_FRAME);
465     arkStepParam.fp = &fp[1];
466     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
467     frame[2][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME);
468     arkStepParam.fp = &fp[2];
469     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
470     frame[3][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME);
471     arkStepParam.fp = &fp[3];
472     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
473     frame[4][2] = static_cast<uintptr_t>(FrameType::BUILTIN_ENTRY_FRAME);
474     arkStepParam.fp = &fp[4];
475     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
476     frame[5][2] = static_cast<uintptr_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME);
477     arkStepParam.fp = &fp[5];
478     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
479     frame[6][2] = static_cast<uintptr_t>(FrameType::BASELINE_BUILTIN_FRAME);
480     arkStepParam.fp = &fp[6];
481     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
482     frame[7][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME);
483     arkStepParam.fp = &fp[7];
484     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
485     frame[8][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME);
486     arkStepParam.fp = &fp[8];
487     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
488     frame[9][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME_WITH_ARGV);
489     arkStepParam.fp = &fp[9];
490     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
491 }
492 
HWTEST_F_L0(JsStackInfoTest,TestStepArk__002)493 HWTEST_F_L0(JsStackInfoTest, TestStepArk__002)
494 {
495     void *ctx = nullptr;
496     uintptr_t sp = 0;
497     uintptr_t pc = 0;
498     bool isJsFrame = true;
499     uintptr_t frame[30][3];
500     uintptr_t fp[30];
501     for (int i = 0; i < 30; i++) {
502         frame[i][0] = 0;
503         frame[i][1] = 0;
504     }
505     fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8;
506     for (int i = 1; i < 30; i++) {
507         fp[i] = fp[i-1] + 24;
508     }
509     ArkStepParam arkStepParam{ &fp[0], &sp, &pc, &isJsFrame };
510     frame[0][2] = static_cast<uintptr_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME);
511     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
512     frame[1][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_FRAME);
513     arkStepParam.fp = &fp[1];
514     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
515     frame[2][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME);
516     arkStepParam.fp = &fp[2];
517     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
518     frame[3][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME);
519     arkStepParam.fp = &fp[3];
520     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
521     frame[4][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
522     arkStepParam.fp = &fp[4];
523     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
524     frame[5][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_ENTRY_FRAME);
525     arkStepParam.fp = &fp[5];
526     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
527     frame[6][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME);
528     arkStepParam.fp = &fp[6];
529     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
530     frame[7][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME);
531     arkStepParam.fp = &fp[7];
532     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
533     frame[8][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
534     arkStepParam.fp = &fp[8];
535     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
536     frame[9][2] = 100;
537     arkStepParam.fp = &fp[9];
538     ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
539 }
540 
HWTEST_F_L0(JsStackInfoTest,TestLocalParseJsFrameInfo__001)541 HWTEST_F_L0(JsStackInfoTest, TestLocalParseJsFrameInfo__001)
542 {
543     const char *filename = "__JsStackInfoTest1.pa";
544     const char *pfdata = R"(
545         .function void foo() {
546             return
547         }
548     )";
549 
550     auto pfManager = JSPandaFileManager::GetInstance();
551 
552     pandasm::Parser parser1;
553     auto res = parser1.Parse(pfdata);
554     auto file = pandasm::AsmEmitter::Emit(res.Value());
555     auto jsPandaFile = pfManager->NewJSPandaFile(file.release(), CString(filename));
556     pfManager->AddJSPandaFile(jsPandaFile);
557     EXPECT_TRUE(jsPandaFile != nullptr);
558     auto methods = JSStackTrace::ReadAllMethodInfos(jsPandaFile);
559 
560     uintptr_t byteCodePc = methods[0].codeBegin;
561     uintptr_t mapBase = reinterpret_cast<uintptr_t>(jsPandaFile->GetHeader());
562     uintptr_t loadOffset = 0;
563     JsFunction jsFunction;
564 
565     // Incorrect invocation demonstration
566     auto ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
567     EXPECT_TRUE(ret == -1);
568 
569     // Correct invocation demonstration
570     ark_create_local();
571     ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
572     EXPECT_TRUE(ret == 1);
573 
574     ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
575     EXPECT_TRUE(ret == 1);
576 
577     ark_destroy_local();
578 
579     pfManager->RemoveJSPandaFile(jsPandaFile.get());
580 }
581 
HWTEST_F_L0(JsStackInfoTest,TestLocalParseJsFrameInfo__002)582 HWTEST_F_L0(JsStackInfoTest, TestLocalParseJsFrameInfo__002)
583 {
584     const char *filename = "__JsStackInfoTest1.pa";
585     const char *pfdata = R"(
586         .function void foo() {
587             return
588         }
589     )";
590 
591     auto pfManager = JSPandaFileManager::GetInstance();
592 
593     pandasm::Parser parser1;
594     auto res = parser1.Parse(pfdata);
595     auto file = pandasm::AsmEmitter::Emit(res.Value());
596     auto jsPandaFile = pfManager->NewJSPandaFile(file.release(), CString(filename));
597     EXPECT_TRUE(jsPandaFile != nullptr);
598     auto methods = JSStackTrace::ReadAllMethodInfos(jsPandaFile);
599 
600     uintptr_t byteCodePc = methods[0].codeBegin;
601     uintptr_t mapBase = reinterpret_cast<uintptr_t>(jsPandaFile->GetHeader());
602     uintptr_t loadOffset = 0;
603     JsFunction jsFunction;
604 
605     ark_create_local();
606     auto ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
607     ark_destroy_local();
608     // pandafile manager can't find jsPandaFile
609     EXPECT_TRUE(ret == -1);
610 }
611 }  // namespace panda::test