| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_REMOTE_API_TEST_H_ |
| #define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_REMOTE_API_TEST_H_ |
| |
| #include <initializer_list> |
| #include <memory> |
| #include <vector> |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/developer/debug/shared/platform_message_loop.h" |
| #include "src/developer/debug/shared/test_stream_buffer.h" |
| #include "src/developer/debug/zxdb/client/remote_api.h" |
| #include "src/developer/debug/zxdb/common/test_with_loop.h" |
| #include "src/lib/fxl/memory/ref_counted.h" |
| |
| namespace zxdb { |
| |
| class Frame; |
| class MockModuleSymbols; |
| class MockRemoteAPI; |
| class ModuleSymbols; |
| class Process; |
| class Session; |
| class Thread; |
| |
| // This is a test harness for client tests that mock out the RemoteAPI. This class sets up a message |
| // loop and the necessary plumbing. |
| // |
| // The individual tests supply their own implementation of RemoteAPI. |
| class RemoteAPITest : public TestWithLoop { |
| public: |
| // testing::Test implementation. |
| void SetUp() override; |
| void TearDown() override; |
| |
| // TODO(dangyi): Use pointer instead of reference to maintain consistency with ClientObject. |
| Session& session() { return *session_; } |
| |
| // Returns the MockRemoteAPI constructed by the default implementation of GetRemoteAPIImpl() |
| // below. |
| // |
| // Subclasses can provide any remote API implementation, but most tests want to use the standard |
| // MockRemoteAPI. When GetRemoteAPIImpl() has not been overridden, it will create a MockRemoteAPI |
| // and this getter will return it. |
| // |
| // If a derived implementation overrides GetRemoteAPIImpl(), this will return null. Such tests |
| // should provide their own getter for their specific implementation. |
| MockRemoteAPI* mock_remote_api() const { return mock_remote_api_; } |
| |
| // Injects the given module into the process. Most callers will want InjectMockModule() below. |
| void InjectModule(Process* process, fxl::RefPtr<ModuleSymbols> mod_sym, const std::string& name, |
| uint64_t load_address, const std::string& build_id); |
| |
| // Creates a MockModuleSymbols with a random name and build ID and reports it as loaded at the |
| // given address. If the load address is 0, an arbitrary one will be generated. |
| fxl::RefPtr<MockModuleSymbols> InjectMockModule(Process* process, uint64_t load_address = 0); |
| |
| // Makes the target have a fake running process with the given KOID. This assumes there is only |
| // one target in the system and that it is not currently running. |
| Process* InjectProcess(uint64_t process_koid); |
| |
| // Sends a "thread created" notifications to the client for the given fake KOID. The thread will |
| // be reported as running. |
| Thread* InjectThread(uint64_t process_koid, uint64_t thread_koid); |
| |
| // Sends the exception notification to the session. |
| void InjectException(const debug_ipc::NotifyException& exception); |
| |
| // Sends the exception notification and forces the given stack information. This bypasses the |
| // normal thread metadata computation. The exception address will be taken from the address of the |
| // top of the stack. |
| // |
| // If you use the one that takes a NotifyException, the calling code need not populate the thread |
| // vector and stack amount, they will be ignored. |
| void InjectExceptionWithStack(const debug_ipc::NotifyException& exception, |
| std::vector<std::unique_ptr<Frame>> frames, bool has_all_frames); |
| void InjectExceptionWithStack(uint64_t process_koid, uint64_t thread_koid, |
| debug_ipc::ExceptionType exception_type, |
| std::vector<std::unique_ptr<Frame>> frames, bool has_all_frames, |
| const std::vector<debug_ipc::BreakpointStats>& breakpoints = {}); |
| |
| protected: |
| // Constructs the remote API implementation for this test. |
| // |
| // Derived classes can override this to provide their own IPC mocks. Ownership will be transferred |
| // to the Session so it will be valid until TearDown (most implementations will want to keep a |
| // pointer). |
| // |
| // The default implementation will construct a MockRemoteAPI which will be available from |
| // mock_remote_api(); |
| virtual std::unique_ptr<RemoteAPI> GetRemoteAPIImpl(); |
| |
| // Allows tests to override the architecture for the test to run in. Defaults to x64. |
| virtual debug::Arch GetArch() const { return debug::Arch::kX64; } |
| |
| private: |
| std::unique_ptr<Session> session_; |
| MockRemoteAPI* mock_remote_api_ = nullptr; // See getter above. Owned by System. |
| }; |
| |
| } // namespace zxdb |
| |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_REMOTE_API_TEST_H_ |