1 /* 2 * Copyright (c) 2021-2022 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 #ifndef PANDA_RUNTIME_TESTS_TOOLING_TEST_RUNNER_H 16 #define PANDA_RUNTIME_TESTS_TOOLING_TEST_RUNNER_H 17 18 #include "test_util.h" 19 20 namespace panda::tooling::test { 21 class TestRunner : public PtHooks { 22 public: TestRunner(const char * test_name,DebugInterface * runtime_debug_interface)23 TestRunner(const char *test_name, DebugInterface *runtime_debug_interface) 24 { 25 debug_interface_ = runtime_debug_interface; 26 test_name_ = test_name; 27 test_ = TestUtil::GetTest(test_name); 28 test_->debug_interface = runtime_debug_interface; 29 TestUtil::Reset(); 30 runtime_debug_interface->RegisterHooks(this); 31 } 32 Run()33 void Run() 34 { 35 if (test_->scenario) { 36 test_->scenario(); 37 } 38 } 39 Breakpoint(PtThread thread,Method * method,const PtLocation & location)40 void Breakpoint(PtThread thread, Method *method, const PtLocation &location) override 41 { 42 if (test_->breakpoint) { 43 test_->breakpoint(thread, method, location); 44 } 45 } 46 LoadModule(std::string_view panda_file_name)47 void LoadModule(std::string_view panda_file_name) override 48 { 49 if (test_->load_module) { 50 test_->load_module(panda_file_name); 51 } 52 } 53 Paused(PauseReason reason)54 void Paused(PauseReason reason) override 55 { 56 if (test_->paused) { 57 test_->paused(reason); 58 } 59 }; 60 Exception(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * object,Method * catch_method,const PtLocation & catch_location)61 void Exception(PtThread thread, Method *method, const PtLocation &location, ObjectHeader *object, 62 Method *catch_method, const PtLocation &catch_location) override 63 { 64 if (test_->exception) { 65 test_->exception(thread, method, location, object, catch_method, catch_location); 66 } 67 } 68 ExceptionCatch(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * object)69 void ExceptionCatch(PtThread thread, Method *method, const PtLocation &location, ObjectHeader *object) override 70 { 71 if (test_->exception_catch) { 72 test_->exception_catch(thread, method, location, object); 73 } 74 } 75 PropertyAccess(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * object,PtProperty property)76 void PropertyAccess(PtThread thread, Method *method, const PtLocation &location, ObjectHeader *object, 77 PtProperty property) override 78 { 79 if (test_->property_access) { 80 test_->property_access(thread, method, location, object, property); 81 } 82 } 83 PropertyModification(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * object,PtProperty property,VRegValue new_value)84 void PropertyModification(PtThread thread, Method *method, const PtLocation &location, ObjectHeader *object, 85 PtProperty property, VRegValue new_value) override 86 { 87 if (test_->property_modification) { 88 test_->property_modification(thread, method, location, object, property, new_value); 89 } 90 } 91 FramePop(PtThread thread,Method * method,bool was_popped_by_exception)92 void FramePop(PtThread thread, Method *method, bool was_popped_by_exception) override 93 { 94 if (test_->frame_pop) { 95 test_->frame_pop(thread, method, was_popped_by_exception); 96 } 97 } 98 GarbageCollectionStart()99 void GarbageCollectionStart() override 100 { 101 if (test_->garbage_collection_start) { 102 test_->garbage_collection_start(); 103 } 104 } 105 GarbageCollectionFinish()106 void GarbageCollectionFinish() override 107 { 108 if (test_->garbage_collection_finish) { 109 test_->garbage_collection_finish(); 110 } 111 } 112 MethodEntry(PtThread thread,Method * method)113 void MethodEntry(PtThread thread, Method *method) override 114 { 115 if (test_->method_entry) { 116 test_->method_entry(thread, method); 117 } 118 } 119 MethodExit(PtThread thread,Method * method,bool was_popped_by_exception,VRegValue return_value)120 void MethodExit(PtThread thread, Method *method, bool was_popped_by_exception, VRegValue return_value) override 121 { 122 if (test_->method_exit) { 123 test_->method_exit(thread, method, was_popped_by_exception, return_value); 124 } 125 } 126 SingleStep(PtThread thread,Method * method,const PtLocation & location)127 void SingleStep(PtThread thread, Method *method, const PtLocation &location) override 128 { 129 if (test_->single_step) { 130 test_->single_step(thread, method, location); 131 } 132 } 133 ThreadStart(PtThread thread)134 void ThreadStart(PtThread thread) override 135 { 136 if (test_->thread_start) { 137 test_->thread_start(thread); 138 } 139 } 140 ThreadEnd(PtThread thread)141 void ThreadEnd(PtThread thread) override 142 { 143 if (test_->thread_end) { 144 test_->thread_end(thread); 145 } 146 } 147 VmDeath()148 void VmDeath() override 149 { 150 if (test_->vm_death) { 151 test_->vm_death(); 152 } 153 TestUtil::Event(DebugEvent::VM_DEATH); 154 } 155 VmInitialization(PtThread thread)156 void VmInitialization(PtThread thread) override 157 { 158 if (test_->vm_init) { 159 test_->vm_init(thread); 160 } 161 TestUtil::Event(DebugEvent::VM_INITIALIZATION); 162 } 163 VmStart()164 void VmStart() override 165 { 166 if (test_->vm_start) { 167 test_->vm_start(); 168 } 169 } 170 ExceptionRevoked(ExceptionWrapper reason,ExceptionID exception_id)171 void ExceptionRevoked(ExceptionWrapper reason, ExceptionID exception_id) override 172 { 173 if (test_->exception_revoked) { 174 test_->exception_revoked(reason, exception_id); 175 } 176 } 177 ExecutionContextCreated(ExecutionContextWrapper context)178 void ExecutionContextCreated(ExecutionContextWrapper context) override 179 { 180 if (test_->execution_context_created) { 181 test_->execution_context_created(context); 182 } 183 } 184 ExecutionContextDestroyed(ExecutionContextWrapper context)185 void ExecutionContextDestroyed(ExecutionContextWrapper context) override 186 { 187 if (test_->execution_context_destroyed) { 188 test_->execution_context_destroyed(context); 189 } 190 } 191 ExecutionContextsCleared()192 void ExecutionContextsCleared() override 193 { 194 if (test_->execution_context_cleared) { 195 test_->execution_context_cleared(); 196 } 197 } 198 InspectRequested(PtObject object,PtObject hints)199 void InspectRequested(PtObject object, PtObject hints) override 200 { 201 if (test_->inspect_requested) { 202 test_->inspect_requested(object, hints); 203 } 204 } 205 ClassLoad(PtThread thread,BaseClass * klass)206 void ClassLoad(PtThread thread, BaseClass *klass) override 207 { 208 if (test_->class_load) { 209 test_->class_load(thread, klass); 210 } 211 } 212 ClassPrepare(PtThread thread,BaseClass * klass)213 void ClassPrepare(PtThread thread, BaseClass *klass) override 214 { 215 if (test_->class_prepare) { 216 test_->class_prepare(thread, klass); 217 } 218 } 219 MonitorWait(PtThread thread,ObjectHeader * object,int64_t timeout)220 void MonitorWait(PtThread thread, ObjectHeader *object, int64_t timeout) override 221 { 222 if (test_->monitor_wait) { 223 test_->monitor_wait(thread, object, timeout); 224 } 225 } 226 MonitorWaited(PtThread thread,ObjectHeader * object,bool timed_out)227 void MonitorWaited(PtThread thread, ObjectHeader *object, bool timed_out) override 228 { 229 if (test_->monitor_waited) { 230 test_->monitor_waited(thread, object, timed_out); 231 } 232 } 233 MonitorContendedEnter(PtThread thread,ObjectHeader * object)234 void MonitorContendedEnter(PtThread thread, ObjectHeader *object) override 235 { 236 if (test_->monitor_contended_enter) { 237 test_->monitor_contended_enter(thread, object); 238 } 239 } 240 MonitorContendedEntered(PtThread thread,ObjectHeader * object)241 void MonitorContendedEntered(PtThread thread, ObjectHeader *object) override 242 { 243 if (test_->monitor_contended_entered) { 244 test_->monitor_contended_entered(thread, object); 245 } 246 } 247 ObjectAlloc(BaseClass * klass,ObjectHeader * object,PtThread thread,size_t size)248 void ObjectAlloc(BaseClass *klass, ObjectHeader *object, PtThread thread, size_t size) override 249 { 250 if (test_->object_alloc) { 251 test_->object_alloc(klass, object, thread, size); 252 } 253 } 254 TerminateTest()255 void TerminateTest() 256 { 257 debug_interface_->UnregisterHooks(); 258 if (TestUtil::IsTestFinished()) { 259 return; 260 } 261 LOG(FATAL, DEBUGGER) << "Test " << test_name_ << " failed"; 262 } 263 264 private: 265 DebugInterface *debug_interface_; 266 const char *test_name_; 267 ApiTest *test_; 268 }; 269 } // namespace panda::tooling::test 270 271 #endif // PANDA_RUNTIME_TESTS_TOOLING_TEST_RUNNER_H 272