OLD | NEW |
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 'package:observatory/models.dart' as M; | 8 import 'package:observatory/models.dart' as M; |
9 import 'package:observatory/service_common.dart'; | 9 import 'package:observatory/service_common.dart'; |
10 import 'package:unittest/unittest.dart'; | 10 import 'package:unittest/unittest.dart'; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 completeError(e); | 92 completeError(e); |
93 return pausedAtSyntheticBreakpoint.future; | 93 return pausedAtSyntheticBreakpoint.future; |
94 } | 94 } |
95 | 95 |
96 Breakpoint syntheticBreakpoint; | 96 Breakpoint syntheticBreakpoint; |
97 | 97 |
98 subscription = stream.listen((ServiceEvent event) async { | 98 subscription = stream.listen((ServiceEvent event) async { |
99 // Synthetic breakpoint add event. This is the first event we will | 99 // Synthetic breakpoint add event. This is the first event we will |
100 // receive. | 100 // receive. |
101 bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) && | 101 bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) && |
102 (event.breakpoint.isSyntheticAsyncContinuation) && | 102 (event.breakpoint.isSyntheticAsyncContinuation) && |
103 (event.owner == isolate); | 103 (event.owner == isolate); |
104 // Resume after synthetic breakpoint added. This is the second event | 104 // Resume after synthetic breakpoint added. This is the second event |
105 // we will recieve. | 105 // we will recieve. |
106 bool isResume = (event.kind == ServiceEvent.kResume) && | 106 bool isResume = (event.kind == ServiceEvent.kResume) && |
107 (syntheticBreakpoint != null) && | 107 (syntheticBreakpoint != null) && |
108 (event.owner == isolate); | 108 (event.owner == isolate); |
109 // Paused at synthetic breakpoint. This is the third event we will | 109 // Paused at synthetic breakpoint. This is the third event we will |
110 // receive. | 110 // receive. |
111 bool isPaused = (event.kind == ServiceEvent.kPauseBreakpoint) && | 111 bool isPaused = (event.kind == ServiceEvent.kPauseBreakpoint) && |
112 (syntheticBreakpoint != null) && | 112 (syntheticBreakpoint != null) && |
113 (event.breakpoint == syntheticBreakpoint); | 113 (event.breakpoint == syntheticBreakpoint); |
114 if (isAdd) { | 114 if (isAdd) { |
115 syntheticBreakpoint = event.breakpoint; | 115 syntheticBreakpoint = event.breakpoint; |
116 } else if (isResume) {} else if (isPaused) { | 116 } else if (isResume) { |
| 117 } else if (isPaused) { |
117 pausedAtSyntheticBreakpoint.complete(isolate); | 118 pausedAtSyntheticBreakpoint.complete(isolate); |
118 syntheticBreakpoint = null; | 119 syntheticBreakpoint = null; |
119 cancelSubscription(); | 120 cancelSubscription(); |
120 } | 121 } |
121 }); | 122 }); |
122 | 123 |
123 // Issue the step OverAwait command. | 124 // Issue the step OverAwait command. |
124 try { | 125 try { |
125 await isolate.stepOverAsyncSuspension(); | 126 await isolate.stepOverAsyncSuspension(); |
126 } catch (e) { | 127 } catch (e) { |
(...skipping 22 matching lines...) Expand all Loading... |
149 return false; | 150 return false; |
150 } | 151 } |
151 } | 152 } |
152 | 153 |
153 Future<Isolate> hasPausedFor(Isolate isolate, String kind) { | 154 Future<Isolate> hasPausedFor(Isolate isolate, String kind) { |
154 // Set up a listener to wait for breakpoint events. | 155 // Set up a listener to wait for breakpoint events. |
155 Completer completer = new Completer(); | 156 Completer completer = new Completer(); |
156 isolate.vm.getEventStream(VM.kDebugStream).then((stream) { | 157 isolate.vm.getEventStream(VM.kDebugStream).then((stream) { |
157 var subscription; | 158 var subscription; |
158 subscription = stream.listen((ServiceEvent event) { | 159 subscription = stream.listen((ServiceEvent event) { |
159 if ((isolate == event.isolate) && (event.kind == kind)) { | 160 if ((isolate == event.isolate) && (event.kind == kind)) { |
160 if (completer != null) { | 161 if (completer != null) { |
161 // Reload to update isolate.pauseEvent. | 162 // Reload to update isolate.pauseEvent. |
162 print('Paused with $kind'); | 163 print('Paused with $kind'); |
163 subscription.cancel(); | 164 subscription.cancel(); |
164 completer.complete(isolate.reload()); | 165 completer.complete(isolate.reload()); |
165 completer = null; | 166 completer = null; |
| 167 } |
166 } | 168 } |
167 } | |
168 }); | 169 }); |
169 | 170 |
170 // Pause may have happened before we subscribed. | 171 // Pause may have happened before we subscribed. |
171 isolate.reload().then((_) { | 172 isolate.reload().then((_) { |
172 if ((isolate.pauseEvent != null) && | 173 if ((isolate.pauseEvent != null) && |
173 isEventOfKind(isolate.pauseEvent, kind)) { | 174 isEventOfKind(isolate.pauseEvent, kind)) { |
174 // Already waiting at a breakpoint. | 175 // Already waiting at a breakpoint. |
175 if (completer != null) { | 176 if (completer != null) { |
176 print('Paused with $kind'); | 177 print('Paused with $kind'); |
177 subscription.cancel(); | 178 subscription.cancel(); |
178 completer.complete(isolate); | 179 completer.complete(isolate); |
179 completer = null; | 180 completer = null; |
180 } | 181 } |
181 } | 182 } |
182 }); | 183 }); |
183 }); | 184 }); |
184 | 185 |
185 return completer.future; // Will complete when breakpoint hit. | 186 return completer.future; // Will complete when breakpoint hit. |
186 } | 187 } |
187 | 188 |
188 Future<Isolate> hasStoppedAtBreakpoint(Isolate isolate) { | 189 Future<Isolate> hasStoppedAtBreakpoint(Isolate isolate) { |
189 return hasPausedFor(isolate, ServiceEvent.kPauseBreakpoint); | 190 return hasPausedFor(isolate, ServiceEvent.kPauseBreakpoint); |
190 } | 191 } |
191 | 192 |
192 Future<Isolate> hasStoppedPostRequest(Isolate isolate) { | 193 Future<Isolate> hasStoppedPostRequest(Isolate isolate) { |
193 return hasPausedFor(isolate, ServiceEvent.kPausePostRequest); | 194 return hasPausedFor(isolate, ServiceEvent.kPausePostRequest); |
194 } | 195 } |
195 | 196 |
196 Future<Isolate> hasStoppedWithUnhandledException(Isolate isolate) { | 197 Future<Isolate> hasStoppedWithUnhandledException(Isolate isolate) { |
197 return hasPausedFor(isolate, ServiceEvent.kPauseException); | 198 return hasPausedFor(isolate, ServiceEvent.kPauseException); |
198 } | 199 } |
199 | 200 |
200 Future<Isolate> hasStoppedAtExit(Isolate isolate) { | 201 Future<Isolate> hasStoppedAtExit(Isolate isolate) { |
201 return hasPausedFor(isolate, ServiceEvent.kPauseExit); | 202 return hasPausedFor(isolate, ServiceEvent.kPauseExit); |
202 } | 203 } |
203 | 204 |
204 Future<Isolate> hasPausedAtStart(Isolate isolate) { | 205 Future<Isolate> hasPausedAtStart(Isolate isolate) { |
205 return hasPausedFor(isolate, ServiceEvent.kPauseStart); | 206 return hasPausedFor(isolate, ServiceEvent.kPauseStart); |
206 } | 207 } |
207 | 208 |
208 Future<Isolate> markDartColonLibrariesDebuggable(Isolate isolate) async { | 209 Future<Isolate> markDartColonLibrariesDebuggable(Isolate isolate) async { |
209 await isolate.reload(); | 210 await isolate.reload(); |
210 for (Library lib in isolate.libraries) { | 211 for (Library lib in isolate.libraries) { |
211 await lib.load(); | 212 await lib.load(); |
212 if (lib.uri.startsWith('dart:') && !lib.uri.startsWith('dart:_')) { | 213 if (lib.uri.startsWith('dart:') && |
| 214 !lib.uri.startsWith('dart:_')) { |
213 var setDebugParams = { | 215 var setDebugParams = { |
214 'libraryId': lib.id, | 216 'libraryId': lib.id, |
215 'isDebuggable': true, | 217 'isDebuggable': true, |
216 }; | 218 }; |
217 Map<String, dynamic> result = await isolate.invokeRpcNoUpgrade( | 219 Map<String, dynamic> result = |
218 'setLibraryDebuggable', setDebugParams); | 220 await isolate.invokeRpcNoUpgrade('setLibraryDebuggable', |
| 221 setDebugParams); |
219 } | 222 } |
220 } | 223 } |
221 return isolate; | 224 return isolate; |
222 } | 225 } |
223 | 226 |
224 IsolateTest reloadSources([bool pause = false]) { | 227 IsolateTest reloadSources([bool pause = false]) { |
225 return (Isolate isolate) async { | 228 return (Isolate isolate) async { |
226 Map<String, dynamic> params = <String, dynamic>{}; | 229 Map<String, dynamic> params = <String, dynamic>{ }; |
227 if (pause == true) { | 230 if (pause == true) { |
228 params['pause'] = pause; | 231 params['pause'] = pause; |
229 } | 232 } |
230 return isolate.invokeRpc('reloadSources', params); | 233 return isolate.invokeRpc('reloadSources', params); |
231 }; | 234 }; |
232 } | 235 } |
233 | 236 |
234 // Currying is your friend. | 237 // Currying is your friend. |
235 IsolateTest setBreakpointAtLine(int line) { | 238 IsolateTest setBreakpointAtLine(int line) { |
236 return (Isolate isolate) async { | 239 return (Isolate isolate) async { |
237 print("Setting breakpoint for line $line"); | 240 print("Setting breakpoint for line $line"); |
238 Library lib = await isolate.rootLibrary.load(); | 241 Library lib = await isolate.rootLibrary.load(); |
239 Script script = lib.scripts.single; | 242 Script script = lib.scripts.single; |
240 | 243 |
241 Breakpoint bpt = await isolate.addBreakpoint(script, line); | 244 Breakpoint bpt = await isolate.addBreakpoint(script, line); |
(...skipping 27 matching lines...) Expand all Loading... |
269 for (Frame f in stack['frames']) { | 272 for (Frame f in stack['frames']) { |
270 sb.write(" $f [${await f.location.getLine()}]\n"); | 273 sb.write(" $f [${await f.location.getLine()}]\n"); |
271 } | 274 } |
272 throw sb.toString(); | 275 throw sb.toString(); |
273 } else { | 276 } else { |
274 print('Program is stopped at line: $line'); | 277 print('Program is stopped at line: $line'); |
275 } | 278 } |
276 }; | 279 }; |
277 } | 280 } |
278 | 281 |
| 282 |
279 IsolateTest stoppedInFunction(String functionName, {bool contains: false}) { | 283 IsolateTest stoppedInFunction(String functionName, {bool contains: false}) { |
280 return (Isolate isolate) async { | 284 return (Isolate isolate) async { |
281 print("Checking we are in function: $functionName"); | 285 print("Checking we are in function: $functionName"); |
282 | 286 |
283 ServiceMap stack = await isolate.getStack(); | 287 ServiceMap stack = await isolate.getStack(); |
284 expect(stack.type, equals('Stack')); | 288 expect(stack.type, equals('Stack')); |
285 | 289 |
286 List<Frame> frames = stack['frames']; | 290 List<Frame> frames = stack['frames']; |
287 expect(frames.length, greaterThanOrEqualTo(1)); | 291 expect(frames.length, greaterThanOrEqualTo(1)); |
288 | 292 |
289 Frame topFrame = stack['frames'][0]; | 293 Frame topFrame = stack['frames'][0]; |
290 ServiceFunction function = await topFrame.function.load(); | 294 ServiceFunction function = await topFrame.function.load(); |
291 final bool matches = contains | 295 final bool matches = |
292 ? function.name.contains(functionName) | 296 contains ? function.name.contains(functionName) : |
293 : function.name == functionName; | 297 function.name == functionName; |
294 if (!matches) { | 298 if (!matches) { |
295 StringBuffer sb = new StringBuffer(); | 299 StringBuffer sb = new StringBuffer(); |
296 sb.write("Expected to be in function $functionName but " | 300 sb.write("Expected to be in function $functionName but " |
297 "actually in function ${function.name}"); | 301 "actually in function ${function.name}"); |
298 sb.write("\nFull stack trace:\n"); | 302 sb.write("\nFull stack trace:\n"); |
299 for (Frame f in stack['frames']) { | 303 for (Frame f in stack['frames']) { |
300 await f.function.load(); | 304 await f.function.load(); |
301 await (f.function.dartOwner as ServiceObject).load(); | 305 await (f.function.dartOwner as ServiceObject).load(); |
302 String name = f.function.name; | 306 String name = f.function.name; |
303 String ownerName = (f.function.dartOwner as ServiceObject).name; | 307 String ownerName = (f.function.dartOwner as ServiceObject).name; |
304 sb.write(" $f [$name] [$ownerName]\n"); | 308 sb.write(" $f [$name] [$ownerName]\n"); |
305 } | 309 } |
306 throw sb.toString(); | 310 throw sb.toString(); |
307 } else { | 311 } else { |
308 print('Program is stopped in function: $functionName'); | 312 print('Program is stopped in function: $functionName'); |
309 } | 313 } |
310 }; | 314 }; |
311 } | 315 } |
312 | 316 |
| 317 |
313 Future<Isolate> resumeIsolate(Isolate isolate) { | 318 Future<Isolate> resumeIsolate(Isolate isolate) { |
314 Completer completer = new Completer(); | 319 Completer completer = new Completer(); |
315 isolate.vm.getEventStream(VM.kDebugStream).then((stream) { | 320 isolate.vm.getEventStream(VM.kDebugStream).then((stream) { |
316 var subscription; | 321 var subscription; |
317 subscription = stream.listen((ServiceEvent event) { | 322 subscription = stream.listen((ServiceEvent event) { |
318 if (event.kind == ServiceEvent.kResume) { | 323 if (event.kind == ServiceEvent.kResume) { |
319 subscription.cancel(); | 324 subscription.cancel(); |
320 completer.complete(); | 325 completer.complete(); |
321 } | 326 } |
322 }); | 327 }); |
323 }); | 328 }); |
324 isolate.resume(); | 329 isolate.resume(); |
325 return completer.future; | 330 return completer.future; |
326 } | 331 } |
327 | 332 |
| 333 |
328 Future resumeAndAwaitEvent(Isolate isolate, stream, onEvent) async { | 334 Future resumeAndAwaitEvent(Isolate isolate, stream, onEvent) async { |
329 Completer completer = new Completer(); | 335 Completer completer = new Completer(); |
330 var sub; | 336 var sub; |
331 sub = await isolate.vm.listenEventStream(stream, (ServiceEvent event) { | 337 sub = await isolate.vm.listenEventStream( |
332 var r = onEvent(event); | 338 stream, |
333 if (r is! Future) { | 339 (ServiceEvent event) { |
334 r = new Future.value(r); | 340 var r = onEvent(event); |
335 } | 341 if (r is! Future) { |
336 r.then((x) => sub.cancel().then((_) { | 342 r = new Future.value(r); |
337 completer.complete(); | 343 } |
338 })); | 344 r.then((x) => sub.cancel().then((_) { |
339 }); | 345 completer.complete(); |
| 346 })); |
| 347 }); |
340 await isolate.resume(); | 348 await isolate.resume(); |
341 return completer.future; | 349 return completer.future; |
342 } | 350 } |
343 | 351 |
344 IsolateTest resumeIsolateAndAwaitEvent(stream, onEvent) { | 352 IsolateTest resumeIsolateAndAwaitEvent(stream, onEvent) { |
345 return (Isolate isolate) async => | 353 return (Isolate isolate) async => |
346 resumeAndAwaitEvent(isolate, stream, onEvent); | 354 resumeAndAwaitEvent(isolate, stream, onEvent); |
347 } | 355 } |
348 | 356 |
| 357 |
349 Future<Isolate> stepOver(Isolate isolate) async { | 358 Future<Isolate> stepOver(Isolate isolate) async { |
350 await isolate.stepOver(); | 359 await isolate.stepOver(); |
351 return hasStoppedAtBreakpoint(isolate); | 360 return hasStoppedAtBreakpoint(isolate); |
352 } | 361 } |
353 | 362 |
354 Future<Isolate> stepInto(Isolate isolate) async { | 363 Future<Isolate> stepInto(Isolate isolate) async { |
355 await isolate.stepInto(); | 364 await isolate.stepInto(); |
356 return hasStoppedAtBreakpoint(isolate); | 365 return hasStoppedAtBreakpoint(isolate); |
357 } | 366 } |
358 | 367 |
359 Future<Isolate> stepOut(Isolate isolate) async { | 368 Future<Isolate> stepOut(Isolate isolate) async { |
360 await isolate.stepOut(); | 369 await isolate.stepOut(); |
361 return hasStoppedAtBreakpoint(isolate); | 370 return hasStoppedAtBreakpoint(isolate); |
362 } | 371 } |
363 | 372 |
| 373 |
364 Future isolateIsRunning(Isolate isolate) async { | 374 Future isolateIsRunning(Isolate isolate) async { |
365 await isolate.reload(); | 375 await isolate.reload(); |
366 expect(isolate.running, true); | 376 expect(isolate.running, true); |
367 } | 377 } |
368 | 378 |
369 Future<Class> getClassFromRootLib(Isolate isolate, String className) async { | 379 Future<Class> getClassFromRootLib(Isolate isolate, String className) async { |
370 Library rootLib = await isolate.rootLibrary.load(); | 380 Library rootLib = await isolate.rootLibrary.load(); |
371 for (var i = 0; i < rootLib.classes.length; i++) { | 381 for (var i = 0; i < rootLib.classes.length; i++) { |
372 Class cls = rootLib.classes[i]; | 382 Class cls = rootLib.classes[i]; |
373 if (cls.name == className) { | 383 if (cls.name == className) { |
374 return cls; | 384 return cls; |
375 } | 385 } |
376 } | 386 } |
377 return null; | 387 return null; |
378 } | 388 } |
379 | 389 |
380 Future<Instance> rootLibraryFieldValue( | 390 |
381 Isolate isolate, String fieldName) async { | 391 Future<Instance> rootLibraryFieldValue(Isolate isolate, |
| 392 String fieldName) async { |
382 Library rootLib = await isolate.rootLibrary.load(); | 393 Library rootLib = await isolate.rootLibrary.load(); |
383 Field field = rootLib.variables.singleWhere((v) => v.name == fieldName); | 394 Field field = rootLib.variables.singleWhere((v) => v.name == fieldName); |
384 await field.load(); | 395 await field.load(); |
385 Instance value = field.staticValue; | 396 Instance value = field.staticValue; |
386 await value.load(); | 397 await value.load(); |
387 return value; | 398 return value; |
388 } | 399 } |
389 | 400 |
390 IsolateTest runStepThroughProgramRecordingStops(List<String> recordStops) { | 401 IsolateTest runStepThroughProgramRecordingStops(List<String> recordStops) { |
391 return (Isolate isolate) async { | 402 return (Isolate isolate) async { |
(...skipping 29 matching lines...) Expand all Loading... |
421 ? recordStops.length | 432 ? recordStops.length |
422 : expectedStops.length; | 433 : expectedStops.length; |
423 for (int i = 0; i < end; ++i) { | 434 for (int i = 0; i < end; ++i) { |
424 expect(recordStops[i], expectedStops[i]); | 435 expect(recordStops[i], expectedStops[i]); |
425 } | 436 } |
426 | 437 |
427 expect(recordStops.length >= expectedStops.length, true, | 438 expect(recordStops.length >= expectedStops.length, true, |
428 reason: "Expects at least ${expectedStops.length} breaks."); | 439 reason: "Expects at least ${expectedStops.length} breaks."); |
429 }; | 440 }; |
430 } | 441 } |
OLD | NEW |