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_SPECIAL_LOCATION_BREAKPOINT_TEST_H 17#define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_SPECIAL_LOCATION_BREAKPOINT_TEST_H 18 19#include "tooling/test/client_utils/test_util.h" 20 21namespace panda::ecmascript::tooling::test { 22class JsSpecialLocationBreakpointTest : public TestActions { 23public: 24 JsSpecialLocationBreakpointTest() 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 step.js 34 {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN}, 35 // break on start 36 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, 37 // set breakpoint 38 {SocketAction::SEND, "b " DEBUGGER_JS_DIR "step.js 16"}, 39 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, 40 [this](auto recv, auto, auto) -> bool { return RecvBreakpointInfo(recv, 15); }}, 41 {SocketAction::SEND, "b " DEBUGGER_JS_DIR "step.js 98"}, 42 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, 43 [this](auto recv, auto, auto) -> bool { return RecvBreakpointInfo(recv, 97); }}, 44 // hit breakpoint on first line 45 {SocketAction::SEND, "resume"}, 46 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 47 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 48 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 49 [this](auto recv, auto, auto) -> bool { return RecvHitBreakInfo(recv, 15); }}, 50 // hit breakpoint on the end of line 51 {SocketAction::SEND, "resume"}, 52 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 53 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 54 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, 55 [this](auto recv, auto, auto) -> bool { return RecvHitBreakInfo(recv, 97); }}, 56 // reply success and run 57 {SocketAction::SEND, "success"}, 58 {SocketAction::SEND, "resume"}, 59 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, 60 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, 61 }; 62 } 63 64 bool RecvBreakpointInfo(std::string recv, int line) 65 { 66 std::unique_ptr<PtJson> json = PtJson::Parse(recv); 67 Result ret; 68 int id = 0; 69 ret = json->GetInt("id", &id); 70 if (ret != Result::SUCCESS) { 71 return false; 72 } 73 74 std::unique_ptr<PtJson> result = nullptr; 75 ret = json->GetObject("result", &result); 76 if (ret != Result::SUCCESS) { 77 return false; 78 } 79 80 std::string breakpointId = ""; 81 ret = result->GetString("breakpointId", &breakpointId); 82 if (ret != Result::SUCCESS || breakpointId.find(sourceFile_) == std::string::npos || 83 breakpointId.find(std::to_string(line)) == std::string::npos) { 84 return false; 85 } 86 87 std::unique_ptr<PtJson> locations = nullptr; 88 ret = result->GetArray("locations", &locations); 89 if (ret != Result::SUCCESS) { 90 return false; 91 } 92 93 int lineNumber = 0; 94 ret = locations->Get(0)->GetInt("lineNumber", &lineNumber); 95 if (ret != Result::SUCCESS || lineNumber != line) { 96 return false; 97 } 98 return true; 99 } 100 101 bool RecvHitBreakInfo(std::string recv, int line) 102 { 103 std::unique_ptr<PtJson> json = PtJson::Parse(recv); 104 Result ret; 105 std::string method = ""; 106 ret = json->GetString("method", &method); 107 if (ret != Result::SUCCESS || method != "Debugger.paused") { 108 return false; 109 } 110 111 std::unique_ptr<PtJson> params = nullptr; 112 ret = json->GetObject("params", ¶ms); 113 if (ret != Result::SUCCESS) { 114 return false; 115 } 116 117 std::unique_ptr<PtJson> hitBreakpoints = nullptr; 118 ret = params->GetArray("hitBreakpoints", &hitBreakpoints); 119 if (ret != Result::SUCCESS) { 120 return false; 121 } 122 123 std::string breakpoint = ""; 124 breakpoint = hitBreakpoints->Get(0)->GetString(); 125 if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || 126 breakpoint.find(std::to_string(line)) == std::string::npos) { 127 return false; 128 } 129 return true; 130 } 131 132 std::pair<std::string, std::string> GetEntryPoint() override 133 { 134 return {pandaFile_, entryPoint_}; 135 } 136 ~JsSpecialLocationBreakpointTest() = default; 137 138private: 139 std::string pandaFile_ = DEBUGGER_ABC_DIR "step.abc"; 140 std::string sourceFile_ = DEBUGGER_JS_DIR "step.js"; 141 std::string entryPoint_ = "_GLOBAL::func_main_0"; 142}; 143 144std::unique_ptr<TestActions> GetJsSpecialLocationBreakpointTest() 145{ 146 return std::make_unique<JsSpecialLocationBreakpointTest>(); 147} 148} // namespace panda::ecmascript::tooling::test 149 150#endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_SPECIAL_LOCATION_BREAKPOINT_TEST_H 151