// 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:async'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'common/service_test_common.dart'; import 'common/test_helper.dart'; int counter = 0; void periodicTask(_) { counter++; counter++; // Line 16. We set our breakpoint here. counter++; if (counter % 300 == 0) { print('counter = $counter'); } } void startTimer() { Timer.periodic(const Duration(milliseconds: 10), periodicTask); } int getLineNumberFromTokenPos(Script s, int token) => s.tokenPosTable![token].first; var tests = [ // Pause (VmService? service, IsolateRef? isolateRef) async { final isolateId = isolateRef!.id!; Completer completer = Completer(); var stream = service!.onDebugEvent; late var subscription; subscription = stream.listen((Event event) { if (event.kind == EventKind.kPauseInterrupted) { subscription.cancel(); completer.complete(); } }); await service.streamListen(EventStreams.kDebug); await service.pause(isolateId); await completer.future; await service.streamCancel(EventStreams.kDebug); }, // Resume (VmService service, IsolateRef isolate) async { final isolateId = isolate.id!; Completer completer = Completer(); var stream = service.onDebugEvent; late var subscription; subscription = stream.listen((Event event) { if (event.kind == EventKind.kResume) { subscription.cancel(); completer.complete(); } }); await service.streamListen(EventStreams.kDebug); await service.resume(isolateId); await completer.future; await service.streamCancel(EventStreams.kDebug); }, // Add breakpoint (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; Isolate isolate = await service.getIsolate(isolateId); final Library rootLib = (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library; // Set up a listener to wait for breakpoint events. Completer completer = Completer(); var stream = service.onDebugEvent; late var subscription; subscription = stream.listen((Event event) { if (event.kind == EventKind.kPauseBreakpoint) { print('Breakpoint reached'); subscription.cancel(); completer.complete(); } }); await service.streamListen(EventStreams.kDebug); final Script script = (await service.getObject( isolateId, rootLib.scripts!.first.id!)) as Script; // Add the breakpoint. final Breakpoint bpt = await service.addBreakpoint(isolateId, script.id!, 16); final SourceLocation location = bpt.location; expect(location.script!.id, script.id); expect(script.getLineNumberFromTokenPos(location.tokenPos!), 16); isolate = await service.getIsolate(isolateId); expect(isolate.breakpoints!.length, 1); await completer.future; // Wait for breakpoint events. await service.streamCancel(EventStreams.kDebug); }, // We are at the breakpoint on line 16. (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; final stack = await service.getStack(isolateId); expect(stack.frames!.length, greaterThanOrEqualTo(1)); Script script = (await service.getObject( isolateId, stack.frames![0].location!.script!.id!)) as Script; expect(script.uri, endsWith('debugging_test.dart')); expect( script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!), 16); }, // Stepping (VmService service, IsolateRef isolate) async { // Set up a listener to wait for breakpoint events. final completer = Completer(); var stream = service.onDebugEvent; late var subscription; subscription = stream.listen((Event event) { if (event.kind == EventKind.kPauseBreakpoint) { print('Breakpoint reached'); subscription.cancel(); completer.complete(); } }); print('performing step over'); await stepOver(service, isolate); print('step over done'); await completer.future; // Wait for breakpoint events. print('breakpoint completed'); }, // We are now at line 17. (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; final stack = await service.getStack(isolateId); expect(stack.frames!.length, greaterThanOrEqualTo(1)); final Script script = (await service.getObject( isolateId, stack.frames![0].location!.script!.id!)) as Script; expect(script.uri, endsWith('debugging_test.dart')); expect( script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!), 17); }, // Remove breakpoint (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; // Set up a listener to wait for breakpoint events. final completer = Completer(); var stream = service.onDebugEvent; late var subscription; subscription = stream.listen((Event event) async { if (event.kind == EventKind.kBreakpointRemoved) { print('Breakpoint removed'); final isolate = await service.getIsolate(isolateId); expect(isolate.breakpoints!.length, 0); subscription.cancel(); completer.complete(); } }); final Isolate isolate = await service.getIsolate(isolateId); expect(isolate.breakpoints!.length, 1); final bpt = isolate.breakpoints!.first; await service.streamListen(EventStreams.kDebug); await service.removeBreakpoint(isolateId, bpt.id!); await completer.future; await service.streamCancel(EventStreams.kDebug); }, // Resume (VmService service, IsolateRef isolate) async { final completer = Completer(); var stream = service.onDebugEvent; late var subscription; subscription = stream.listen((Event event) { if (event.kind == EventKind.kResume) { subscription.cancel(); completer.complete(); } }); await resumeIsolate(service, isolate); await completer.future; }, // Add breakpoint at function entry (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; Isolate isolate = await service.getIsolate(isolateId); // Set up a listener to wait for breakpoint events. final completer = Completer(); var stream = service.onDebugEvent; late var subscription; subscription = stream.listen((Event event) { if (event.kind == EventKind.kPauseBreakpoint) { print('Breakpoint reached'); subscription.cancel(); completer.complete(); } }); await service.streamListen(EventStreams.kDebug); final Library rootLib = (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library; // Find a specific function. final FuncRef function = rootLib.functions!.firstWhere((f) => f.name == 'periodicTask'); expect(function, isNotNull); // Add the breakpoint at function entry final bpt = await service.addBreakpointAtEntry(isolateId, function.id!); final Script script = (await service.getObject(isolateId, bpt.location.script.id)) as Script; expect(script.uri, endsWith('debugging_test.dart')); expect(script.getLineNumberFromTokenPos(bpt.location.tokenPos), 14); // Refresh isolate state. isolate = await service.getIsolate(isolateId); expect(isolate.breakpoints!.length, 1); await completer.future; // Wait for breakpoint events. }, // We are now at line 14. (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; final stack = await service.getStack(isolateId); expect(stack.frames!.length, greaterThanOrEqualTo(1)); final Script script = (await service.getObject( isolateId, stack.frames![0].location!.script!.id!)) as Script; expect(script.uri, endsWith('debugging_test.dart')); expect( script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!), 14); }, ]; main([args = const []]) => runIsolateTests( args, tests, 'debugging_test.dart', testeeBefore: startTimer, );