blob: 7c790e860380393f2fcb24f2cda1606c6ab4d4c0 [file] [log] [blame]
// 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.
@TestOn('vm')
import 'package:dwds/src/connections/debug_connection.dart';
import 'package:dwds/src/services/chrome_proxy_service.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
import 'fixtures/context.dart';
final context = TestContext(
directory: '../example', path: 'scopes.html', pathToServe: 'web');
ChromeProxyService get service =>
fetchChromeProxyService(context.debugConnection);
WipConnection get tabConnection => context.tabConnection;
void main() {
setUpAll(() async {
await context.setUp();
});
tearDownAll(() async {
await context.tearDown();
});
group('variable scope', () {
VM vm;
String isolateId;
Stream<Event> stream;
ScriptList scripts;
ScriptRef mainScript;
Stack stack;
// TODO: Be able to set breakpoints before start/reload so we can exercise
// things that aren't in recurring loops.
/// Support function for pausing and returning the stack at a line.
Future<Stack> breakAt(String breakpointId, ScriptRef scriptRef) async {
var lineNumber =
await context.findBreakpointLine(breakpointId, isolateId, scriptRef);
var bp = await service.addBreakpoint(isolateId, scriptRef.id, lineNumber);
// Wait for breakpoint to trigger.
await stream
.firstWhere((event) => event.kind == EventKind.kPauseBreakpoint);
// Remove breakpoint so it doesn't impact other tests.
await service.removeBreakpoint(isolateId, bp.id);
var stack = await service.getStack(isolateId);
return stack;
}
setUp(() async {
vm = await service.getVM();
isolateId = vm.isolates.first.id;
scripts = await service.getScripts(isolateId);
await service.streamListen('Debug');
stream = service.onEvent('Debug');
mainScript = scripts.scripts
.firstWhere((each) => each.uri.contains('scopes_main.dart'));
});
tearDown(() async {
await service.resume(isolateId);
});
test('variables in static function', () async {
stack = await breakAt('staticFunction', mainScript);
var frame = stack.frames.first;
var variableNames = frame.vars.map((variable) => variable.name).toList()
..sort();
expect(variableNames, containsAll(['formal']));
});
test('variables in function', () async {
stack = await breakAt('nestedFunction', mainScript);
var frame = stack.frames.first;
var variableNames = frame.vars.map((variable) => variable.name).toList()
..sort();
expect(
variableNames,
containsAll([
'aClass',
'another',
'intLocalInMain',
'local',
'localThatsNull',
'nestedFunction',
'parameter',
'testClass'
]));
});
test('variables in closure nested in method', () async {
stack = await breakAt('nestedClosure', mainScript);
var frame = stack.frames.first;
var variableNames = frame.vars.map((variable) => variable.name).toList()
..sort();
expect(variableNames,
['closureLocalInsideMethod', 'local', 'parameter', 'this']);
});
test('variables in method', () async {
stack = await breakAt('printMethod', mainScript);
var frame = stack.frames.first;
var variableNames = frame.vars.map((variable) => variable.name).toList()
..sort();
expect(variableNames, ['this']);
});
test('evaluateJsOnCallFrame', () async {
stack = await breakAt('nestedFunction', mainScript);
var inspector = service.appInspectorProvider();
var debugger = inspector.debugger;
var parameter = await debugger.evaluateJsOnCallFrameIndex(0, 'parameter');
expect(parameter.value, matches(RegExp(r'\d+ world')));
var ticks = await debugger.evaluateJsOnCallFrameIndex(1, 'ticks');
// We don't know how many ticks there were before we stopped, but it should
// be a positive number.
expect(ticks.value, isPositive);
});
});
}