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
23namespace panda::ecmascript::tooling::test {
24class TestHooks : public PtHooks {
25public:
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
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
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
132private:
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