| // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | import 'dart:developer'; | 
 | import 'package:observatory/service_io.dart'; | 
 | import 'package:test/test.dart'; | 
 | import 'service_test_common.dart'; | 
 | import 'test_helper.dart'; | 
 |  | 
 | const int LINE = 106; | 
 | const int LINE_A = 23; | 
 | const int LINE_B = 36; | 
 | const int LINE_C = 47; | 
 | const int LINE_D = 61; | 
 | const int LINE_E = 78; | 
 | const int LINE_F = 93; | 
 |  | 
 | // break statement | 
 | Stream<int> testBreak() async* { | 
 |   for (int t = 0; t < 10; t++) { | 
 |     try { | 
 |       if (t == 1) break; | 
 |       await throwException(); // LINE_A | 
 |     } catch (e) {} finally { | 
 |       yield t; | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | // return statement | 
 | Stream<int> testReturn() async* { | 
 |   for (int t = 0; t < 10; t++) { | 
 |     try { | 
 |       yield t; | 
 |       if (t == 1) return; | 
 |       await throwException(); // LINE_B | 
 |     } catch (e) {} finally { | 
 |       yield t; | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | // Multiple functions | 
 | Stream<int> testMultipleFunctions() async* { | 
 |   try { | 
 |     yield 0; | 
 |     await throwException(); // LINE_C | 
 |   } catch (e) {} finally { | 
 |     yield 1; | 
 |   } | 
 | } | 
 |  | 
 | // continue statement | 
 | Stream<int> testContinueSwitch() async* { | 
 |   int currentState = 0; | 
 |   switch (currentState) { | 
 |     case 0: | 
 |       { | 
 |         try { | 
 |           if (currentState == 1) continue label; | 
 |           await throwException(); // LINE_D | 
 |         } catch (e) {} finally { | 
 |           yield 0; | 
 |         } | 
 |         yield 1; | 
 |         break; | 
 |       } | 
 |     label: | 
 |     case 1: | 
 |       break; | 
 |   } | 
 | } | 
 |  | 
 | Stream<int> testNestFinally() async* { | 
 |   int i = 0; | 
 |   try { | 
 |     if (i == 1) return; | 
 |     await throwException(); //LINE_E | 
 |   } catch (e) {} finally { | 
 |     try { | 
 |       yield i; | 
 |     } finally { | 
 |       yield 1; | 
 |     } | 
 |     yield 1; | 
 |   } | 
 | } | 
 |  | 
 | Stream<int> testAsyncClosureInFinally() async* { | 
 |   int i = 0; | 
 |   try { | 
 |     if (i == 1) return; | 
 |     await throwException(); //LINE_F | 
 |   } catch (e) {} finally { | 
 |     inner() async { | 
 |       await Future.delayed(Duration(milliseconds: 10)); | 
 |     } | 
 |  | 
 |     await inner; | 
 |     yield 1; | 
 |   } | 
 | } | 
 |  | 
 | Future<void> throwException() async { | 
 |   await Future.delayed(Duration(milliseconds: 10)); | 
 |   throw new Exception(""); // LINE | 
 | } | 
 |  | 
 | code() async { | 
 |   await for (var x in testBreak()) {} | 
 |   await for (var x in testReturn()) {} | 
 |   await for (var x in testMultipleFunctions()) {} | 
 |   await for (var x in testContinueSwitch()) {} | 
 |   await for (var x in testNestFinally()) {} | 
 |   await for (var x in testAsyncClosureInFinally()) {} | 
 | } | 
 |  | 
 | var tests = <IsolateTest>[ | 
 |   hasPausedAtStart, | 
 |   setBreakpointAtLine(LINE), | 
 |   resumeIsolate, | 
 |   hasStoppedAtBreakpoint, | 
 |   stoppedAtLine(LINE), | 
 |   (Isolate isolate) async { | 
 |     // test break statement | 
 |     ServiceMap stack = await isolate.getStack(); | 
 |     expect(stack['awaiterFrames'], isNotNull); | 
 |     expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2)); | 
 |  | 
 |     // Check second top frame contains correct line number | 
 |     Script script = stack['awaiterFrames'][1].location.script; | 
 |     expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos), | 
 |         equals(LINE_A)); | 
 |   }, | 
 |   resumeIsolate, | 
 |   hasStoppedAtBreakpoint, | 
 |   stoppedAtLine(LINE), | 
 |   (Isolate isolate) async { | 
 |     // test return statement | 
 |     ServiceMap stack = await isolate.getStack(); | 
 |     expect(stack['awaiterFrames'], isNotNull); | 
 |     expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2)); | 
 |  | 
 |     // Check second top frame contains correct line number | 
 |     Script script = stack['awaiterFrames'][1].location.script; | 
 |     expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos), | 
 |         equals(LINE_B)); | 
 |   }, | 
 |   resumeIsolate, | 
 |   hasStoppedAtBreakpoint, | 
 |   stoppedAtLine(LINE), | 
 |   (Isolate isolate) async { | 
 |     // test break statement | 
 |     ServiceMap stack = await isolate.getStack(); | 
 |     expect(stack['awaiterFrames'], isNotNull); | 
 |     expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2)); | 
 |  | 
 |     // Check second top frame contains correct line number | 
 |     Script script = stack['awaiterFrames'][1].location.script; | 
 |     expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos), | 
 |         equals(LINE_C)); | 
 |   }, | 
 |   resumeIsolate, | 
 |   hasStoppedAtBreakpoint, | 
 |   stoppedAtLine(LINE), | 
 |   (Isolate isolate) async { | 
 |     // test break statement | 
 |     ServiceMap stack = await isolate.getStack(); | 
 |     expect(stack['awaiterFrames'], isNotNull); | 
 |     expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2)); | 
 |  | 
 |     // Check second top frame contains correct line number | 
 |     Script script = stack['awaiterFrames'][1].location.script; | 
 |     expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos), | 
 |         equals(LINE_D)); | 
 |   }, | 
 |   resumeIsolate, | 
 |   hasStoppedAtBreakpoint, | 
 |   stoppedAtLine(LINE), | 
 |   (Isolate isolate) async { | 
 |     // test nested finally statement | 
 |     ServiceMap stack = await isolate.getStack(); | 
 |     expect(stack['awaiterFrames'], isNotNull); | 
 |     expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2)); | 
 |  | 
 |     // Check second top frame contains correct line number | 
 |     Script script = stack['awaiterFrames'][1].location.script; | 
 |     expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos), | 
 |         equals(LINE_E)); | 
 |   }, | 
 |   resumeIsolate, | 
 |   hasStoppedAtBreakpoint, | 
 |   stoppedAtLine(LINE), | 
 |   (Isolate isolate) async { | 
 |     // test async closure within finally block | 
 |     ServiceMap stack = await isolate.getStack(); | 
 |     expect(stack['awaiterFrames'], isNotNull); | 
 |     expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2)); | 
 |  | 
 |     // Check second top frame contains correct line number | 
 |     Script script = stack['awaiterFrames'][1].location.script; | 
 |     expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos), | 
 |         equals(LINE_F)); | 
 |   }, | 
 |   resumeIsolate, | 
 |   hasStoppedAtExit | 
 | ]; | 
 |  | 
 | main(args) { | 
 |   runIsolateTestsSynchronous(args, tests, | 
 |       testeeConcurrent: code, pause_on_start: true, pause_on_exit: true); | 
 | } |