Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dwds/test/instances/common/class_inspection_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void runTests({
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: debug,
experiments: ['dot-shorthands'],
canaryFeatures: canaryFeatures,
moduleFormat: provider.ddcModuleFormat,
),
Expand Down
134 changes: 134 additions & 0 deletions dwds/test/instances/common/dot_shorthands_common.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// 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:dwds/src/services/expression_compiler.dart' show ModuleFormat;
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,
required bool debug,
}) {
final context = TestContext(TestProject.testExperiment, provider);
final testInspector = TestInspector(context);

late VmService service;
late Stream<Event> stream;
late String isolateId;
late ScriptRef mainScript;

Future<void> onBreakPoint(breakPointId, body) => testInspector.onBreakPoint(
stream,
isolateId,
mainScript,
breakPointId,
body,
);

Future<InstanceRef> getInstanceRef(frame, expression) =>
testInspector.getInstanceRef(isolateId, frame, expression);

group('$compilationMode |', () {
setUpAll(() async {
setCurrentLogWriter(debug: debug);
await context.setUp(
testSettings: TestSettings(
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: debug,
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('Debug');
stream = service.onEvent('Debug');

mainScript = scripts.scripts!.firstWhere(
(each) => each.uri!.contains('main.dart'),
);
});

tearDownAll(() async {
await context.tearDown();
});

setUp(() => setCurrentLogWriter(debug: debug));
tearDown(() => service.resume(isolateId));

test('dot shorthands: expression evaluation', () async {
await 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');
});
});

test('dot shorthands: single-stepping', () async {
await onBreakPoint('testDotShorthands', (event) async {
final scriptBasename = basename(mainScript.uri!);

const lineA = 116;
const lineB = 118;
const lineC = 119;
const lineD = 120;
const lineE = 127;
const lineF = 129;
const lineG = 131;
const lineH = 132;

final expected = [
'$scriptBasename:$lineE:3', // on 'c'
// TODO(2638): Investigate why this conditional exclusion is needed.
if (provider.ddcModuleFormat == ModuleFormat.ddc)
'$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(
stream,
isolateId,
stops,
provider.ddcModuleFormat == ModuleFormat.ddc ? 13 : 12,
);

expect(stops, expected);
});
});
});
}
2 changes: 1 addition & 1 deletion dwds/test/instances/common/patterns_inspection_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void runTests({
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: debug,
experiments: ['records', 'patterns'],
experiments: ['dot-shorthands'],
canaryFeatures: canaryFeatures,
),
);
Expand Down
2 changes: 1 addition & 1 deletion dwds/test/instances/common/record_inspection_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void runTests({
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: debug,
experiments: ['records', 'patterns'],
experiments: ['dot-shorthands'],
canaryFeatures: canaryFeatures,
moduleFormat: provider.ddcModuleFormat,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void runTests({
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: debug,
experiments: ['records', 'patterns'],
experiments: ['dot-shorthands'],
canaryFeatures: canaryFeatures,
moduleFormat: provider.ddcModuleFormat,
),
Expand Down
54 changes: 54 additions & 0 deletions dwds/test/instances/common/test_inspector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// 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' show Completer, StreamSubscription;

import 'package:path/path.dart' show basename;
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';

Expand Down Expand Up @@ -214,6 +217,57 @@ class TestInspector {
),
);
}

Future<String> _locationToString(
VmService service,
String isolateId,
SourceLocation location,
) async {
final script =
await service.getObject(isolateId, location.script!.id!) as Script;
final scriptName = basename(script.uri!);
final tokenPos = location.tokenPos!;
final line = script.getLineNumberFromTokenPos(tokenPos);
final column = script.getColumnNumberFromTokenPos(tokenPos);
return '$scriptName:$line:$column';
}

Future<void> runStepIntoThroughProgramRecordingStops(
Stream<Event> debugStream,
String isolateId,

/// A list to which the pause location is added after each single-step.
List<String> recordedStops,

/// A limit on the number of stops to record.
///
/// The program will not be resumed after the length of [recordedStops]
/// becomes [numStops].
int numStops,
) async {
final completer = Completer<void>();

late StreamSubscription subscription;
subscription = debugStream.listen((event) async {
if (event.kind == EventKind.kPauseInterrupted) {
final isolate = await service.getIsolate(isolateId);
final frame = isolate.pauseEvent!.topFrame!;
recordedStops.add(
await _locationToString(service, isolateId, frame.location!),
);
if (recordedStops.length == numStops) {
await subscription.cancel();
completer.complete();
}
await service.resume(isolateId, step: StepOption.kInto);
} else if (event.kind == EventKind.kPauseExit) {
await subscription.cancel();
completer.complete();
}
});
await service.resume(isolateId, step: StepOption.kInto);
await completer.future;
}
}

