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 |