blob: 4503adc3b7d44acacf54c5ed8a62741ce42036b4 [file]
// Copyright (c) 2025, 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 'package:path/path.dart' show basename;
import 'package:test/test.dart';
import 'package:test_common/logging.dart';
import 'package:test_common/test_sdk_configuration.dart';
import 'package:vm_service/vm_service.dart';
import '../../fixtures/context.dart';
import '../../fixtures/project.dart';
import '../../fixtures/utilities.dart';
import 'test_inspector.dart';
void runTests({
required TestSdkConfigurationProvider provider,
required CompilationMode compilationMode,
required bool canaryFeatures,
}) {
final context = TestContext(TestProject.testDotShorthands, provider);
final testInspector = TestInspector(context);
late VmService service;
late Stream<Event> stream;
late String isolateId;
late ScriptRef mainScript;
Future<void> onBreakpoint(
String breakPointId,
Future<void> Function(Event) body,
) => testInspector.onBreakPoint(
stream,
isolateId,
mainScript,
breakPointId,
body,
);
Future<InstanceRef> getInstanceRef(frame, expression) =>
testInspector.getInstanceRef(isolateId, frame, expression);
group('$compilationMode | dot shorthands:', () {
setUp(() async {
setCurrentLogWriter(debug: provider.verbose);
await context.setUp(
testSettings: TestSettings(
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: provider.verbose,
experiments: ['dot-shorthands'],
canaryFeatures: canaryFeatures,
moduleFormat: provider.ddcModuleFormat,
),
);
service = context.debugConnection.vmService;
final vm = await service.getVM();
isolateId = vm.isolates!.first.id!;
final scripts = await service.getScripts(isolateId);
await service.streamListen(EventStreams.kDebug);
stream = service.onDebugEvent;
mainScript = scripts.scripts!.firstWhere(
(each) => each.uri!.contains('main.dart'),
);
});
tearDown(() async {
await context.tearDown();
});
test('expression evaluation', () async {
final bp = onBreakpoint('testDotShorthands', (event) async {
final frame = event.topFrame!.index!;
var instanceRef = await getInstanceRef(frame, '(c = .two).value');
expect(instanceRef.valueAsString, '2');
instanceRef = await getInstanceRef(frame, '(c = .three).value');
expect(instanceRef.valueAsString, '3');
instanceRef = await getInstanceRef(frame, '(c = .four()).value');
expect(instanceRef.valueAsString, '4');
await service.resume(isolateId);
});
final isolate = await service.getIsolate(isolateId);
await service.evaluate(
isolateId,
isolate.rootLib!.id!,
'testDotShorthands()',
);
await bp;
});
test('single-stepping', () async {
final bp = onBreakpoint('testDotShorthands', (event) async {
final scriptBasename = basename(mainScript.uri!);
const lineA = 9;
const lineB = 11;
const lineC = 12;
const lineD = 13;
const lineE = 20;
const lineF = 22;
const lineG = 24;
const lineH = 25;
final expected = [
'$scriptBasename:$lineE:3', // on 'c'
'$scriptBasename:$lineB:15', // on 'C'
'$scriptBasename:$lineA:10', // on 'v' of 'value'
'$scriptBasename:$lineA:16', // on ';'
'$scriptBasename:$lineB:20', // on '2'
'$scriptBasename:$lineF:3', // on 'c'
'$scriptBasename:$lineC:25', // on 'C'
'$scriptBasename:$lineA:10', // on 'v' of 'value'
'$scriptBasename:$lineA:16', // on ';'
'$scriptBasename:$lineC:27', // on '3'
'$scriptBasename:$lineG:3', // on 'c'
'$scriptBasename:$lineD:22', // on 'C'
'$scriptBasename:$lineA:10', // on 'v' of 'value'
'$scriptBasename:$lineA:16', // on ';'
'$scriptBasename:$lineD:24', // on '4'
'$scriptBasename:$lineH:3', // on 'p' of 'print'
];
final stops = <String>[];
await testInspector.runStepIntoThroughProgramRecordingStops(
isolateId,
stops,
expected.length,
);
expect(stops, expected);
await service.resume(isolateId);
});
final isolate = await service.getIsolate(isolateId);
await service.evaluate(
isolateId,
isolate.rootLib!.id!,
'testDotShorthands()',
);
await bp;
});
});
}