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_ARROW_TEST_H 17#define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_STEPOUT_ARROW_TEST_H 18 19#include "tooling/test/client_utils/test_util.h" 20 21namespace panda::ecmascript::tooling::test { 22class JsStepoutArrowTest : public TestActions { 23public: 24 JsStepoutArrowTest() 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 arrow_func.js 34 {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN}, 35 // break on start 36 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 37 [](auto recv, auto, auto) -> bool { 38 std::unique_ptr<PtJson> json = PtJson::Parse(recv); 39 DebuggerClient debuggerClient(0); 40 debuggerClient.RecvReply(std::move(json)); 41 return true; 42 }}, 43 // set first breakpoint 44 {SocketAction::SEND, "b " DEBUGGER_JS_DIR "arrow_func.js 19"}, 45 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 46 47 // hit breakpoint after resume first time 48 {SocketAction::SEND, "resume"}, 49 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 50 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 51 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 52 [this](auto recv, auto, auto) -> bool { return RecvBreakInfo(recv); }}, 53 54 {SocketAction::SEND, "watch num1"}, 55 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 56 [this](auto recv, auto, auto) -> bool { return RecvWatchInfo(recv, "2"); }}, 57 {SocketAction::SEND, "watch num2"}, 58 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 59 [this](auto recv, auto, auto) -> bool { return RecvWatchInfo(recv, "2"); }}, 60 61 {SocketAction::SEND, "so"}, 62 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 63 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 64 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 65 [this](auto recv, auto, auto) -> bool { return RecvStepoutInfo(recv, "func_main_0", 22); }}, 66 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 67 68 {SocketAction::SEND, "resume"}, 69 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 70 71 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 72 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 73 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, 74 75 // reply success and run 76 {SocketAction::SEND, "success"}, 77 {SocketAction::SEND, "resume"}, 78 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 79 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 80 }; 81 } 82 83 bool RecvBreakInfo(std::string recv) 84 { 85 std::unique_ptr<PtJson> json = PtJson::Parse(recv); 86 Result ret; 87 std::string method = ""; 88 ret = json->GetString("method", &method); 89 if (ret != Result::SUCCESS || method != "Debugger.paused") { 90 return false; 91 } 92 93 std::unique_ptr<PtJson> params = nullptr; 94 ret = json->GetObject("params", ¶ms); 95 if (ret != Result::SUCCESS) { 96 return false; 97 } 98 99 std::unique_ptr<PtJson> hitBreakpoints = nullptr; 100 ret = params->GetArray("hitBreakpoints", &hitBreakpoints); 101 if (ret != Result::SUCCESS) { 102 return false; 103 } 104 105 std::string breakpoint = ""; 106 breakpoint = hitBreakpoints->Get(0)->GetString(); 107 if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || 108 breakpoint.find("18") == std::string::npos) { 109 return false; 110 } 111 112 DebuggerClient debuggerClient(0); 113 debuggerClient.PausedReply(std::move(json)); 114 return true; 115 } 116 117 bool RecvStepoutInfo(std::string recv, std::string funcName, int lineNumber) 118 { 119 std::unique_ptr<PtJson> json = PtJson::Parse(recv); 120 Result ret; 121 std::string method = ""; 122 ret = json->GetString("method", &method); 123 if (ret != Result::SUCCESS || method != "Debugger.paused") { 124 return false; 125 } 126 127 std::unique_ptr<PtJson> params = nullptr; 128 ret = json->GetObject("params", ¶ms); 129 if (ret != Result::SUCCESS) { 130 return false; 131 } 132 133 std::unique_ptr<PtJson> callFrames = nullptr; 134 ret = params->GetArray("callFrames", &callFrames); 135 if (ret != Result::SUCCESS) { 136 return false; 137 } 138 139 std::string functionName = ""; 140 ret = callFrames->Get(0)->GetString("functionName", &functionName); 141 if (ret != Result::SUCCESS || functionName != funcName) { 142 return false; 143 } 144 145 std::unique_ptr<PtJson> location = nullptr; 146 ret = callFrames->Get(0)->GetObject("location", &location); 147 if (ret != Result::SUCCESS) { 148 return false; 149 } 150 151 int lineNum = 0; 152 ret = location->GetInt("lineNumber", &lineNum); 153 if (ret != Result::SUCCESS || lineNum != lineNumber) { 154 return false; 155 } 156 157 DebuggerClient debuggerClient(0); 158 debuggerClient.PausedReply(std::move(json)); 159 return true; 160 } 161 162 bool RecvWatchInfo(std::string recv, std::string var_value) 163 { 164 std::unique_ptr<PtJson> json = PtJson::Parse(recv); 165 Result ret; 166 int id = 0; 167 ret = json->GetInt("id", &id); 168 if (ret != Result::SUCCESS) { 169 return false; 170 } 171 172 std::unique_ptr<PtJson> result = nullptr; 173 ret = json->GetObject("result", &result); 174 if (ret != Result::SUCCESS) { 175 return false; 176 } 177 178 std::unique_ptr<PtJson> watchResult = nullptr; 179 ret = result->GetObject("result", &watchResult); 180 if (ret != Result::SUCCESS) { 181 return false; 182 } 183 184 std::string type = ""; 185 ret = watchResult->GetString("type", &type); 186 if (ret != Result::SUCCESS || type != "number") { 187 return false; 188 } 189 190 std::string value = ""; 191 ret = watchResult->GetString("unserializableValue", &value); 192 if (ret != Result::SUCCESS || value != var_value) { 193 return false; 194 } 195 return true; 196 } 197 198 std::pair<std::string, std::string> GetEntryPoint() override 199 { 200 return {pandaFile_, entryPoint_}; 201 } 202 ~JsStepoutArrowTest() = default; 203 204private: 205 std::string pandaFile_ = DEBUGGER_ABC_DIR "arrow_func.abc"; 206 std::string sourceFile_ = DEBUGGER_JS_DIR "arrow_func.js"; 207 std::string entryPoint_ = "_GLOBAL::func_main_0"; 208}; 209 210std::unique_ptr<TestActions> GetJsStepoutArrowTest() 211{ 212 return std::make_unique<JsStepoutArrowTest>(); 213} 214} // namespace panda::ecmascript::tooling::test 215 216#endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_STEPOUT_ARROW_TEST_H 217