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#ifndef ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_STEPOUT_RECURSION_TEST_H 17#define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_STEPOUT_RECURSION_TEST_H 18 19#include "tooling/test/client_utils/test_util.h" 20 21namespace panda::ecmascript::tooling::test { 22class JsStepoutRecursionTest : public TestActions { 23public: 24 JsStepoutRecursionTest() 25 { 26 testAction = { 27 {SocketAction::SEND, "enable"}, 28 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 29 {SocketAction::SEND, "runtime-enable"}, 30 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 31 {SocketAction::SEND, "run"}, 32 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 33 // load common_func.js 34 {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN}, 35 // break on start 36 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, 37 // set first breakpoint 38 {SocketAction::SEND, "b " DEBUGGER_JS_DIR "common_func.js 61"}, 39 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 40 41 // hit breakpoint after resume first time 42 {SocketAction::SEND, "resume"}, 43 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 44 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 45 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, 46 47 {SocketAction::SEND, "so"}, 48 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 49 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 50 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 51 [this](auto recv, auto, auto) -> bool { return RecvStepoutInfo(recv, "factorial", 60); }}, 52 {SocketAction::SEND, "so"}, 53 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 54 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 55 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 56 [this](auto recv, auto, auto) -> bool { return RecvStepoutInfo(recv, "factorial", 60); }}, 57 {SocketAction::SEND, "so"}, 58 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 59 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 60 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 61 [this](auto recv, auto, auto) -> bool { return RecvStepoutInfo(recv, "factorial", 60); }}, 62 {SocketAction::SEND, "so"}, 63 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 64 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 65 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 66 [this](auto recv, auto, auto) -> bool { return RecvStepoutInfo(recv, "factorial", 60); }}, 67 68 // reply success and run 69 {SocketAction::SEND, "success"}, 70 {SocketAction::SEND, "resume"}, 71 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 72 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 73 }; 74 } 75 76 bool RecvStepoutInfo(std::string recv, std::string funcName, int lineNumber) 77 { 78 std::unique_ptr<PtJson> json = PtJson::Parse(recv); 79 Result ret; 80 std::string method = ""; 81 ret = json->GetString("method", &method); 82 if (ret != Result::SUCCESS || method != "Debugger.paused") { 83 return false; 84 } 85 86 std::unique_ptr<PtJson> params = nullptr; 87 ret = json->GetObject("params", ¶ms); 88 if (ret != Result::SUCCESS) { 89 return false; 90 } 91 92 std::unique_ptr<PtJson> callFrames = nullptr; 93 ret = params->GetArray("callFrames", &callFrames); 94 if (ret != Result::SUCCESS) { 95 return false; 96 } 97 98 std::string functionName = ""; 99 ret = callFrames->Get(0)->GetString("functionName", &functionName); 100 if (ret != Result::SUCCESS || functionName != funcName) { 101 return false; 102 } 103 104 std::unique_ptr<PtJson> location = nullptr; 105 ret = callFrames->Get(0)->GetObject("location", &location); 106 if (ret != Result::SUCCESS) { 107 return false; 108 } 109 110 int lineNum = 0; 111 ret = location->GetInt("lineNumber", &lineNum); 112 if (ret != Result::SUCCESS || lineNum != lineNumber) { 113 return false; 114 } 115 116 DebuggerClient debuggerClient(0); 117 debuggerClient.PausedReply(std::move(json)); 118 return true; 119 } 120 121 std::pair<std::string, std::string> GetEntryPoint() override 122 { 123 return {pandaFile_, entryPoint_}; 124 } 125 ~JsStepoutRecursionTest() = default; 126 127private: 128 std::string pandaFile_ = DEBUGGER_ABC_DIR "common_func.abc"; 129 std::string sourceFile_ = DEBUGGER_JS_DIR "common_func.js"; 130 std::string entryPoint_ = "_GLOBAL::func_main_0"; 131}; 132 133std::unique_ptr<TestActions> GetJsStepoutRecursionTest() 134{ 135 return std::make_unique<JsStepoutRecursionTest>(); 136} 137} // namespace panda::ecmascript::tooling::test 138 139#endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_STEPOUT_RECURSION_TEST_H 140