1 /* 2 * Copyright (c) 2021 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_TEST_HOOKS_H 17 #define ECMASCRIPT_TOOLING_TEST_UTILS_TEST_HOOKS_H 18 19 #include "agent/debugger_impl.h" 20 #include "backend/js_pt_hooks.h" 21 #include "test/utils/test_util.h" 22 23 namespace panda::ecmascript::tooling::test { 24 class TestHooks : public PtHooks { 25 public: TestHooks(const std::string &testName, const EcmaVM *vm)26 TestHooks(const std::string &testName, const EcmaVM *vm) : vm_(vm) 27 { 28 testName_ = testName; 29 test_ = TestUtil::GetTest(testName); 30 runtime_ = std::make_unique<RuntimeImpl>(vm, test_->channel_); 31 debugger_ = std::make_unique<DebuggerImpl>(vm, test_->channel_, runtime_.get()); 32 test_->vm_ = vm; 33 test_->debugger_ = debugger_.get(); 34 test_->runtime_ = runtime_.get(); 35 test_->debugInterface_ = debugger_->jsDebugger_; 36 debugInterface_ = debugger_->jsDebugger_; 37 TestUtil::Reset(); 38 debugInterface_->RegisterHooks(this); 39 } 40 Run()41 void Run() 42 { 43 if (test_->scenario) { 44 test_->scenario(); 45 } 46 } 47 48 void DebuggerStmt(const JSPtLocation &location) override 49 { 50 if (test_->debugger_) { 51 test_->debuggerStmt(location); 52 } 53 } 54 55 void Breakpoint(const JSPtLocation &location) override 56 { 57 if (test_->breakpoint) { 58 test_->breakpoint(location); 59 } 60 } 61 62 void LoadModule(std::string_view panda_file_name, [[maybe_unused]] std::string_view entryPoint) override 63 { 64 if (test_->loadModule) { 65 test_->loadModule(panda_file_name); 66 } 67 } 68 69 void Exception(const JSPtLocation &location) override 70 { 71 if (test_->exception) { 72 Local<JSValueRef> exception = DebuggerApi::GetAndClearException(vm_); 73 74 test_->exception(location); 75 76 if (!exception->IsHole()) { 77 DebuggerApi::SetException(vm_, exception); 78 } 79 } 80 } 81 82 bool SingleStep(const JSPtLocation &location) override 83 { 84 if (test_->singleStep) { 85 return test_->singleStep(location); 86 } 87 return false; 88 } 89 90 bool NativeOut() override 91 { 92 if (test_->nativeOut) { 93 return test_->nativeOut(); 94 } 95 96 return false; 97 } 98 99 void VmDeath() override 100 { 101 if (test_->vmDeath) { 102 test_->vmDeath(); 103 } 104 TestUtil::Event(DebugEvent::VM_DEATH); 105 } 106 107 void VmStart() override 108 { 109 if (test_->vmStart) { 110 test_->vmStart(); 111 } 112 TestUtil::Event(DebugEvent::VM_START); 113 } 114 115 void NativeCalling([[maybe_unused]] const void *nativeAddress) override {} 116 117 void NativeReturn([[maybe_unused]] const void *nativeAddress) override {} 118 119 void SendableMethodEntry([[maybe_unused]] JSHandle<Method> method) override {} 120 TerminateTest()121 void TerminateTest() 122 { 123 debugInterface_->UnregisterHooks(); 124 if (TestUtil::IsTestFinished()) { 125 return; 126 } 127 LOG_DEBUGGER(FATAL) << "Test " << testName_ << " failed"; 128 } 129 130 ~TestHooks() = default; 131 132 private: 133 const EcmaVM *vm_ {nullptr}; 134 std::unique_ptr<RuntimeImpl> runtime_ {nullptr}; 135 std::unique_ptr<DebuggerImpl> debugger_ {nullptr}; 136 JSDebugger *debugInterface_; 137 std::string testName_; 138 TestEvents *test_; 139 }; 140 } // namespace panda::ecmascript::tooling::test 141 142 #endif // ECMASCRIPT_TOOLING_TEST_UTILS_TEST_HOOKS_H 143