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

Side by Side Diff: tests/standalone/debugger/debug_lib.dart

Issue 13474011: Update debugger test (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « tests/standalone/debugger/basic_debugger_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // Library used by debugger wire protocol tests (standalone VM debugging). 5 // Library used by debugger wire protocol tests (standalone VM debugging).
6 6
7 library DartDebugger; 7 library DartDebugger;
8 8
9 import "dart:io"; 9 import "dart:io";
10 import "dart:math"; 10 import "dart:math";
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 isMatch = false; 147 isMatch = false;
148 } 148 }
149 } else { 149 } else {
150 isMatch = false; 150 isMatch = false;
151 } 151 }
152 }); 152 });
153 return isMatch; 153 return isMatch;
154 } 154 }
155 155
156 156
157 class BreakpointEvent {
158 String functionName;
159 var template = { "event": "paused", "params": { "reason": "breakpoint" }};
160
161 BreakpointEvent({String function: null}) {
162 functionName = function;
163 }
164
165 void match(Debugger debugger) {
166 var msg = debugger.currentMessage;
167 if (!matchMaps(template, msg)) {
168 debugger.error("message does not match $template");
169 }
170 var name = getJsonValue(msg, "params:callFrames[0]:functionName");
171 if (name == "main") {
172 // Extract script url of debugged script.
173 var scriptUrl = getJsonValue(msg, "params:callFrames[0]:location:url");
174 assert(scriptUrl != null);
175 debugger.scriptUrl = scriptUrl;
176 }
177 if (functionName != null) {
178 var name = getJsonValue(msg, "params:callFrames[0]:functionName");
179 if (functionName != name) {
180 debugger.error("expected function name $functionName but got $name");
181 }
182 }
183 }
184 }
185
186 Breakpoint({String function}) {
187 return new BreakpointEvent(function: function);
188 }
189
190 class Matcher { 157 class Matcher {
191 void match(Debugger debugger); 158 void match(Debugger debugger);
192 } 159 }
193 160
194 class FrameMatcher extends Matcher { 161
162 class Command {
163 var template;
164
165 void send(Debugger debugger) {
166 debugger.sendMessage(template);
167 }
168
169 void matchResponse(Debugger debugger) {
170 Map response = debugger.currentMessage;
171 var id = template["id"];
172 assert(id != null && id >= 0);
173 if (response["id"] != id) {
174 debugger.error("Expected messaged id $id but got ${response["id"]}.");
175 }
176 }
177 }
178
179
180 class FrameMatcher extends Command {
195 int frameIndex; 181 int frameIndex;
196 List<String> functionNames; 182 List<String> functionNames;
197 183
198 FrameMatcher(this.frameIndex, this.functionNames); 184 FrameMatcher(this.frameIndex, this.functionNames) {
185 template = {"id": 0, "command": "getStackTrace", "params": {"isolateId": 0}} ;
186 }
199 187
200 void match(Debugger debugger) { 188 void matchResponse(Debugger debugger) {
189 super.matchResponse(debugger);
201 var msg = debugger.currentMessage; 190 var msg = debugger.currentMessage;
202 List frames = getJsonValue(msg, "params:callFrames"); 191 List frames = getJsonValue(msg, "result:callFrames");
203 assert(frames != null); 192 assert(frames != null);
193 if (debugger.scriptUrl == null) {
194 var name = frames[0]["functionName"];
195 if (name == "main") {
196 // Extract script url of debugged script.
197 debugger.scriptUrl = frames[0]["location"]["url"];
198 assert(debugger.scriptUrl != null);
199 }
200 }
204 if (frames.length < functionNames.length) { 201 if (frames.length < functionNames.length) {
205 debugger.error("stack trace not long enough " 202 debugger.error("stack trace not long enough "
206 "to match ${functionNames.length} frames"); 203 "to match ${functionNames.length} frames");
207 return; 204 return;
208 } 205 }
209 for (int i = 0; i < functionNames.length; i++) { 206 for (int i = 0; i < functionNames.length; i++) {
210 var idx = i + frameIndex; 207 var idx = i + frameIndex;
211 var property = "params:callFrames[$idx]:functionName"; 208 var name = frames[idx]["functionName"];
212 var name = getJsonValue(msg, property); 209 assert(name != null);
213 if (name == null) {
214 debugger.error("property '$property' not found");
215 return;
216 }
217 if (name != functionNames[i]) { 210 if (name != functionNames[i]) {
218 debugger.error("call frame $idx: " 211 debugger.error("call frame $idx: "
219 "expected function name '${functionNames[i]}' but found '$name'"); 212 "expected function name '${functionNames[i]}' but found '$name'");
220 return; 213 return;
221 } 214 }
222 } 215 }
223 } 216 }
224 } 217 }
225 218
226 219
227 MatchFrame(int frameIndex, String functionName) { 220 MatchFrame(int frameIndex, String functionName) {
228 return new FrameMatcher(frameIndex, [ functionName ]); 221 return new FrameMatcher(frameIndex, [ functionName ]);
229 } 222 }
230 223
231 MatchFrames(List<String> functionNames) { 224 MatchFrames(List<String> functionNames) {
232 return new FrameMatcher(0, functionNames); 225 return new FrameMatcher(0, functionNames);
233 } 226 }
234 227
235 228
236 class Command { 229 class RunCommand extends Command {
237 var template; 230 RunCommand.resume() {
238 Command();
239 Command.resume() {
240 template = {"id": 0, "command": "resume", "params": {"isolateId": 0}}; 231 template = {"id": 0, "command": "resume", "params": {"isolateId": 0}};
241 } 232 }
242 Command.step() { 233 RunCommand.step() {
243 template = {"id": 0, "command": "stepOver", "params": {"isolateId": 0}}; 234 template = {"id": 0, "command": "stepOver", "params": {"isolateId": 0}};
244 } 235 }
245 Map makeMsg(int cmdId, int isolateId) {
246 template["id"] = cmdId;
247 if ((template["params"] != null)
248 && (template["params"]["isolateId"] != null)) {
249 template["params"]["isolateId"] = isolateId;
250 }
251 return template;
252 }
253
254 void send(Debugger debugger) { 236 void send(Debugger debugger) {
255 template["id"] = debugger.seqNr;
256 template["params"]["isolateId"] = debugger.isolateId;
257 debugger.sendMessage(template); 237 debugger.sendMessage(template);
258 } 238 debugger.isPaused = false;
259
260 void matchResponse(Debugger debugger) {
261 Map response = debugger.currentMessage;
262 var id = template["id"];
263 assert(id != null && id >= 0);
264 if (response["id"] != id) {
265 debugger.error("Expected messaged id $id but got ${response["id"]}.");
266 }
267 } 239 }
268 } 240 }
269 241
270 Resume() => new Command.resume(); 242
271 Step() => new Command.step(); 243 Resume() => new RunCommand.resume();
244 Step() => new RunCommand.step();
245
272 246
273 class SetBreakpointCommand extends Command { 247 class SetBreakpointCommand extends Command {
274 int line; 248 int line;
275 SetBreakpointCommand(int this.line) { 249 SetBreakpointCommand(int this.line) {
276 template = {"id": 0, 250 template = {"id": 0,
277 "command": "setBreakpoint", 251 "command": "setBreakpoint",
278 "params": { "isolateId": 0, 252 "params": { "isolateId": 0,
279 "url": null, 253 "url": null,
280 "line": null }}; 254 "line": null }};
281 } 255 }
256
282 void send(Debugger debugger) { 257 void send(Debugger debugger) {
283 assert(debugger.scriptUrl != null); 258 assert(debugger.scriptUrl != null);
284 template["params"]["url"] = debugger.scriptUrl; 259 template["params"]["url"] = debugger.scriptUrl;
285 template["params"]["line"] = line; 260 template["params"]["line"] = line;
286 super.send(debugger); 261 debugger.sendMessage(template);
287 } 262 }
288 } 263 }
289 264
290 SetBreakpoint(int line) => new SetBreakpointCommand(line); 265 SetBreakpoint(int line) => new SetBreakpointCommand(line);
291 266
292 267
293 // A debug script is a list of Event, Matcher and Command objects. 268 // A debug script is a list of Command objects.
294 class DebugScript { 269 class DebugScript {
295 List entries; 270 List entries;
296 int currentIndex; 271 DebugScript(List scriptEntries) {
297 DebugScript(List this.entries) : currentIndex = 0; 272 entries = new List.from(scriptEntries.reversed);
298 get currentEntry { 273 entries.add(MatchFrame(0, "main"));
299 if (currentIndex < entries.length) return entries[currentIndex];
300 return null;
301 } 274 }
302 advance() { 275 bool get isEmpty => entries.isEmpty;
303 currentIndex++; 276 get currentEntry => entries.last;
304 } 277 advance() => entries.removeLast();
278 add(entry) => entries.add(entry);
305 } 279 }
306 280
307 281
308 class Debugger { 282 class Debugger {
309 // Debug target process properties. 283 // Debug target process properties.
310 Process targetProcess; 284 Process targetProcess;
311 int portNumber; 285 int portNumber;
312 Socket socket; 286 Socket socket;
313 JsonBuffer responses = new JsonBuffer(); 287 JsonBuffer responses = new JsonBuffer();
314 288
315 DebugScript script; 289 DebugScript script;
316 int seqNr = 0; // Sequence number of next debugger command message. 290 int seqNr = 0; // Sequence number of next debugger command message.
317 Command lastCommand = null; // Most recent command sent to target. 291 Command lastCommand = null; // Most recent command sent to target.
318 List<String> errors = new List(); 292 List<String> errors = new List();
319 293
320 // Data collected from debug target. 294 // Data collected from debug target.
321 Map currentMessage = null; // Currently handled message sent by target. 295 Map currentMessage = null; // Currently handled message sent by target.
322 String scriptUrl = null; 296 String scriptUrl = null;
323 bool shutdownEventSeen = false; 297 bool shutdownEventSeen = false;
324 int isolateId = 0; 298 int isolateId = 0;
299 bool isPaused = false;
325 300
326 Debugger(this.targetProcess, this.portNumber) { 301 Debugger(this.targetProcess, this.portNumber) {
327 stdin.listen((_) {}); 302 stdin.listen((_) {});
328 var stdoutStringStream = targetProcess.stdout 303 var stdoutStringStream = targetProcess.stdout
329 .transform(new StringDecoder()) 304 .transform(new StringDecoder())
330 .transform(new LineTransformer()); 305 .transform(new LineTransformer());
331 stdoutStringStream.listen((line) { 306 stdoutStringStream.listen((line) {
332 if (showDebuggeeOutput) { 307 if (showDebuggeeOutput) {
333 print("TARG: $line"); 308 print("TARG: $line");
334 } 309 }
335 }); 310 });
336 311
337 var stderrStringStream = targetProcess.stderr 312 var stderrStringStream = targetProcess.stderr
338 .transform(new StringDecoder()) 313 .transform(new StringDecoder())
339 .transform(new LineTransformer()); 314 .transform(new LineTransformer());
340 stderrStringStream.listen((line) { 315 stderrStringStream.listen((line) {
341 if (showDebuggeeOutput) { 316 if (showDebuggeeOutput) {
342 print("TARG: $line"); 317 print("TARG: $line");
343 } 318 }
344 }); 319 });
345 } 320 }
346 321
347 // Handle debugger events for which there is no explicit 322 // Handle debugger events, updating the debugger state.
348 // entry in the debug script, for example isolate create and 323 void handleEvent(Map<String,dynamic> msg) {
349 // shutdown events, breakpoint resolution events, etc.
350 bool handleImplicitEvents(Map<String,dynamic> msg) {
351 if (msg["event"] == "isolate") { 324 if (msg["event"] == "isolate") {
352 if (msg["params"]["reason"] == "created") { 325 if (msg["params"]["reason"] == "created") {
353 isolateId = msg["params"]["id"]; 326 isolateId = msg["params"]["id"];
354 assert(isolateId != null); 327 assert(isolateId != null);
355 print("Debuggee isolate id $isolateId created."); 328 print("Debuggee isolate id $isolateId created.");
356 } else if (msg["params"]["reason"] == "shutdown") { 329 } else if (msg["params"]["reason"] == "shutdown") {
357 print("Debuggee isolate id ${msg["params"]["id"]} shut down."); 330 print("Debuggee isolate id ${msg["params"]["id"]} shut down.");
358 shutdownEventSeen = true; 331 shutdownEventSeen = true;
359 if (script.currentEntry != null) { 332 if (!script.isEmpty) {
360 error("Premature isolate shutdown event seen."); 333 error("Premature isolate shutdown event seen.");
361 } 334 }
362 } 335 }
363 return true;
364 } else if (msg["event"] == "breakpointResolved") { 336 } else if (msg["event"] == "breakpointResolved") {
365 // Ignore the event. We may want to maintain a table of 337 // Ignore the event. We may want to maintain a table of
366 // breakpoints in the future. 338 // breakpoints in the future.
367 return true; 339 } else if (msg["event"] == "paused") {
340 isPaused = true;
341 } else {
342 error("unknown debugger event received");
368 } 343 }
369 return false;
370 } 344 }
371 345
372 // Handle one JSON message object and match it to the 346 // Handle one JSON message object and match it to the
373 // expected events and responses in the debugging script. 347 // expected events and responses in the debugging script.
374 void handleMessage(Map<String,dynamic> receivedMsg) { 348 void handleMessage(Map<String,dynamic> receivedMsg) {
375 currentMessage = receivedMsg; 349 currentMessage = receivedMsg;
376 var isHandled = handleImplicitEvents(receivedMsg); 350 if (receivedMsg["event"] != null) {
377 if (isHandled) return; 351 handleEvent(receivedMsg);
378 352 if (errorsDetected) {
379 if (receivedMsg["id"] != null) { 353 error("Error while handling debugger event");
354 error("Event received from debug target: $receivedMsg");
355 }
356 } else if (receivedMsg["id"] != null) {
380 // This is a response to the last command we sent. 357 // This is a response to the last command we sent.
381 assert(lastCommand != null); 358 assert(lastCommand != null);
382 lastCommand.matchResponse(this); 359 lastCommand.matchResponse(this);
383 lastCommand = null; 360 lastCommand = null;
384 if (errorsDetected) { 361 if (errorsDetected) {
385 error("Error while matching response to debugger command"); 362 error("Error while matching response to debugger command");
386 error("Response received from debug target: $receivedMsg"); 363 error("Response received from debug target: $receivedMsg");
387 } 364 }
388 return;
389 }
390
391 // This message must be an event that is expected by the script.
392 assert(receivedMsg["event"] != null);
393 if ((script.currentEntry == null) || (script.currentEntry is Command)) {
394 // Error: unexpected event received.
395 error("unexpected event received: $receivedMsg");
396 return;
397 } else {
398 // Match received message with expected event.
399 script.currentEntry.match(this);
400 if (errorsDetected) return;
401 script.advance();
402 while (script.currentEntry is Matcher) {
403 script.currentEntry.match(this);
404 if (errorsDetected) return;
405 script.advance();
406 }
407 } 365 }
408 } 366 }
409 367
410 // Send next debugger command in the script, if a response 368 // Send next debugger command in the script, if a response
411 // form the last command has been received and processed. 369 // form the last command has been received and processed.
412 void sendNextCommand() { 370 void sendNextCommand() {
413 if (lastCommand == null) { 371 if (lastCommand == null) {
414 if (script.currentEntry is Command) { 372 if (script.currentEntry is Command) {
415 script.currentEntry.send(this); 373 script.currentEntry.send(this);
416 lastCommand = script.currentEntry; 374 lastCommand = script.currentEntry;
417 seqNr++; 375 seqNr++;
418 script.advance(); 376 script.advance();
419 } 377 }
420 } 378 }
421 } 379 }
422 380
423 // Handle data received over the wire from the debug target 381 // Handle data received over the wire from the debug target
424 // process. Split input from JSON wire format into individual 382 // process. Split input from JSON wire format into individual
425 // message objects (maps). 383 // message objects (maps).
426 void handleMessages() { 384 void handleMessages() {
427 var msg = responses.getNextMessage(); 385 var msg = responses.getNextMessage();
428 while (msg != null) { 386 while (msg != null) {
429 if (verboseWire) print("RECV: $msg"); 387 if (verboseWire) print("RECV: $msg");
430 var msgObj = JSON.parse(msg); 388 var msgObj = JSON.parse(msg);
431 handleMessage(msgObj); 389 handleMessage(msgObj);
432 if (errorsDetected) { 390 if (errorsDetected) {
433 error("Error while handling script entry ${script.currentIndex}"); 391 error("Error while handling script entry");
434 error("Message received from debug target: $msg"); 392 error("Message received from debug target: $msg");
435 close(killDebugee: true); 393 close(killDebugee: true);
436 return; 394 return;
437 } 395 }
438 if (shutdownEventSeen) { 396 if (shutdownEventSeen) {
439 close(); 397 close();
440 return; 398 return;
441 } 399 }
442 sendNextCommand(); 400 if (isPaused) sendNextCommand();
443 msg = responses.getNextMessage(); 401 msg = responses.getNextMessage();
444 } 402 }
445 } 403 }
446 404
447 runScript(List entries) { 405 runScript(List entries) {
448 script = new DebugScript(entries); 406 script = new DebugScript(entries);
449 openConnection(); 407 openConnection();
450 } 408 }
451 409
452 // Send a debugger command to the target VM. 410 // Send a debugger command to the target VM.
453 void sendMessage(Map<String,dynamic> msg) { 411 void sendMessage(Map<String,dynamic> msg) {
412 if (msg["id"] != null) {
413 msg["id"] = seqNr;
414 }
415 if (msg["params"] != null && msg["params"]["isolateId"] != null) {
416 msg["params"]["isolateId"] = isolateId;
417 }
454 String jsonMsg = JSON.stringify(msg); 418 String jsonMsg = JSON.stringify(msg);
455 if (verboseWire) print("SEND: $jsonMsg"); 419 if (verboseWire) print("SEND: $jsonMsg");
456 socket.write(jsonMsg); 420 socket.write(jsonMsg);
457 } 421 }
458 422
459 bool get errorsDetected => errors.length > 0; 423 bool get errorsDetected => errors.length > 0;
460 424
461 // Record error message. 425 // Record error message.
462 void error(String s) { 426 void error(String s) {
463 errors.add(s); 427 errors.add(s);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 if (++retries >= 3) { 503 if (++retries >= 3) {
540 print('unable to find unused port: $e'); 504 print('unable to find unused port: $e');
541 return -1; 505 return -1;
542 } else { 506 } else {
543 // Retry with another random port. 507 // Retry with another random port.
544 RunScript(script); 508 RunScript(script);
545 } 509 }
546 }); 510 });
547 return true; 511 return true;
548 } 512 }
OLDNEW
« no previous file with comments | « tests/standalone/debugger/basic_debugger_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698