| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // VMOptions=--error_on_bad_type --error_on_bad_override --verbose_debug --trac
e_service | 4 // VMOptions=--error_on_bad_type --error_on_bad_override --verbose_debug --trac
e_service |
| 5 | 5 |
| 6 import 'dart:async'; | 6 import 'dart:async'; |
| 7 import 'dart:developer'; | 7 import 'dart:developer'; |
| 8 | 8 |
| 9 import 'test_helper.dart'; | 9 import 'test_helper.dart'; |
| 10 import 'service_test_common.dart'; | 10 import 'service_test_common.dart'; |
| 11 | 11 |
| 12 import 'package:observatory/models.dart' as M; | 12 import 'package:observatory/models.dart' as M; |
| 13 import 'package:observatory/service_io.dart'; | 13 import 'package:observatory/service_io.dart'; |
| 14 import 'package:unittest/unittest.dart'; | 14 import 'package:unittest/unittest.dart'; |
| 15 | 15 |
| 16 const int LINE_A = 25; | 16 const int LINE_A = 22; |
| 17 const int LINE_B = 27; | 17 const int LINE_B = 24; |
| 18 const int LINE_C = 29; | |
| 19 const int LINE_D = 30; | |
| 20 | 18 |
| 21 // This tests the low level synthetic breakpoint added / paused / removed | 19 // This tests the asyncStepOver command. |
| 22 // machinery triggered by the step OverAwait command. | 20 asyncFunction() async { |
| 23 asyncWithoutAwait() async { | |
| 24 debugger(); | 21 debugger(); |
| 25 print('a'); // LINE_A | 22 print('a'); // LINE_A |
| 26 await new Future.delayed(new Duration(seconds: 2)); | 23 await new Future.delayed(new Duration(seconds: 2)); |
| 27 print('b'); // LINE_B | 24 print('b'); // LINE_B |
| 28 debugger(); // LINE_C | |
| 29 debugger(); // LINE_D | |
| 30 } | 25 } |
| 31 | 26 |
| 32 testMain() { | 27 testMain() { |
| 33 asyncWithoutAwait(); | 28 asyncFunction(); |
| 34 } | 29 } |
| 35 | 30 |
| 36 Breakpoint syntheticBreakpoint; | |
| 37 | |
| 38 Future<Isolate> testLowLevelAwaitOver( | |
| 39 Isolate isolate) { | |
| 40 assert(M.isAtAsyncSuspension(isolate.pauseEvent)); | |
| 41 | |
| 42 int state = 0; | |
| 43 bool firstResume = true; | |
| 44 handleBreakpointAdded(ServiceEvent event) { | |
| 45 expect(syntheticBreakpoint, isNull); | |
| 46 expect(state, 0); | |
| 47 if (!event.breakpoint.isSyntheticAsyncContinuation) { | |
| 48 // Not a synthetic async breakpoint. | |
| 49 return; | |
| 50 } | |
| 51 if (event.owner != isolate) { | |
| 52 // Wrong isolate. | |
| 53 return; | |
| 54 } | |
| 55 syntheticBreakpoint = event.breakpoint; | |
| 56 print('!!!! Synthetic async breakpoint added ${syntheticBreakpoint}'); | |
| 57 state = 1; | |
| 58 } | |
| 59 | |
| 60 handleResume(ServiceEvent event) { | |
| 61 if (firstResume) { | |
| 62 expect(state, 1); | |
| 63 if (event.owner != isolate) { | |
| 64 // Wrong isolate. | |
| 65 return; | |
| 66 } | |
| 67 print('!!!! Got first resume.'); | |
| 68 state = 2; | |
| 69 firstResume = false; | |
| 70 } else { | |
| 71 expect(state, 3); | |
| 72 if (event.owner != isolate) { | |
| 73 // Wrong isolate. | |
| 74 return; | |
| 75 } | |
| 76 print('!!!! Got second resume.'); | |
| 77 state = 4; | |
| 78 } | |
| 79 | |
| 80 } | |
| 81 | |
| 82 handlePauseBreakpoint(ServiceEvent event) { | |
| 83 expect(syntheticBreakpoint, isNotNull); | |
| 84 expect(state, 2); | |
| 85 if (!event.breakpoint.isSyntheticAsyncContinuation) { | |
| 86 // Not a synthetic async breakpoint. | |
| 87 return; | |
| 88 } | |
| 89 if (event.owner != isolate) { | |
| 90 // Wrong isolate. | |
| 91 return; | |
| 92 } | |
| 93 expect(event.breakpoint, equals(syntheticBreakpoint)); | |
| 94 print('!!!! Paused at synthetic async breakpoint ${syntheticBreakpoint}'); | |
| 95 state = 3; | |
| 96 } | |
| 97 | |
| 98 handleBreakpointRemoved(ServiceEvent event) { | |
| 99 expect(syntheticBreakpoint, isNotNull); | |
| 100 expect(state, 4); | |
| 101 if (!event.breakpoint.isSyntheticAsyncContinuation) { | |
| 102 // Not a synthetic async breakpoint. | |
| 103 return; | |
| 104 } | |
| 105 if (event.owner != isolate) { | |
| 106 // Wrong isolate. | |
| 107 return; | |
| 108 } | |
| 109 expect(event.breakpoint, equals(syntheticBreakpoint)); | |
| 110 print('!!!! Synthetic async breakpoint removed ${syntheticBreakpoint}'); | |
| 111 state = 5; | |
| 112 syntheticBreakpoint = null; | |
| 113 } | |
| 114 | |
| 115 // Set up a listener to wait for debugger events. | |
| 116 Completer completer = new Completer(); | |
| 117 isolate.vm.getEventStream(VM.kDebugStream).then((stream) { | |
| 118 var subscription; | |
| 119 subscription = stream.listen((ServiceEvent event) async { | |
| 120 if (event.kind == ServiceEvent.kBreakpointAdded) { | |
| 121 handleBreakpointAdded(event); | |
| 122 expect(state, 1); | |
| 123 } else if (event.kind == ServiceEvent.kResume) { | |
| 124 if (firstResume) { | |
| 125 handleResume(event); | |
| 126 expect(state, 2); | |
| 127 } else { | |
| 128 handleResume(event); | |
| 129 expect(state, 4); | |
| 130 } | |
| 131 } else if (event.kind == ServiceEvent.kPauseBreakpoint) { | |
| 132 handlePauseBreakpoint(event); | |
| 133 expect(state, 3); | |
| 134 // Check that we are paused after the await statement. | |
| 135 await (stoppedAtLine(LINE_B)(isolate)); | |
| 136 // Resume the isolate so that we trigger the breakpoint removal. | |
| 137 print('!!!! Triggering synthetic breakpoint removal.'); | |
| 138 isolate.resume(); | |
| 139 } else if (event.kind == ServiceEvent.kBreakpointRemoved) { | |
| 140 handleBreakpointRemoved(event); | |
| 141 expect(state, 5); | |
| 142 subscription.cancel(); | |
| 143 if (completer != null) { | |
| 144 // Reload to update isolate.pauseEvent. | |
| 145 completer.complete(isolate.reload()); | |
| 146 completer = null; | |
| 147 } | |
| 148 } | |
| 149 }); | |
| 150 }); | |
| 151 | |
| 152 isolate.stepOverAsyncSuspension(); | |
| 153 | |
| 154 return completer.future; // Will complete when breakpoint added. | |
| 155 } | |
| 156 | |
| 157 | |
| 158 var tests = [ | 31 var tests = [ |
| 159 hasStoppedAtBreakpoint, | 32 hasStoppedAtBreakpoint, |
| 160 stoppedAtLine(LINE_A), | 33 stoppedAtLine(LINE_A), |
| 161 stepOver, | 34 stepOver, // At new Duration(). |
| 162 stepOver, | 35 stepOver, // At new Future.delayed(). |
| 163 stepOver, | 36 stepOver, // At async. |
| 37 // Check that we are at the async statement |
| 164 (Isolate isolate) async { | 38 (Isolate isolate) async { |
| 165 expect(M.isAtAsyncSuspension(isolate.pauseEvent), isTrue); | 39 expect(M.isAtAsyncSuspension(isolate.pauseEvent), isTrue); |
| 166 expect(syntheticBreakpoint, isNull); | |
| 167 }, | 40 }, |
| 168 testLowLevelAwaitOver, | 41 asyncStepOver, |
| 169 hasStoppedAtBreakpoint, | 42 stoppedAtLine(LINE_B), |
| 170 stoppedAtLine(LINE_C), | |
| 171 resumeIsolate, | |
| 172 hasStoppedAtBreakpoint, | |
| 173 stoppedAtLine(LINE_D), | |
| 174 resumeIsolate, | 43 resumeIsolate, |
| 175 ]; | 44 ]; |
| 176 | 45 |
| 177 main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain); | 46 main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain); |
| OLD | NEW |