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

Side by Side Diff: runtime/observatory/tests/service/service_test_common.dart

Issue 2752753002: Additional service tests (Closed)
Patch Set: Formatted some tests Created 3 years, 9 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
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 service_test_common; 5 library service_test_common;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io' show Platform;
8 import 'package:observatory/models.dart' as M; 9 import 'package:observatory/models.dart' as M;
9 import 'package:observatory/service_common.dart'; 10 import 'package:observatory/service_common.dart';
10 import 'package:unittest/unittest.dart'; 11 import 'package:unittest/unittest.dart';
11 12
12 typedef Future IsolateTest(Isolate isolate); 13 typedef Future IsolateTest(Isolate isolate);
13 typedef Future VMTest(VM vm); 14 typedef Future VMTest(VM vm);
14 15
15 Map<String, StreamSubscription> streamSubscriptions = {}; 16 Map<String, StreamSubscription> streamSubscriptions = {};
16 17
17 Future subscribeToStream(VM vm, String streamName, onEvent) async { 18 Future subscribeToStream(VM vm, String streamName, onEvent) async {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 completeError(e); 93 completeError(e);
93 return pausedAtSyntheticBreakpoint.future; 94 return pausedAtSyntheticBreakpoint.future;
94 } 95 }
95 96
96 Breakpoint syntheticBreakpoint; 97 Breakpoint syntheticBreakpoint;
97 98
98 subscription = stream.listen((ServiceEvent event) async { 99 subscription = stream.listen((ServiceEvent event) async {
99 // Synthetic breakpoint add event. This is the first event we will 100 // Synthetic breakpoint add event. This is the first event we will
100 // receive. 101 // receive.
101 bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) && 102 bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) &&
102 (event.breakpoint.isSyntheticAsyncContinuation) && 103 (event.breakpoint.isSyntheticAsyncContinuation) &&
103 (event.owner == isolate); 104 (event.owner == isolate);
104 // Resume after synthetic breakpoint added. This is the second event 105 // Resume after synthetic breakpoint added. This is the second event
105 // we will recieve. 106 // we will recieve.
106 bool isResume = (event.kind == ServiceEvent.kResume) && 107 bool isResume = (event.kind == ServiceEvent.kResume) &&
107 (syntheticBreakpoint != null) && 108 (syntheticBreakpoint != null) &&
108 (event.owner == isolate); 109 (event.owner == isolate);
109 // Paused at synthetic breakpoint. This is the third event we will 110 // Paused at synthetic breakpoint. This is the third event we will
110 // receive. 111 // receive.
111 bool isPaused = (event.kind == ServiceEvent.kPauseBreakpoint) && 112 bool isPaused = (event.kind == ServiceEvent.kPauseBreakpoint) &&
112 (syntheticBreakpoint != null) && 113 (syntheticBreakpoint != null) &&
113 (event.breakpoint == syntheticBreakpoint); 114 (event.breakpoint == syntheticBreakpoint);
114 if (isAdd) { 115 if (isAdd) {
115 syntheticBreakpoint = event.breakpoint; 116 syntheticBreakpoint = event.breakpoint;
116 } else if (isResume) { 117 } else if (isResume) {} else if (isPaused) {
117 } else if (isPaused) {
118 pausedAtSyntheticBreakpoint.complete(isolate); 118 pausedAtSyntheticBreakpoint.complete(isolate);
119 syntheticBreakpoint = null; 119 syntheticBreakpoint = null;
120 cancelSubscription(); 120 cancelSubscription();
121 } 121 }
122 }); 122 });
123 123
124 // Issue the step OverAwait command. 124 // Issue the step OverAwait command.
125 try { 125 try {
126 await isolate.stepOverAsyncSuspension(); 126 await isolate.stepOverAsyncSuspension();
127 } catch (e) { 127 } catch (e) {
(...skipping 22 matching lines...) Expand all
150 return false; 150 return false;
151 } 151 }
152 } 152 }
153 153
154 Future<Isolate> hasPausedFor(Isolate isolate, String kind) { 154 Future<Isolate> hasPausedFor(Isolate isolate, String kind) {
155 // Set up a listener to wait for breakpoint events. 155 // Set up a listener to wait for breakpoint events.
156 Completer completer = new Completer(); 156 Completer completer = new Completer();
157 isolate.vm.getEventStream(VM.kDebugStream).then((stream) { 157 isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
158 var subscription; 158 var subscription;
159 subscription = stream.listen((ServiceEvent event) { 159 subscription = stream.listen((ServiceEvent event) {
160 if ((isolate == event.isolate) && (event.kind == kind)) { 160 if ((isolate == event.isolate) && (event.kind == kind)) {
161 if (completer != null) { 161 if (completer != null) {
162 // Reload to update isolate.pauseEvent. 162 // Reload to update isolate.pauseEvent.
163 print('Paused with $kind'); 163 print('Paused with $kind');
164 subscription.cancel(); 164 subscription.cancel();
165 completer.complete(isolate.reload()); 165 completer.complete(isolate.reload());
166 completer = null; 166 completer = null;
167 }
168 } 167 }
168 }
169 }); 169 });
170 170
171 // Pause may have happened before we subscribed. 171 // Pause may have happened before we subscribed.
172 isolate.reload().then((_) { 172 isolate.reload().then((_) {
173 if ((isolate.pauseEvent != null) && 173 if ((isolate.pauseEvent != null) &&
174 isEventOfKind(isolate.pauseEvent, kind)) { 174 isEventOfKind(isolate.pauseEvent, kind)) {
175 // Already waiting at a breakpoint. 175 // Already waiting at a breakpoint.
176 if (completer != null) { 176 if (completer != null) {
177 print('Paused with $kind'); 177 print('Paused with $kind');
178 subscription.cancel(); 178 subscription.cancel();
179 completer.complete(isolate); 179 completer.complete(isolate);
180 completer = null; 180 completer = null;
181 } 181 }
182 } 182 }
183 }); 183 });
184 }); 184 });
185 185
186 return completer.future; // Will complete when breakpoint hit. 186 return completer.future; // Will complete when breakpoint hit.
187 } 187 }
188 188
189 Future<Isolate> hasStoppedAtBreakpoint(Isolate isolate) { 189 Future<Isolate> hasStoppedAtBreakpoint(Isolate isolate) {
190 return hasPausedFor(isolate, ServiceEvent.kPauseBreakpoint); 190 return hasPausedFor(isolate, ServiceEvent.kPauseBreakpoint);
191 } 191 }
192 192
193 Future<Isolate> hasStoppedPostRequest(Isolate isolate) { 193 Future<Isolate> hasStoppedPostRequest(Isolate isolate) {
194 return hasPausedFor(isolate, ServiceEvent.kPausePostRequest); 194 return hasPausedFor(isolate, ServiceEvent.kPausePostRequest);
195 } 195 }
196 196
197 Future<Isolate> hasStoppedWithUnhandledException(Isolate isolate) { 197 Future<Isolate> hasStoppedWithUnhandledException(Isolate isolate) {
198 return hasPausedFor(isolate, ServiceEvent.kPauseException); 198 return hasPausedFor(isolate, ServiceEvent.kPauseException);
199 } 199 }
200 200
201 Future<Isolate> hasStoppedAtExit(Isolate isolate) { 201 Future<Isolate> hasStoppedAtExit(Isolate isolate) {
202 return hasPausedFor(isolate, ServiceEvent.kPauseExit); 202 return hasPausedFor(isolate, ServiceEvent.kPauseExit);
203 } 203 }
204 204
205 Future<Isolate> hasPausedAtStart(Isolate isolate) { 205 Future<Isolate> hasPausedAtStart(Isolate isolate) {
206 return hasPausedFor(isolate, ServiceEvent.kPauseStart); 206 return hasPausedFor(isolate, ServiceEvent.kPauseStart);
207 } 207 }
208 208
209 Future<Isolate> markDartColonLibrariesDebuggable(Isolate isolate) async { 209 Future<Isolate> markDartColonLibrariesDebuggable(Isolate isolate) async {
210 await isolate.reload(); 210 await isolate.reload();
211 for (Library lib in isolate.libraries) { 211 for (Library lib in isolate.libraries) {
212 await lib.load(); 212 await lib.load();
213 if (lib.uri.startsWith('dart:') && 213 if (lib.uri.startsWith('dart:') && !lib.uri.startsWith('dart:_')) {
214 !lib.uri.startsWith('dart:_')) {
215 var setDebugParams = { 214 var setDebugParams = {
216 'libraryId': lib.id, 215 'libraryId': lib.id,
217 'isDebuggable': true, 216 'isDebuggable': true,
218 }; 217 };
219 Map<String, dynamic> result = 218 Map<String, dynamic> result = await isolate.invokeRpcNoUpgrade(
220 await isolate.invokeRpcNoUpgrade('setLibraryDebuggable', 219 'setLibraryDebuggable', setDebugParams);
221 setDebugParams);
222 } 220 }
223 } 221 }
224 return isolate; 222 return isolate;
225 } 223 }
226 224
227 IsolateTest reloadSources([bool pause = false]) { 225 IsolateTest reloadSources([bool pause = false]) {
228 return (Isolate isolate) async { 226 return (Isolate isolate) async {
229 Map<String, dynamic> params = <String, dynamic>{ }; 227 Map<String, dynamic> params = <String, dynamic>{};
230 if (pause == true) { 228 if (pause == true) {
231 params['pause'] = pause; 229 params['pause'] = pause;
232 } 230 }
233 return isolate.invokeRpc('reloadSources', params); 231 return isolate.invokeRpc('reloadSources', params);
234 }; 232 };
235 } 233 }
236 234
237 // Currying is your friend. 235 // Currying is your friend.
238 IsolateTest setBreakpointAtLine(int line) { 236 IsolateTest setBreakpointAtLine(int line) {
239 return (Isolate isolate) async { 237 return (Isolate isolate) async {
240 print("Setting breakpoint for line $line"); 238 print("Setting breakpoint for line $line");
241 Library lib = await isolate.rootLibrary.load(); 239 Library lib = await isolate.rootLibrary.load();
242 Script script = lib.scripts.single; 240 Script script = lib.scripts.single;
243 241
244 Breakpoint bpt = await isolate.addBreakpoint(script, line); 242 Breakpoint bpt = await isolate.addBreakpoint(script, line);
(...skipping 27 matching lines...) Expand all
272 for (Frame f in stack['frames']) { 270 for (Frame f in stack['frames']) {
273 sb.write(" $f [${await f.location.getLine()}]\n"); 271 sb.write(" $f [${await f.location.getLine()}]\n");
274 } 272 }
275 throw sb.toString(); 273 throw sb.toString();
276 } else { 274 } else {
277 print('Program is stopped at line: $line'); 275 print('Program is stopped at line: $line');
278 } 276 }
279 }; 277 };
280 } 278 }
281 279
282 280 IsolateTest stoppedInFunction(String functionName,
283 IsolateTest stoppedInFunction(String functionName, {bool contains: false}) { 281 {bool contains: false, bool includeOwner: false}) {
284 return (Isolate isolate) async { 282 return (Isolate isolate) async {
285 print("Checking we are in function: $functionName"); 283 print("Checking we are in function: $functionName");
286 284
287 ServiceMap stack = await isolate.getStack(); 285 ServiceMap stack = await isolate.getStack();
288 expect(stack.type, equals('Stack')); 286 expect(stack.type, equals('Stack'));
289 287
290 List<Frame> frames = stack['frames']; 288 List<Frame> frames = stack['frames'];
291 expect(frames.length, greaterThanOrEqualTo(1)); 289 expect(frames.length, greaterThanOrEqualTo(1));
292 290
293 Frame topFrame = stack['frames'][0]; 291 Frame topFrame = stack['frames'][0];
294 ServiceFunction function = await topFrame.function.load(); 292 ServiceFunction function = await topFrame.function.load();
293 String name = function.name;
294 if (includeOwner) {
295 ServiceFunction owner =
296 await (function.dartOwner as ServiceObject).load();
297 name = '${owner.name}.$name';
298 }
295 final bool matches = 299 final bool matches =
296 contains ? function.name.contains(functionName) : 300 contains ? name.contains(functionName) : name == functionName;
297 function.name == functionName;
298 if (!matches) { 301 if (!matches) {
299 StringBuffer sb = new StringBuffer(); 302 StringBuffer sb = new StringBuffer();
300 sb.write("Expected to be in function $functionName but " 303 sb.write("Expected to be in function $functionName but "
301 "actually in function ${function.name}"); 304 "actually in function $name");
302 sb.write("\nFull stack trace:\n"); 305 sb.write("\nFull stack trace:\n");
303 for (Frame f in stack['frames']) { 306 for (Frame f in stack['frames']) {
304 await f.function.load(); 307 await f.function.load();
305 await (f.function.dartOwner as ServiceObject).load(); 308 await (f.function.dartOwner as ServiceObject).load();
306 String name = f.function.name; 309 String name = f.function.name;
307 String ownerName = (f.function.dartOwner as ServiceObject).name; 310 String ownerName = (f.function.dartOwner as ServiceObject).name;
308 sb.write(" $f [$name] [$ownerName]\n"); 311 sb.write(" $f [$name] [$ownerName]\n");
309 } 312 }
310 throw sb.toString(); 313 throw sb.toString();
311 } else { 314 } else {
312 print('Program is stopped in function: $functionName'); 315 print('Program is stopped in function: $functionName');
313 } 316 }
314 }; 317 };
315 } 318 }
316 319
317
318 Future<Isolate> resumeIsolate(Isolate isolate) { 320 Future<Isolate> resumeIsolate(Isolate isolate) {
319 Completer completer = new Completer(); 321 Completer completer = new Completer();
320 isolate.vm.getEventStream(VM.kDebugStream).then((stream) { 322 isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
321 var subscription; 323 var subscription;
322 subscription = stream.listen((ServiceEvent event) { 324 subscription = stream.listen((ServiceEvent event) {
323 if (event.kind == ServiceEvent.kResume) { 325 if (event.kind == ServiceEvent.kResume) {
324 subscription.cancel(); 326 subscription.cancel();
325 completer.complete(); 327 completer.complete();
326 } 328 }
327 }); 329 });
328 }); 330 });
329 isolate.resume(); 331 isolate.resume();
330 return completer.future; 332 return completer.future;
331 } 333 }
332 334
333
334 Future resumeAndAwaitEvent(Isolate isolate, stream, onEvent) async { 335 Future resumeAndAwaitEvent(Isolate isolate, stream, onEvent) async {
335 Completer completer = new Completer(); 336 Completer completer = new Completer();
336 var sub; 337 var sub;
337 sub = await isolate.vm.listenEventStream( 338 sub = await isolate.vm.listenEventStream(stream, (ServiceEvent event) {
338 stream, 339 var r = onEvent(event);
339 (ServiceEvent event) { 340 if (r is! Future) {
340 var r = onEvent(event); 341 r = new Future.value(r);
341 if (r is! Future) { 342 }
342 r = new Future.value(r); 343 r.then((x) => sub.cancel().then((_) {
343 } 344 completer.complete();
344 r.then((x) => sub.cancel().then((_) { 345 }));
345 completer.complete(); 346 });
346 }));
347 });
348 await isolate.resume(); 347 await isolate.resume();
349 return completer.future; 348 return completer.future;
350 } 349 }
351 350
352 IsolateTest resumeIsolateAndAwaitEvent(stream, onEvent) { 351 IsolateTest resumeIsolateAndAwaitEvent(stream, onEvent) {
353 return (Isolate isolate) async => 352 return (Isolate isolate) async =>
354 resumeAndAwaitEvent(isolate, stream, onEvent); 353 resumeAndAwaitEvent(isolate, stream, onEvent);
355 } 354 }
356 355
357
358 Future<Isolate> stepOver(Isolate isolate) async { 356 Future<Isolate> stepOver(Isolate isolate) async {
359 await isolate.stepOver(); 357 await isolate.stepOver();
360 return hasStoppedAtBreakpoint(isolate); 358 return hasStoppedAtBreakpoint(isolate);
361 } 359 }
362 360
363 Future<Isolate> stepInto(Isolate isolate) async { 361 Future<Isolate> stepInto(Isolate isolate) async {
364 await isolate.stepInto(); 362 await isolate.stepInto();
365 return hasStoppedAtBreakpoint(isolate); 363 return hasStoppedAtBreakpoint(isolate);
366 } 364 }
367 365
368 Future<Isolate> stepOut(Isolate isolate) async { 366 Future<Isolate> stepOut(Isolate isolate) async {
369 await isolate.stepOut(); 367 await isolate.stepOut();
370 return hasStoppedAtBreakpoint(isolate); 368 return hasStoppedAtBreakpoint(isolate);
371 } 369 }
372 370
373
374 Future isolateIsRunning(Isolate isolate) async { 371 Future isolateIsRunning(Isolate isolate) async {
375 await isolate.reload(); 372 await isolate.reload();
376 expect(isolate.running, true); 373 expect(isolate.running, true);
377 } 374 }
378 375
379 Future<Class> getClassFromRootLib(Isolate isolate, String className) async { 376 Future<Class> getClassFromRootLib(Isolate isolate, String className) async {
380 Library rootLib = await isolate.rootLibrary.load(); 377 Library rootLib = await isolate.rootLibrary.load();
381 for (var i = 0; i < rootLib.classes.length; i++) { 378 for (var i = 0; i < rootLib.classes.length; i++) {
382 Class cls = rootLib.classes[i]; 379 Class cls = rootLib.classes[i];
383 if (cls.name == className) { 380 if (cls.name == className) {
384 return cls; 381 return cls;
385 } 382 }
386 } 383 }
387 return null; 384 return null;
388 } 385 }
389 386
390 387 Future<Instance> rootLibraryFieldValue(
391 Future<Instance> rootLibraryFieldValue(Isolate isolate, 388 Isolate isolate, String fieldName) async {
392 String fieldName) async {
393 Library rootLib = await isolate.rootLibrary.load(); 389 Library rootLib = await isolate.rootLibrary.load();
394 Field field = rootLib.variables.singleWhere((v) => v.name == fieldName); 390 Field field = rootLib.variables.singleWhere((v) => v.name == fieldName);
395 await field.load(); 391 await field.load();
396 Instance value = field.staticValue; 392 Instance value = field.staticValue;
397 await value.load(); 393 await value.load();
398 return value; 394 return value;
399 } 395 }
400 396
401 IsolateTest runStepThroughProgramRecordingStops(List<String> recordStops) { 397 IsolateTest runStepThroughProgramRecordingStops(List<String> recordStops) {
402 return (Isolate isolate) async { 398 return (Isolate isolate) async {
(...skipping 15 matching lines...) Expand all
418 // We are at the exit: The test is done. 414 // We are at the exit: The test is done.
419 await cancelStreamSubscription(VM.kDebugStream); 415 await cancelStreamSubscription(VM.kDebugStream);
420 completer.complete(); 416 completer.complete();
421 } 417 }
422 }); 418 });
423 isolate.resume(); 419 isolate.resume();
424 return completer.future; 420 return completer.future;
425 }; 421 };
426 } 422 }
427 423
424 IsolateTest runStepIntoThroughProgramRecordingStops(List<String> recordStops) {
425 return (Isolate isolate) async {
426 Completer completer = new Completer();
427
428 await subscribeToStream(isolate.vm, VM.kDebugStream,
429 (ServiceEvent event) async {
430 if (event.kind == ServiceEvent.kPauseBreakpoint) {
431 await isolate.reload();
432 // We are paused: Step into further.
433 Frame frame = isolate.topFrame;
434 recordStops.add(await frame.location.toUserString());
435 isolate.stepInto();
436 } else if (event.kind == ServiceEvent.kPauseExit) {
437 // We are at the exit: The test is done.
438 await cancelStreamSubscription(VM.kDebugStream);
439 completer.complete();
440 }
441 });
442 isolate.resume();
443 return completer.future;
444 };
445 }
446
428 IsolateTest checkRecordedStops( 447 IsolateTest checkRecordedStops(
429 List<String> recordStops, List<String> expectedStops) { 448 List<String> recordStops, List<String> expectedStops,
449 {bool removeDuplicates = false,
450 bool debugPrint = false,
451 String debugPrintFile,
452 int debugPrintLine}) {
430 return (Isolate isolate) async { 453 return (Isolate isolate) async {
454 if (debugPrint) {
455 for (int i = 0; i < recordStops.length; i++) {
456 String line = recordStops[i];
457 String output = line;
458 int firstColon = line.indexOf(":");
459 int lastColon = line.lastIndexOf(":");
460 if (debugPrintFile != null &&
461 debugPrintLine != null &&
462 firstColon > 0 &&
463 lastColon > 0) {
464 int lineNumber = int.parse(line.substring(firstColon + 1, lastColon));
465 int relativeLineNumber = lineNumber - debugPrintLine;
466 var columnNumber = line.substring(lastColon + 1);
467 var file = line.substring(0, firstColon);
468 if (file == debugPrintFile) {
469 output = '\$file:\${LINE+$relativeLineNumber}:$columnNumber';
470 }
471 }
472 String comma = i == recordStops.length - 1 ? "" : ",";
473 print('"$output"$comma');
474 }
475 }
476 if (removeDuplicates) {
477 recordStops = removeAdjacentDuplicates(recordStops);
478 expectedStops = removeAdjacentDuplicates(expectedStops);
479 }
480
431 int end = recordStops.length < expectedStops.length 481 int end = recordStops.length < expectedStops.length
432 ? recordStops.length 482 ? recordStops.length
433 : expectedStops.length; 483 : expectedStops.length;
434 for (int i = 0; i < end; ++i) { 484 for (int i = 0; i < end; ++i) {
435 expect(recordStops[i], expectedStops[i]); 485 expect(recordStops[i], expectedStops[i]);
436 } 486 }
437 487
438 expect(recordStops.length >= expectedStops.length, true, 488 expect(recordStops.length >= expectedStops.length, true,
439 reason: "Expects at least ${expectedStops.length} breaks."); 489 reason: "Expects at least ${expectedStops.length} breaks.");
440 }; 490 };
441 } 491 }
492
493 List<String> removeAdjacentDuplicates(List<String> fromList) {
494 List<String> result = <String>[];
495 String latestLine;
496 for (String s in fromList) {
497 if (s == latestLine) continue;
498 latestLine = s;
499 result.add(s);
500 }
501 return result;
502 }
503
504 bool isKernel() {
505 for (String argument in Platform.executableArguments) {
506 if (argument.startsWith("--dfe=")) return true;
507 }
508 return false;
509 }
510
511 E ifKernel<E>(E then, E otherwise) {
512 if (isKernel()) return then;
513 return otherwise;
514 }
515
516 void ifKernelExecute(Function kernelFunction, Function nonKernelFunction) {
517 if (isKernel()) {
518 kernelFunction();
519 } else {
520 nonKernelFunction();
521 }
522 }
523
524 void nonKernelExecute(Function nonKernelFunction) {
525 if (!isKernel()) {
526 nonKernelFunction();
527 }
528 }
529
530 void kernelExecute(Function kernelFunction) {
531 if (isKernel()) {
532 kernelFunction();
533 }
534 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698