Map<String, InstanceRef> _associationsToMap(
Expand Down
2 changes: 1 addition & 1 deletion dwds/test/instances/common/type_inspection_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void runTests({
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: debug,
experiments: ['records', 'patterns'],
experiments: ['dot-shorthands'],
canaryFeatures: canaryFeatures,
),
);
Expand Down
39 changes: 39 additions & 0 deletions dwds/test/instances/dot_shorthands_amd_canary_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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.

@Tags(['daily'])
@TestOn('vm')
@Timeout(Duration(minutes: 2))
library;

import 'package:dwds/expression_compiler.dart';
import 'package:test/test.dart';
import 'package:test_common/test_sdk_configuration.dart';

import '../fixtures/context.dart';
import 'common/dot_shorthands_common.dart';

void main() {
// Enable verbose logging for debugging.
final debug = false;
final canaryFeatures = true;

group('canary: $canaryFeatures |', () {
final provider = TestSdkConfigurationProvider(
verbose: debug,
canaryFeatures: canaryFeatures,
ddcModuleFormat: ModuleFormat.amd,
);
tearDownAll(provider.dispose);

for (final compilationMode in CompilationMode.values) {
runTests(
provider: provider,
compilationMode: compilationMode,
canaryFeatures: canaryFeatures,
debug: debug,
);
}
});
}
39 changes: 39 additions & 0 deletions dwds/test/instances/dot_shorthands_amd_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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.

@Tags(['daily'])
@TestOn('vm')
@Timeout(Duration(minutes: 2))
library;

import 'package:dwds/src/services/expression_compiler.dart';
import 'package:test/test.dart';
import 'package:test_common/test_sdk_configuration.dart';

import '../fixtures/context.dart';
import 'common/dot_shorthands_common.dart';

void main() {
// Enable verbose logging for debugging.
final debug = false;
final canaryFeatures = false;

group('canary: $canaryFeatures |', () {
final provider = TestSdkConfigurationProvider(
verbose: debug,
canaryFeatures: canaryFeatures,
ddcModuleFormat: ModuleFormat.amd,
);
tearDownAll(provider.dispose);

for (final compilationMode in CompilationMode.values) {
runTests(
provider: provider,
compilationMode: compilationMode,
canaryFeatures: canaryFeatures,
debug: debug,
);
}
});
}
37 changes: 37 additions & 0 deletions dwds/test/instances/dot_shorthands_ddc_library_bundle_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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.

@Tags(['daily'])
@TestOn('vm')
@Timeout(Duration(minutes: 2))
library;

import 'package:dwds/expression_compiler.dart';
import 'package:test/test.dart';
import 'package:test_common/test_sdk_configuration.dart';

import '../fixtures/context.dart';
import 'common/dot_shorthands_common.dart';

void main() {
// Enable verbose logging for debugging.
final debug = false;
final canaryFeatures = true;
final compilationMode = CompilationMode.frontendServer;

group('canary: $canaryFeatures |', () {
final provider = TestSdkConfigurationProvider(
verbose: debug,
canaryFeatures: canaryFeatures,
ddcModuleFormat: ModuleFormat.ddc,
);
tearDownAll(provider.dispose);
runTests(
provider: provider,
compilationMode: compilationMode,
canaryFeatures: canaryFeatures,
debug: debug,
);
});
}
Loading