Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: experimental/windows_debugger/debugger/core/debuggee_thread_test.cc

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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_event.h"
6 #include "debugger/core/debuggee_iprocess.h"
7 #include "debugger/core/debuggee_process_mock.h"
8 #include "debugger/core/debuggee_thread.h"
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 = 0;
16 HANDLE kFakeProcessHandle = 0;
17 HANDLE kFakeFileHandle = 0;
18
19 const int kNexeThreadStarted = 1;
20 const int kThreadHalted = 2;
21 const int kThreadRunning = 3;
22
23 const char* kNexeUuid =
24 "{7AA7C9CF-89EC-4ed3-8DAD-6DC84302AB11} -v 1"
25 " -event NaClThreadStart -mb c0000000 -ep 20080";
26 const void* kNexeMemBaseAddr = reinterpret_cast<void*>(0xc0000000);
27 const void* kNexeEntryPoint = reinterpret_cast<void*>(0x20080);
28 const debug::DebuggeeThread* kNullThread =
29 reinterpret_cast<debug::DebuggeeThread*>(0);
30 const char* kNullCharPtr = reinterpret_cast<char*>(0);
31
32 class TestableDebuggeeThread : public debug::DebuggeeThread {
33 public:
34 TestableDebuggeeThread(int id,
35 HANDLE handle,
36 debug::IDebuggeeProcess* parent_process)
37 : debug::DebuggeeThread(id, handle, parent_process) {}
38
39 void Kill() { debug::DebuggeeThread::Kill(); }
40 void OnDebugEvent(debug::DebugEvent* debug_event) {
41 debug::DebuggeeThread::OnDebugEvent(debug_event);
42 }
43 bool Continue(debug::DebuggeeThread::ContinueOption option) {
44 return debug::DebuggeeThread::Continue(option);
45 }
46 debug::IDebuggeeProcess& parent_process() {
47 return debug::DebuggeeThread::parent_process();
48 }
49 debug::DebugAPI& debug_api() { return debug::DebuggeeThread::debug_api(); }
50
51 void SimulateBreakpointHit() {
52 DEBUG_EVENT wde;
53 memset(&wde, 0, sizeof(wde));
54 wde.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
55 wde.u.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
56 wde.dwThreadId = id();
57
58 debug::DebugEvent de;
59 de.set_windows_debug_event(wde);
60 OnDebugEvent(&de);
61 }
62 };
63
64 // DebuggeeThread test fixture.
65 class DebuggeeThreadTest : public ::testing::Test {
66 public:
67 DebuggeeThreadTest() {
68 fake_proc_ = new debug::DebuggeeProcessMock(&fake_debug_api_);
69 fake_proc_->AddThread(kFakeThreadId2, kFakeThreadHandle);
70
71 no_thread_ = new TestableDebuggeeThread(kFakeThreadId,
72 kFakeThreadHandle,
73 fake_proc_);
74
75 this_thread_ = new TestableDebuggeeThread(GetCurrentThreadId(),
76 GetCurrentThread(),
77 fake_proc_);
78
79 fake_thread_ = new TestableDebuggeeThread(kFakeThreadId,
80 kFakeThreadHandle,
81 fake_proc_);
82 DEBUG_EVENT wde;
83 memset(&wde, 0, sizeof(wde));
84 wde.dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
85 wde.dwProcessId = fake_proc_->id();
86 wde.dwThreadId = kFakeThreadId;
87
88 debug::DebugEvent de;
89 de.set_windows_debug_event(wde);
90 fake_proc_->OnDebugEvent(&de);
91 }
92
93 ~DebuggeeThreadTest() {
94 delete fake_proc_;
95 delete fake_thread_;
96 delete no_thread_;
97 delete this_thread_;
98 }
99
100 void InitDebugEventWithString(const char* str,
101 int addr,
102 debug::DebugEvent* de) {
103 DEBUG_EVENT wde;
104 memset(&wde, 0, sizeof(wde));
105 wde.dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
106 wde.u.DebugString.lpDebugStringData = reinterpret_cast<char*>(addr);
107 wde.u.DebugString.nDebugStringLength = static_cast<WORD>(strlen(str));
108 fake_proc_->WriteMemory(
109 wde.u.DebugString.lpDebugStringData,
110 strlen(str),
111 str);
112 de->set_windows_debug_event(wde);
113 }
114
115 TestableDebuggeeThread* no_thread_;
116 TestableDebuggeeThread* this_thread_;
117 debug::DebuggeeProcessMock* fake_proc_;
118 TestableDebuggeeThread* fake_thread_;
119 debug::DebugAPIMock fake_debug_api_;
120 };
121
122 TEST_F(DebuggeeThreadTest, SimpleAccessors) {
123 EXPECT_EQ(fake_proc_, &no_thread_->parent_process());
124 EXPECT_EQ(kFakeThreadId, no_thread_->id());
125 EXPECT_EQ(&fake_proc_->debug_api(), &no_thread_->debug_api());
126 EXPECT_EQ(debug::DebuggeeThread::kHalted, no_thread_->state());
127 EXPECT_STREQ("kHalted",
128 debug::DebuggeeThread::GetStateName(no_thread_->state()));
129 }
130
131 TEST_F(DebuggeeThreadTest, Nothread) {
132 EXPECT_FALSE(no_thread_->IsNaClAppThread());
133 EXPECT_TRUE(no_thread_->IsHalted());
134 CONTEXT context;
135 EXPECT_TRUE(no_thread_->GetContext(&context));
136 EXPECT_TRUE(no_thread_->SetContext(context));
137
138 WOW64_CONTEXT wow;
139 EXPECT_TRUE(no_thread_->GetWowContext(&wow));
140 EXPECT_TRUE(no_thread_->SetWowContext(wow));
141 }
142
143 TEST_F(DebuggeeThreadTest, NothreadShallNotCrash) {
144 no_thread_->Kill();
145 no_thread_->Continue(debug::DebuggeeThread::kContinue);
146 no_thread_->Continue(debug::DebuggeeThread::kContinueAndPassException);
147 no_thread_->Continue(debug::DebuggeeThread::kSingleStep);
148 no_thread_->SetIP(NULL);
149
150 debug::DebugEvent de;
151 no_thread_->OnDebugEvent(&de);
152 }
153
154 TEST_F(DebuggeeThreadTest, SimpleAccessorsForThisThread) {
155 EXPECT_EQ(GetCurrentThreadId(), this_thread_->id());
156 }
157
158 TEST_F(DebuggeeThreadTest, ReadRegsForThisThread) {
159 CONTEXT zeroed_context;
160 memset(&zeroed_context, 0, sizeof(zeroed_context));
161 CONTEXT context;
162 EXPECT_TRUE(this_thread_->GetContext(&context));
163 EXPECT_NE(0, memcmp(&context, &zeroed_context, sizeof(context)));
164 const void* zero_ip = 0;
165 EXPECT_NE(zero_ip, this_thread_->GetIP());
166 }
167
168 TEST_F(DebuggeeThreadTest, RecvDebugUnicodeStringAndHalt) {
169 DEBUG_EVENT wde;
170 memset(&wde, 0, sizeof(wde));
171 wde.dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
172 wde.u.DebugString.fUnicode = 1;
173
174 debug::DebugEvent de;
175 de.set_windows_debug_event(wde);
176 no_thread_->OnDebugEvent(&de);
177 EXPECT_TRUE(no_thread_->IsHalted());
178 }
179
180 TEST_F(DebuggeeThreadTest, RecvDebugStringB) {
181 debug::DebugEvent de;
182 InitDebugEventWithString("abc", 1, &de);
183
184 fake_thread_->OnDebugEvent(&de);
185 EXPECT_TRUE(fake_thread_->IsHalted());
186 EXPECT_EQ(debug::DebugEvent::kNotNaClDebugEvent, de.nacl_debug_event_code());
187 }
188
189 TEST_F(DebuggeeThreadTest, RecvNexeDebugString) {
190 debug::DebugEvent de;
191 InitDebugEventWithString(kNexeUuid, 2, &de);
192
193 fake_thread_->OnDebugEvent(&de);
194 EXPECT_TRUE(fake_thread_->IsHalted());
195 EXPECT_EQ(debug::DebugEvent::kThreadIsAboutToStart,
196 de.nacl_debug_event_code());
197 }
198
199 TEST_F(DebuggeeThreadTest, RecvNexeDebugStringValidateParams) {
200 debug::DebugEvent de;
201 InitDebugEventWithString(kNexeUuid, 2, &de);
202 fake_thread_->OnDebugEvent(&de);
203
204 EXPECT_TRUE(fake_thread_->IsNaClAppThread());
205 EXPECT_EQ(kNexeMemBaseAddr, fake_proc_->nexe_mem_base());
206 EXPECT_EQ(kNexeEntryPoint, fake_proc_->nexe_entry_point());
207 }
208
209 TEST_F(DebuggeeThreadTest, RecvNexeDebugStringAndContinue) {
210 debug::DebugEvent de;
211 InitDebugEventWithString(kNexeUuid, 2, &de);
212
213 fake_thread_->OnDebugEvent(&de);
214
215 EXPECT_TRUE(fake_thread_->IsHalted());
216 EXPECT_EQ(debug::DebuggeeThread::kHalted, fake_thread_->state());
217
218 fake_thread_->Continue(debug::DebuggeeThread::kContinue);
219 EXPECT_FALSE(fake_thread_->IsHalted());
220 EXPECT_EQ(debug::DebuggeeThread::kRunning, fake_thread_->state());
221 EXPECT_FALSE(fake_debug_api_.single_step_enabled_);
222 }
223
224 TEST_F(DebuggeeThreadTest, RecvNexeDebugStringAndContinueB) {
225 debug::DebugEvent de;
226 InitDebugEventWithString(kNexeUuid, 2, &de);
227 fake_thread_->OnDebugEvent(&de);
228
229 fake_thread_->Continue(debug::DebuggeeThread::kContinueAndPassException);
230 EXPECT_FALSE(fake_thread_->IsHalted());
231 EXPECT_EQ(debug::DebuggeeThread::kRunning, fake_thread_->state());
232 EXPECT_FALSE(fake_debug_api_.single_step_enabled_);
233 }
234
235 TEST_F(DebuggeeThreadTest, RecvNexeDebugStringAndContinueVerifyCallList) {
236 debug::DebugEvent de;
237 InitDebugEventWithString(kNexeUuid, 2, &de);
238 fake_thread_->OnDebugEvent(&de);
239
240 fake_debug_api_.ClearCallSequence();
241 fake_thread_->Continue(debug::DebuggeeThread::kContinue);
242
243 std::deque<debug::DebugAPIMock::FunctionId> call_list;
244 call_list.push_back(debug::DebugAPIMock::kContinueDebugEvent);
245 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list));
246 }
247
248 TEST_F(DebuggeeThreadTest, RecvNexeDebugStringAndContinueVerifyCallListB) {
249 debug::DebugEvent de;
250 InitDebugEventWithString(kNexeUuid, 2, &de);
251 fake_thread_->OnDebugEvent(&de);
252
253 fake_debug_api_.ClearCallSequence();
254 fake_thread_->Continue(debug::DebuggeeThread::kContinueAndPassException);
255
256 std::deque<debug::DebugAPIMock::FunctionId> call_list;
257 call_list.push_back(debug::DebugAPIMock::kContinueDebugEvent);
258 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list));
259 }
260
261 TEST_F(DebuggeeThreadTest, RecvNexeDebugStringAndSingleStep) {
262 debug::DebugEvent de;
263 InitDebugEventWithString(kNexeUuid, 2, &de);
264
265 fake_thread_->OnDebugEvent(&de);
266 EXPECT_TRUE(fake_thread_->IsHalted());
267
268 fake_thread_->Continue(debug::DebuggeeThread::kSingleStep);
269 EXPECT_FALSE(fake_thread_->IsHalted());
270 EXPECT_TRUE(fake_debug_api_.single_step_enabled_);
271 }
272
273 TEST_F(DebuggeeThreadTest, RecvNexeDebugStringAndSingleStepVerifyCallList) {
274 fake_debug_api_.ClearCallSequence();
275
276 debug::DebugEvent de;
277 InitDebugEventWithString(kNexeUuid, 2, &de);
278 fake_thread_->OnDebugEvent(&de);
279 fake_thread_->Continue(debug::DebuggeeThread::kSingleStep);
280
281 std::deque<debug::DebugAPIMock::FunctionId> call_list;
282 call_list.push_back(debug::DebugAPIMock::kGetThreadContext);
283 call_list.push_back(debug::DebugAPIMock::kSetThreadContext);
284 call_list.push_back(debug::DebugAPIMock::kGetThreadContext);
285 call_list.push_back(debug::DebugAPIMock::kSetThreadContext);
286 call_list.push_back(debug::DebugAPIMock::kContinueDebugEvent);
287
288 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list));
289 }
290
291 TEST_F(DebuggeeThreadTest, Kill) {
292 TestableDebuggeeThread thread(1, reinterpret_cast<HANDLE>(1), fake_proc_);
293 fake_debug_api_.ClearCallSequence();
294 thread.Kill();
295
296 std::deque<debug::DebugAPIMock::FunctionId> call_list;
297 call_list.push_back(debug::DebugAPIMock::kTerminateThread);
298 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list));
299 }
300
301 TEST_F(DebuggeeThreadTest, SetContextVerifyCallList) {
302 fake_debug_api_.ClearCallSequence();
303 debug::DebuggeeThread thread(1, reinterpret_cast<HANDLE>(1), fake_proc_);
304
305 CONTEXT ct;
306 thread.GetContext(&ct);
307 thread.SetContext(ct);
308
309 std::deque<debug::DebugAPIMock::FunctionId> call_list;
310 call_list.push_back(debug::DebugAPIMock::kGetThreadContext);
311 call_list.push_back(debug::DebugAPIMock::kSetThreadContext);
312 EXPECT_TRUE(fake_debug_api_.CompareCallSequence(call_list));
313 }
314
315 TEST_F(DebuggeeThreadTest, RecvAlienBreakpoint) {
316 fake_thread_->SimulateBreakpointHit();
317 EXPECT_TRUE(fake_thread_->IsHalted());
318 }
319
320 TEST_F(DebuggeeThreadTest, FailContinue) {
321 fake_thread_->SimulateBreakpointHit();
322 EXPECT_TRUE(fake_thread_->IsHalted());
323 EXPECT_TRUE(fake_thread_->Continue(debug::DebuggeeThread::kContinue));
324 EXPECT_FALSE(fake_thread_->IsHalted());
325 EXPECT_FALSE(fake_thread_->Continue(debug::DebuggeeThread::kContinue));
326 EXPECT_FALSE(fake_thread_->IsHalted());
327
328 fake_thread_->SimulateBreakpointHit();
329 EXPECT_TRUE(fake_thread_->IsHalted());
330 EXPECT_TRUE(fake_thread_->Continue(debug::DebuggeeThread::kSingleStep));
331 EXPECT_FALSE(fake_thread_->IsHalted());
332 EXPECT_FALSE(fake_thread_->Continue(debug::DebuggeeThread::kSingleStep));
333 EXPECT_FALSE(fake_thread_->IsHalted());
334
335 fake_thread_->SimulateBreakpointHit();
336 EXPECT_TRUE(fake_thread_->IsHalted());
337 EXPECT_TRUE(fake_thread_->Continue(
338 debug::DebuggeeThread::kContinueAndPassException));
339 EXPECT_FALSE(fake_thread_->IsHalted());
340 EXPECT_FALSE(fake_thread_->Continue(
341 debug::DebuggeeThread::kContinueAndPassException));
342 EXPECT_FALSE(fake_thread_->IsHalted());
343 }
344
345 TEST_F(DebuggeeThreadTest, FailIfNotHalted) {
346 fake_thread_->SimulateBreakpointHit();
347 EXPECT_TRUE(fake_thread_->IsHalted());
348 EXPECT_TRUE(fake_thread_->Continue(debug::DebuggeeThread::kContinue));
349
350 EXPECT_FALSE(fake_thread_->IsHalted());
351 CONTEXT context;
352 EXPECT_FALSE(fake_thread_->GetContext(&context));
353 EXPECT_FALSE(fake_thread_->SetContext(context));
354
355 WOW64_CONTEXT wow_ctx;
356 EXPECT_FALSE(fake_thread_->GetWowContext(&wow_ctx));
357 EXPECT_FALSE(fake_thread_->SetWowContext(wow_ctx));
358
359 EXPECT_EQ(NULL, fake_thread_->GetIP());
360 EXPECT_FALSE(fake_thread_->SetIP(NULL));
361 }
362
363 TEST_F(DebuggeeThreadTest, NotFailIfHalted) {
364 EXPECT_TRUE(fake_thread_->IsHalted());
365 CONTEXT context;
366 EXPECT_TRUE(fake_thread_->GetContext(&context));
367 EXPECT_TRUE(fake_thread_->SetContext(context));
368
369 WOW64_CONTEXT wow_ctx;
370 EXPECT_TRUE(fake_thread_->GetWowContext(&wow_ctx));
371 EXPECT_TRUE(fake_thread_->SetWowContext(wow_ctx));
372
373 EXPECT_TRUE(fake_thread_->SetIP(NULL));
374 }
375
376 } // namespace
377
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698