• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_UTILS_TESTCASES_JS_DROP_FRAME_TEST_H
17 #define ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_DROP_FRAME_TEST_H
18 
19 #include "test/utils/test_util.h"
20 
21 namespace panda::ecmascript::tooling::test {
22 class JsDropFrameTest : public TestEvents {
23 public:
JsDropFrameTest()24     JsDropFrameTest()
25     {
26         channel_ = new JsDropFrameTestChannel();
27 
28         breakpoint = [this](const JSPtLocation &location) {
29             ASSERT_TRUE(location.GetMethodId().IsValid());
30             ++breakpointCounter_;
31             debugger_->NotifyPaused(location, PauseReason::INSTRUMENTATION);
32             static_cast<JsDropFrameTestChannel *>(channel_)->IncreaseCheckVariableCounter();
33             DropFrameIfChecked();
34             TestUtil::SuspendUntilContinue(DebugEvent::BREAKPOINT, location);
35             return true;
36         };
37 
38         singleStep = [this](const JSPtLocation &location) {
39             if (debugger_->NotifySingleStep(location)) {
40                 debugger_->NotifyPaused({}, PauseReason::INSTRUMENTATION);
41                 static_cast<JsDropFrameTestChannel *>(channel_)->IncreaseCheckVariableCounter();
42                 TestUtil::SuspendUntilContinue(DebugEvent::CHECK_COMPLETE);
43                 DropFrameIfChecked();
44                 TestUtil::SuspendUntilContinue(DebugEvent::DROPFRAME);
45                 return true;
46             }
47             return false;
48         };
49 
50         loadModule = [this](std::string_view moduleName) {
51             static_cast<JsDropFrameTestChannel *>(channel_)->Initial(vm_, runtime_);
52             runtime_->Enable();
53             size_t breakpoint[POINTER_SIZE][LINE_COLUMN] =
54                 {{26, 0}, {42, 0}, {57, 0}, {69, 0}, {87, 0}, {100, 0}, {117, 0}}; // 0-based
55             SetJSPtLocation(breakpoint[0], POINTER_SIZE, pointerLocations_);
56             InitBreakpointOpQueue();
57             TestUtil::SuspendUntilContinue(DebugEvent::LOAD_MODULE);
58             ASSERT_EQ(moduleName, pandaFile_);
59             ASSERT_TRUE(debugger_->NotifyScriptParsed(0, pandaFile_));
60             auto condFuncRef = FunctionRef::Undefined(vm_);
61             for (auto &iter : pointerLocations_) {
62                 auto ret = debugInterface_->SetBreakpoint(iter, condFuncRef);
63                 ASSERT_TRUE(ret);
64             }
65             return true;
66         };
67 
68         scenario = [this]() {
69             TestUtil::WaitForLoadModule();
70             TestUtil::Continue();
71             for (size_t index = 0; index < POINTER_SIZE; index++) {
72                 for (size_t hitCount = 0; hitCount < breakpointHitTimes[index]; hitCount++) {
73                     TestUtil::WaitForBreakpoint(pointerLocations_.at(index));
74                     TestUtil::Continue();
75                     while (dropFrameChecked_) {
76                         dropFrameChecked_ = false;
77                         TestUtil::WaitForCheckComplete();
78                         TestUtil::Continue();
79                         TestUtil::WaitForDropframe();
80                         dropframeCounter_++;
81                         TestUtil::Continue();
82                     }
83                 }
84                 auto ret = debugInterface_->RemoveBreakpoint(pointerLocations_.at(index));
85                 ASSERT_TRUE(ret);
86             }
87             ASSERT_EXITED();
88             return true;
89         };
90 
91         vmDeath = [this]() {
92             ASSERT_EQ(breakpointCounter_, 29U);  // a total of 29 times hitting breakpoints
93             ASSERT_EQ(dropframeCounter_, 23U); // a total of 23 times dropping frames
94             return true;
95         };
96     }
97 
GetEntryPoint()98     std::pair<std::string, std::string> GetEntryPoint() override
99     {
100         return {pandaFile_, entryPoint_};
101     }
~JsDropFrameTest()102     ~JsDropFrameTest()
103     {
104         delete channel_;
105         channel_ = nullptr;
106     }
107 
108 private:
109     class JsDropFrameTestChannel : public TestChannel {
110     public:
111         JsDropFrameTestChannel() = default;
112         ~JsDropFrameTestChannel() = default;
Initial(const EcmaVM * vm,RuntimeImpl * runtime)113         void Initial(const EcmaVM *vm, RuntimeImpl *runtime)
114         {
115             vm_ = vm;
116             runtime_ = runtime;
117         }
118 
SendNotification(const PtBaseEvents & events)119         void SendNotification(const PtBaseEvents &events) override
120         {
121             const static std::vector<std::function<bool(const PtBaseEvents &events)>> eventList = {
122                 [](const PtBaseEvents &events) -> bool {
123                     std::string sourceFile = DEBUGGER_JS_DIR "dropframe.js";
124                     auto parsed = static_cast<const ScriptParsed *>(&events);
125                     ASSERT_EQ(parsed->GetName(), "Debugger.scriptParsed");
126                     ASSERT_EQ(parsed->GetUrl(), sourceFile);
127                     return true;
128                 },
129                 [this](const PtBaseEvents &events) -> bool {
130                     std::cout << checkVariableCounter_ << std::endl;
131                     auto paused = static_cast<const Paused *>(&events);
132                     ASSERT_EQ(paused->GetName(), "Debugger.paused");
133                     auto allFrames = paused->GetCallFrames();
134                     std::map<std::string, std::string> truthVariableMap = variableMap_.at(checkVariableCounter_);
135                     for (size_t index = 0; index < allFrames->size(); index++) {
136                         auto frame = paused->GetCallFrames()->at(index).get();
137                         auto scopes = frame->GetScopeChain();
138                         for (uint32_t i = 0; i < scopes->size(); i++) {
139                             auto scope = scopes->at(i).get();
140                             if (scope->GetType() != Scope::Type::Local()) {
141                                 continue;
142                             }
143                             auto localId = scope->GetObject()->GetObjectId();
144                             GetPropertiesParams params;
145                             params.SetObjectId(localId).SetOwnProperties(true);
146                             std::vector<std::unique_ptr<PropertyDescriptor>> outPropertyDesc;
147                             runtime_->GetProperties(params, &outPropertyDesc, {}, {}, {});
148                             for (const auto &property : outPropertyDesc) {
149                                 std::cout << "=====================================" << std::endl;
150                                 std::string name = property->GetName();
151                                 std::cout << name << std::endl;
152                                 if (truthVariableMap.count(name)) {
153                                     auto value = property->GetValue();
154                                     if (value->HasValue()) {
155                                         std::string valueStr = value->GetValue()->ToString(vm_)->ToString();
156                                         std::cout << valueStr << std::endl;
157                                         ASSERT_EQ(valueStr, truthVariableMap[name]);
158                                     }
159                                 }
160                             }
161                         }
162                     }
163                     return true;
164                 }
165             };
166 
167             ASSERT_TRUE(eventList[index_](events));
168             index_ |= 1;
169         }
170 
IncreaseCheckVariableCounter()171         void IncreaseCheckVariableCounter()
172         {
173             checkVariableCounter_++;
174         }
175 
176     private:
177         NO_COPY_SEMANTIC(JsDropFrameTestChannel);
178         NO_MOVE_SEMANTIC(JsDropFrameTestChannel);
179 
180         const std::vector<std::map<std::string, std::string>> variableMap_ = {
181             { { "a", "2" }, { "b", "3" }, { "c", "4" }, {"d", "2"} },
182             { { "a", "2" }, { "b", "3" }, { "c", "3" }, {"d", "1"} },
183             { { "a", "2" }, { "b", "2" }, { "c", "3" }, {"d", "0"} },
184             { { "a", "1" }, { "b", "2" }, { "c", "3" } },
185             { { "a", "2" }, { "b", "3" }, { "c", "4" }, {"d", "2"} },
186             { { "a", "4" }, { "b", "5" }, { "c", "6" }, {"d", "2"} },
187             { { "a", "6" }, { "b", "4" }, { "c", "5" }, {"d", "2"} },
188             { { "a", "6" }, { "b", "4" }, { "c", "5" }, {"d", "1"} },
189             { { "a", "2" }, { "b", "3" }, { "c", "4" } },
190             { { "a", "4" }, { "b", "5" }, { "c", "6" }, {"d", "2"} },
191             { { "a", "8" }, { "b", "13" }, { "c", "78" }, {"d", "1"} },
192             { { "a", "4" }, { "b", "5" }, { "c", "6" }, {"d", "1"} },
193             { { "a", "8" }, { "b", "13" }, { "c", "78" }, {"d", "1"} },
194             { { "a", "16" }, { "b", "29" }, { "c", "2262" }, {"d", "182"} },
195             { { "a", "8" }, { "b", "13" }, { "c", "78" }, {"d", "182"} },
196             { { "a", "4" }, { "b", "5" }, { "c", "6" } },
197             { { "a", "8" }, { "b", "13" }, { "c", "78" }, {"d", "1"} },
198             { { "a", "32" }, { "b", "61" }, { "c", "4214" }, {"d", "1"} },
199             { { "a", "16" }, { "b", "29" }, { "c", "2262" }, {"d", "1"} },
200             { { "a", "32" }, { "b", "61" }, { "c", "4214" }, {"d", "1"} },
201             { { "a", "64" }, { "b", "125" }, { "c", "12214" }, {"d", "29"} },
202             { { "a", "128" }, { "b", "253" }, { "c", "44598" }, {"d", "1769"} },
203             { { "a", "256" }, { "b", "509" }, { "c", "174902" }, {"d", "221125"} },
204             { { "a", "128" }, { "b", "253" }, { "c", "44598" }, {"d", "221125"} },
205             { { "a", "16" }, { "b", "29" }, { "c", "2262" } },
206             { { "a", "32" }, { "b", "61" }, { "c", "4214" }, {"d", "1"} },
207             { { "a", "256" }, { "b", "1277" }, { "c", "176435" } },
208             { { "a", "256" }, { "b", "509" }, { "c", "174902" } },
209             { { "a", "256" }, { "b", "509" }, { "c", "174902" } },
210             { { "a", "256" }, { "b", "1277" }, { "c", "176435" } },
211             { { "a", "256" }, { "b", "2301" }, { "c", "178992" } },
212             { { "a", "512" }, { "b", "3837" }, { "c", "183341" } },
213             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" } },
214             { { "a", "512" }, { "b", "3837" }, { "c", "183341" } },
215             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" } },
216             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" }, {"s", "2"} },
217             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" }, {"s", "2"} },
218             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" } },
219             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" } },
220             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" } },
221             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" }, {"s", "2"} },
222             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" }, {"s", "3"} },
223             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" } },
224             { { "a", "1024" }, { "b", "7933" }, { "c", "192298" }, {"s", "3"} },
225             { { "a", "10" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} },
226             { { "a", "9" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} },
227             { { "a", "8" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} },
228             { { "a", "10" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} },
229             { { "a", "11" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} },
230             { { "a", "12" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} },
231             { { "a", "7" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} },
232             { { "a", "10" }, { "b", "7933" }, { "c", "192298" }, {"x", "7"} }
233         };
234 
235         int32_t index_ {0};
236         const EcmaVM *vm_ {nullptr};
237         RuntimeImpl *runtime_ {nullptr};
238         size_t checkVariableCounter_ {0};
239     };
240 
241     enum breakpointOpType {
242         RESUME = 1,
243         DROPLASTFRAME = 2
244     };
245 
246     static constexpr size_t LINE_COLUMN = 2;
247     static constexpr size_t POINTER_SIZE = 7;
248 
249     std::string pandaFile_ = DEBUGGER_ABC_DIR "dropframe.abc";
250     std::string sourceFile_ = DEBUGGER_JS_DIR "dropframe.js";
251     std::string entryPoint_ = "_GLOBAL::func_main_0";
252     size_t breakpointCounter_ = 0;
253     size_t dropframeCounter_ = 0;
254     bool dropFrameChecked_ = false;
255     std::vector<JSPtLocation> pointerLocations_;
256     size_t breakpointHitTimes[POINTER_SIZE] = {2, 2, 4, 6, 6, 4, 5};
257     std::queue<std::pair<uint8_t, uint8_t>> breakpointOp;
258 
InitBreakpointOpQueue()259     void InitBreakpointOpQueue()
260     {
261         breakpointOp.push({1, breakpointOpType::DROPLASTFRAME});
262         breakpointOp.push({1, breakpointOpType::DROPLASTFRAME});
263         breakpointOp.push({1, breakpointOpType::DROPLASTFRAME});
264         breakpointOp.push({3, breakpointOpType::DROPLASTFRAME});
265         breakpointOp.push({3, breakpointOpType::DROPLASTFRAME});
266         breakpointOp.push({3, breakpointOpType::DROPLASTFRAME});
267         breakpointOp.push({5, breakpointOpType::DROPLASTFRAME});
268         breakpointOp.push({7, breakpointOpType::DROPLASTFRAME});
269         breakpointOp.push({7, breakpointOpType::DROPLASTFRAME});
270         breakpointOp.push({9, breakpointOpType::DROPLASTFRAME});
271         breakpointOp.push({13, breakpointOpType::DROPLASTFRAME});
272         breakpointOp.push({13, breakpointOpType::DROPLASTFRAME});
273         breakpointOp.push({15, breakpointOpType::DROPLASTFRAME});
274         breakpointOp.push({15, breakpointOpType::DROPLASTFRAME});
275         breakpointOp.push({19, breakpointOpType::DROPLASTFRAME});
276         breakpointOp.push({21, breakpointOpType::DROPLASTFRAME});
277         breakpointOp.push({21, breakpointOpType::DROPLASTFRAME});
278         breakpointOp.push({21, breakpointOpType::DROPLASTFRAME});
279         breakpointOp.push({21, breakpointOpType::DROPLASTFRAME});
280         breakpointOp.push({23, breakpointOpType::DROPLASTFRAME});
281         breakpointOp.push({25, breakpointOpType::DROPLASTFRAME});
282         breakpointOp.push({25, breakpointOpType::DROPLASTFRAME});
283         breakpointOp.push({28, breakpointOpType::DROPLASTFRAME});
284     }
285 
DropFrameIfChecked()286     void DropFrameIfChecked()
287     {
288         while (!dropFrameChecked_ && !breakpointOp.empty() && breakpointOp.front().first == breakpointCounter_) {
289             if (breakpointOp.front().second == breakpointOpType::DROPLASTFRAME) {
290                 PtJson paramsJson;
291                 paramsJson.Add("droppedDepth", 1U);
292                 std::unique_ptr<DropFrameParams> params = DropFrameParams::Create(paramsJson);
293                 debugger_->DropFrame(*params);
294                 dropFrameChecked_ = true;
295             }
296             breakpointOp.pop();
297         }
298     }
299 
SetJSPtLocation(size_t * arr,size_t number,std::vector<JSPtLocation> & locations)300     void SetJSPtLocation(size_t *arr, size_t number, std::vector<JSPtLocation> &locations)
301     {
302         for (size_t i = 0; i < number; i++) {
303             JSPtLocation location = TestUtil::GetLocation(sourceFile_.c_str(), arr[i * LINE_COLUMN],
304                                                           arr[i * LINE_COLUMN + 1], pandaFile_.c_str());
305             locations.push_back(location);
306         }
307     };
308 };
309 
GetJsDropFrameTest()310 std::unique_ptr<TestEvents> GetJsDropFrameTest()
311 {
312     return std::make_unique<JsDropFrameTest>();
313 }
314 }  // namespace panda::ecmascript::tooling::test
315 
316 #endif  // ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_DROP_FRAME_TEST_H
317