OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 #include "debugger/core/debug_api_mock.h" | |
5 #include "debugger/core/debug_breakpoint.h" | |
6 #include "debugger/core/debug_event.h" | |
7 #include "debugger/core/debuggee_process.h" | |
8 | |
9 #include "gtest/gtest.h" | |
10 | |
11 namespace { | |
12 const int kFakeProcessId = 847; | |
13 const int kFakeThreadId = 378421; | |
14 const int kFakeThreadId2 = 308421; | |
15 HANDLE kFakeThreadHandle = reinterpret_cast<void*>(1); | |
16 HANDLE kFakeProcessHandle = reinterpret_cast<void*>(2); | |
17 HANDLE kFakeFileHandle = NULL; | |
18 | |
19 const int kNexeThreadStarted = 1; | |
20 const int kThreadHalted = 2; | |
21 const int kThreadRunning = 3; | |
22 | |
23 const debug::DebuggeeThread* kNullThreadPtr = NULL; | |
24 const debug::Breakpoint* kNullBreakpointPtr = NULL; | |
25 void* kFakeAddr1 = reinterpret_cast<void*>(0x1B0e37C5); | |
26 void* kFakeAddr2 = reinterpret_cast<void*>(0x435F976D); | |
27 | |
28 class TestableDebuggeeProcess : public debug::DebuggeeProcess { | |
29 public: | |
30 TestableDebuggeeProcess(int id, | |
31 HANDLE handle, | |
32 HANDLE file_handle, | |
33 debug::DebugAPI* debug_api) | |
34 : debug::DebuggeeProcess(id, | |
35 handle, | |
36 file_handle, | |
37 debug_api) { | |
38 } | |
39 | |
40 void OnDebugEvent(debug::DebugEvent* debug_event) { | |
41 debug::DebuggeeProcess::OnDebugEvent(debug_event); | |
42 } | |
43 | |
44 void Halt() { state_ = kHalted; } | |
45 }; | |
46 | |
47 class DebuggeeProcessTest : public ::testing::Test { | |
48 public: | |
49 DebuggeeProcessTest() { | |
50 proc_ = new TestableDebuggeeProcess(kFakeProcessId, | |
51 kFakeProcessHandle, | |
52 kFakeFileHandle, | |
53 &fake_debug_api_); | |
54 CreateThread(kFakeThreadId2); | |
55 fake_debug_api_.ClearCallSequence(); | |
56 } | |
57 | |
58 ~DebuggeeProcessTest() { | |
59 delete proc_; | |
60 } | |
61 | |
62 void CreateThread(int id) { | |
63 DEBUG_EVENT wde; | |
64 memset(&wde, 0, sizeof(wde)); | |
65 wde.dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT; | |
66 wde.dwProcessId = proc_->id(); | |
67 wde.dwThreadId = id; | |
68 | |
69 debug::DebugEvent de; | |
70 de.set_windows_debug_event(wde); | |
71 proc_->OnDebugEvent(&de); | |
72 proc_->Continue(); | |
73 } | |
74 | |
75 debug::DebugEvent CreateBreakpointDebugEvent(int thread_id, void* addr) { | |
76 DEBUG_EVENT wde; | |
77 memset(&wde, 0, sizeof(wde)); | |
78 wde.dwDebugEventCode = EXCEPTION_DEBUG_EVENT; | |
79 wde.dwProcessId = proc_->id(); | |
80 wde.dwThreadId = thread_id; | |
81 wde.u.Exception.ExceptionRecord.ExceptionCode = | |
82 EXCEPTION_BREAKPOINT; | |
83 wde.u.Exception.ExceptionRecord.ExceptionAddress = | |
84 addr; | |
85 | |
86 debug::DebugEvent de; | |
87 de.set_windows_debug_event(wde); | |
88 return de; | |
89 } | |
90 | |
91 TestableDebuggeeProcess* proc_; | |
92 debug::DebugAPIMock fake_debug_api_; | |
93 }; | |
94 | |
95 TEST_F(DebuggeeProcessTest, SimpleAccessors) { | |
96 ASSERT_NE(reinterpret_cast<debug::DebugAPIMock*>(NULL), &proc_->debug_api()); | |
97 | |
98 EXPECT_EQ(&proc_->debug_api(), &fake_debug_api_); | |
99 EXPECT_EQ(kFakeProcessId, proc_->id()); | |
100 EXPECT_EQ(kFakeProcessHandle, proc_->handle()); | |
101 EXPECT_EQ(debug::DebuggeeProcess::kRunning, proc_->state()); | |
102 | |
103 debug::DebugAPI deb_api; | |
104 debug::DebuggeeProcess this_proc(::GetCurrentProcessId(), | |
105 ::GetCurrentProcess(), | |
106 kFakeFileHandle, | |
107 &deb_api); | |
108 | |
109 int sz = this_proc.GetWordSizeInBits(); | |
110 #ifdef _WIN64 | |
111 EXPECT_EQ(64, sz); | |
112 EXPECT_FALSE(this_proc.IsWoW()); | |
113 #else | |
114 EXPECT_EQ(32, sz); | |
115 #endif | |
116 } | |
117 | |
118 TEST_F(DebuggeeProcessTest, Threads) { | |
119 std::deque<int> threads; | |
120 threads.push_back(1); | |
121 threads.push_back(2); | |
122 proc_->GetThreadIds(&threads); | |
123 ASSERT_EQ(1, threads.size()); | |
124 EXPECT_EQ(kFakeThreadId2, threads[0]); | |
125 EXPECT_EQ(NULL, proc_->GetHaltedThread()); | |
126 | |
127 debug::DebuggeeThread* thread = proc_->GetThread(threads[0]); | |
128 ASSERT_NE(kNullThreadPtr, thread); | |
129 } | |
130 | |
131 TEST_F(DebuggeeProcessTest, MemRead) { | |
132 char buff[10]; | |
133 ASSERT_TRUE(proc_->ReadMemory(0, sizeof(buff), buff)); | |
134 std::deque<debug::DebugAPIMock::FunctionId> call_list; | |
135 call_list.push_back(debug::DebugAPIMock::kReadProcessMemory); | |
136 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list)); | |
137 } | |
138 | |
139 TEST_F(DebuggeeProcessTest, MemWrite) { | |
140 proc_->Halt(); | |
141 char buff[10]; | |
142 ASSERT_TRUE(proc_->WriteMemory(0, sizeof(buff), buff)); | |
143 std::deque<debug::DebugAPIMock::FunctionId> call_list; | |
144 call_list.push_back(debug::DebugAPIMock::kWriteProcessMemory); | |
145 call_list.push_back(debug::DebugAPIMock::kFlushInstructionCache); | |
146 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list)); | |
147 } | |
148 | |
149 TEST_F(DebuggeeProcessTest, Breakpoints) { | |
150 CreateThread(kFakeThreadId); | |
151 proc_->Halt(); | |
152 | |
153 std::deque<debug::Breakpoint*> breakpoints; | |
154 breakpoints.push_back(0); | |
155 // DebuggeeProcess::GetBreakpoints shall clear 'breakpoints', just | |
156 // in case something was there. | |
157 proc_->GetBreakpoints(&breakpoints); | |
158 EXPECT_EQ(0, breakpoints.size()); | |
159 EXPECT_EQ(kNullBreakpointPtr, proc_->GetBreakpoint(kFakeAddr1)); | |
160 EXPECT_EQ(kNullBreakpointPtr, proc_->GetBreakpoint(kFakeAddr2)); | |
161 | |
162 EXPECT_TRUE(proc_->SetBreakpoint(kFakeAddr1)); | |
163 EXPECT_TRUE(proc_->SetBreakpoint(kFakeAddr2)); | |
164 proc_->GetBreakpoints(&breakpoints); | |
165 ASSERT_EQ(2, breakpoints.size()); | |
166 | |
167 debug::Breakpoint* br1 = breakpoints[0]; | |
168 EXPECT_EQ(kFakeAddr1, breakpoints[0]->address()); | |
169 EXPECT_EQ(kFakeAddr2, breakpoints[1]->address()); | |
170 | |
171 ASSERT_NE(kNullBreakpointPtr, proc_->GetBreakpoint(kFakeAddr1)); | |
172 ASSERT_NE(kNullBreakpointPtr, proc_->GetBreakpoint(kFakeAddr2)); | |
173 EXPECT_EQ(kFakeAddr1, proc_->GetBreakpoint(kFakeAddr1)->address()); | |
174 EXPECT_EQ(kFakeAddr2, proc_->GetBreakpoint(kFakeAddr2)->address()); | |
175 } | |
176 | |
177 TEST_F(DebuggeeProcessTest, ThreadNewAndDelete) { | |
178 CreateThread(kFakeThreadId + 13); | |
179 std::deque<int> threads; | |
180 proc_->GetThreadIds(&threads); | |
181 ASSERT_EQ(2, threads.size()); | |
182 EXPECT_EQ(kFakeThreadId2, threads[0]); | |
183 EXPECT_EQ(kFakeThreadId + 13, threads[1]); | |
184 | |
185 CreateThread(kFakeThreadId + 77); | |
186 proc_->GetThreadIds(&threads); | |
187 ASSERT_EQ(3, threads.size()); | |
188 EXPECT_EQ(kFakeThreadId + 77, threads[2]); | |
189 | |
190 DEBUG_EVENT wde; | |
191 memset(&wde, 0, sizeof(wde)); | |
192 wde.dwProcessId = proc_->id(); | |
193 wde.dwThreadId = kFakeThreadId2; | |
194 wde.dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT; | |
195 | |
196 debug::DebugEvent de; | |
197 de.set_windows_debug_event(wde); | |
198 proc_->OnDebugEvent(&de); | |
199 proc_->GetThreadIds(&threads); | |
200 EXPECT_EQ(3, threads.size()); | |
201 | |
202 proc_->Continue(); | |
203 proc_->GetThreadIds(&threads); | |
204 EXPECT_EQ(2, threads.size()); | |
205 EXPECT_EQ(debug::DebuggeeProcess::kRunning, proc_->state()); | |
206 } | |
207 | |
208 TEST_F(DebuggeeProcessTest, ProcessExit) { | |
209 DEBUG_EVENT wde; | |
210 memset(&wde, 0, sizeof(wde)); | |
211 wde.dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT; | |
212 wde.dwThreadId = kFakeThreadId2; | |
213 wde.dwProcessId = proc_->id(); | |
214 | |
215 debug::DebugEvent de; | |
216 de.set_windows_debug_event(wde); | |
217 | |
218 proc_->OnDebugEvent(&de); | |
219 EXPECT_EQ(debug::DebuggeeProcess::kHalted, proc_->state()); | |
220 EXPECT_EQ(wde.dwDebugEventCode, | |
221 proc_->last_debug_event().windows_debug_event().dwDebugEventCode); | |
222 EXPECT_EQ(wde.dwProcessId, | |
223 proc_->last_debug_event().windows_debug_event().dwProcessId); | |
224 EXPECT_EQ(wde.dwThreadId, | |
225 proc_->last_debug_event().windows_debug_event().dwThreadId); | |
226 | |
227 proc_->Continue(); | |
228 EXPECT_EQ(debug::DebuggeeProcess::kDead, proc_->state()); | |
229 } | |
230 | |
231 TEST_F(DebuggeeProcessTest, HitOurBreakpoint) { | |
232 CreateThread(kFakeThreadId); | |
233 proc_->Halt(); | |
234 EXPECT_TRUE(proc_->SetBreakpoint(kFakeAddr1)); | |
235 | |
236 debug::DebugEvent de = CreateBreakpointDebugEvent(kFakeThreadId, kFakeAddr1); | |
237 proc_->OnDebugEvent(&de); | |
238 | |
239 EXPECT_EQ(debug::DebuggeeProcess::kHalted, proc_->state()); | |
240 EXPECT_EQ(proc_->GetThread(kFakeThreadId), proc_->GetHaltedThread()); | |
241 | |
242 EXPECT_TRUE(proc_->Continue()); | |
243 EXPECT_EQ(debug::DebuggeeProcess::kRunning, proc_->state()); | |
244 } | |
245 | |
246 TEST_F(DebuggeeProcessTest, HitBreakpointSingleStep) { | |
247 debug::DebugEvent de = CreateBreakpointDebugEvent(kFakeThreadId2, kFakeAddr1); | |
248 proc_->OnDebugEvent(&de); | |
249 | |
250 EXPECT_EQ(debug::DebuggeeProcess::kHalted, proc_->state()); | |
251 EXPECT_EQ(proc_->GetThread(kFakeThreadId2), proc_->GetHaltedThread()); | |
252 | |
253 EXPECT_TRUE(proc_->SingleStep()); | |
254 EXPECT_EQ(debug::DebuggeeProcess::kRunning, proc_->state()); | |
255 } | |
256 | |
257 TEST_F(DebuggeeProcessTest, HitUnknownBreakpoint) { | |
258 CreateThread(kFakeThreadId); | |
259 proc_->Halt(); | |
260 EXPECT_TRUE(proc_->SetBreakpoint(kFakeAddr1)); | |
261 | |
262 debug::DebugEvent de = CreateBreakpointDebugEvent(kFakeThreadId, kFakeAddr2); | |
263 proc_->OnDebugEvent(&de); | |
264 | |
265 EXPECT_EQ(debug::DebuggeeProcess::kHalted, proc_->state()); | |
266 EXPECT_EQ(proc_->GetThread(kFakeThreadId), proc_->GetHaltedThread()); | |
267 | |
268 EXPECT_TRUE(proc_->ContinueAndPassExceptionToDebuggee()); | |
269 EXPECT_EQ(debug::DebuggeeProcess::kRunning, proc_->state()); | |
270 } | |
271 | |
272 TEST_F(DebuggeeProcessTest, Break) { | |
273 proc_->Break(); | |
274 std::deque<debug::DebugAPIMock::FunctionId> call_list; | |
275 call_list.push_back(debug::DebugAPIMock::kDebugBreakProcess); | |
276 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list)); | |
277 } | |
278 | |
279 TEST_F(DebuggeeProcessTest, Detach) { | |
280 proc_->Detach(); | |
281 std::deque<debug::DebugAPIMock::FunctionId> call_list; | |
282 call_list.push_back(debug::DebugAPIMock::kDebugActiveProcessStop); | |
283 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list)); | |
284 EXPECT_EQ(debug::DebuggeeProcess::kDead, proc_->state()); | |
285 } | |
286 } // namespace | |
287 | |
OLD | NEW |