| // 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_ipc::Arch GetArch() const { return debug_ipc::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_ |