Skip to content

Commit dad91d3

Browse files
committed
Add tests covering the ability to debug dot shorthands
1 parent 7f376d2 commit dad91d3

12 files changed

+332
-4
lines changed

dwds/test/instances/common/class_inspection_common.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ void runTests({
4949
compilationMode: compilationMode,
5050
enableExpressionEvaluation: true,
5151
verboseCompiler: debug,
52+
experiments: ['dot-shorthands'],
5253
canaryFeatures: canaryFeatures,
5354
moduleFormat: provider.ddcModuleFormat,
5455
),
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:path/path.dart' show basename;
6+
import 'package:test/test.dart';
7+
import 'package:test_common/logging.dart';
8+
import 'package:test_common/test_sdk_configuration.dart';
9+
import 'package:vm_service/vm_service.dart';
10+
11+
import '../../fixtures/context.dart';
12+
import '../../fixtures/project.dart';
13+
import '../../fixtures/utilities.dart';
14+
import 'test_inspector.dart';
15+
16+
void runTests({
17+
required TestSdkConfigurationProvider provider,
18+
required CompilationMode compilationMode,
19+
required bool canaryFeatures,
20+
required bool debug,
21+
}) {
22+
final context = TestContext(TestProject.testExperiment, provider);
23+
final testInspector = TestInspector(context);
24+
25+
late VmService service;
26+
late Stream<Event> stream;
27+
late String isolateId;
28+
late ScriptRef mainScript;
29+
30+
Future<void> onBreakPoint(breakPointId, body) => testInspector.onBreakPoint(
31+
stream,
32+
isolateId,
33+
mainScript,
34+
breakPointId,
35+
body,
36+
);
37+
38+
Future<InstanceRef> getInstanceRef(frame, expression) =>
39+
testInspector.getInstanceRef(isolateId, frame, expression);
40+
41+
group('$compilationMode |', () {
42+
setUpAll(() async {
43+
setCurrentLogWriter(debug: debug);
44+
await context.setUp(
45+
testSettings: TestSettings(
46+
compilationMode: compilationMode,
47+
enableExpressionEvaluation: true,
48+
verboseCompiler: debug,
49+
experiments: ['dot-shorthands'],
50+
canaryFeatures: canaryFeatures,
51+
moduleFormat: provider.ddcModuleFormat,
52+
),
53+
);
54+
service = context.debugConnection.vmService;
55+
56+
final vm = await service.getVM();
57+
isolateId = vm.isolates!.first.id!;
58+
final scripts = await service.getScripts(isolateId);
59+
60+
await service.streamListen('Debug');
61+
stream = service.onEvent('Debug');
62+
63+
mainScript = scripts.scripts!.firstWhere(
64+
(each) => each.uri!.contains('main.dart'),
65+
);
66+
});
67+
68+
tearDownAll(() async {
69+
await context.tearDown();
70+
});
71+
72+
setUp(() => setCurrentLogWriter(debug: debug));
73+
tearDown(() => service.resume(isolateId));
74+
75+
test('dot shorthands: expression evaluation', () async {
76+
await onBreakPoint('testDotShorthands', (event) async {
77+
final frame = event.topFrame!.index!;
78+
79+
var instanceRef = await getInstanceRef(frame, '(c = .two).value');
80+
expect(instanceRef.valueAsString, '2');
81+
82+
instanceRef = await getInstanceRef(frame, '(c = .three).value');
83+
expect(instanceRef.valueAsString, '3');
84+
85+
instanceRef = await getInstanceRef(frame, '(c = .four()).value');
86+
expect(instanceRef.valueAsString, '4');
87+
});
88+
});
89+
90+
test('dot shorthands: single-stepping', () async {
91+
await onBreakPoint('testDotShorthands', (event) async {
92+
final scriptBasename = basename(mainScript.uri!);
93+
94+
const lineA = 116;
95+
const lineB = 118;
96+
const lineC = 119;
97+
const lineD = 120;
98+
const lineE = 127;
99+
const lineF = 129;
100+
const lineG = 131;
101+
const lineH = 132;
102+
103+
final expected = [
104+
'$scriptBasename:$lineE:3', // on 'c'
105+
'$scriptBasename:$lineB:20', // on '2'
106+
'$scriptBasename:$lineF:3', // on 'c'
107+
'$scriptBasename:$lineC:25', // on 'C'
108+
'$scriptBasename:$lineA:10', // on 'v' of 'value'
109+
'$scriptBasename:$lineA:16', // on ';'
110+
'$scriptBasename:$lineC:27', // on '3'
111+
'$scriptBasename:$lineG:3', // on 'c'
112+
'$scriptBasename:$lineD:22', // on 'C'
113+
'$scriptBasename:$lineA:10', // on 'v' of 'value'
114+
'$scriptBasename:$lineA:16', // on ';'
115+
'$scriptBasename:$lineD:24', // on '4'
116+
'$scriptBasename:$lineH:3', // on 'p' of 'print'
117+
];
118+
119+
final stops = <String>[];
120+
await testInspector.runStepIntoThroughProgramRecordingStops(
121+
stream,
122+
isolateId,
123+
stops,
124+
13,
125+
);
126+
127+
expect(stops, expected);
128+
});
129+
});
130+
});
131+
}

dwds/test/instances/common/patterns_inspection_common.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void runTests({
5757
compilationMode: compilationMode,
5858
enableExpressionEvaluation: true,
5959
verboseCompiler: debug,
60-
experiments: ['records', 'patterns'],
60+
experiments: ['dot-shorthands'],
6161
canaryFeatures: canaryFeatures,
6262
),
6363
);

dwds/test/instances/common/record_inspection_common.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void runTests({
6363
compilationMode: compilationMode,
6464
enableExpressionEvaluation: true,
6565
verboseCompiler: debug,
66-
experiments: ['records', 'patterns'],
66+
experiments: ['dot-shorthands'],
6767
canaryFeatures: canaryFeatures,
6868
moduleFormat: provider.ddcModuleFormat,
6969
),

dwds/test/instances/common/record_type_inspection_common.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void runTests({
6262
compilationMode: compilationMode,
6363
enableExpressionEvaluation: true,
6464
verboseCompiler: debug,
65-
experiments: ['records', 'patterns'],
65+
experiments: ['dot-shorthands'],
6666
canaryFeatures: canaryFeatures,
6767
moduleFormat: provider.ddcModuleFormat,
6868
),

dwds/test/instances/common/test_inspector.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:async' show Completer, StreamSubscription;
6+
7+
import 'package:path/path.dart' show basename;
58
import 'package:test/test.dart';
69
import 'package:vm_service/vm_service.dart';
710

@@ -214,6 +217,57 @@ class TestInspector {
214217
),
215218
);
216219
}
220+
221+
Future<String> _locationToString(
222+
VmService service,
223+
String isolateId,
224+
SourceLocation location,
225+
) async {
226+
final script =
227+
await service.getObject(isolateId, location.script!.id!) as Script;
228+
final scriptName = basename(script.uri!);
229+
final tokenPos = location.tokenPos!;
230+
final line = script.getLineNumberFromTokenPos(tokenPos);
231+
final column = script.getColumnNumberFromTokenPos(tokenPos);
232+
return '$scriptName:$line:$column';
233+
}
234+
235+
Future<void> runStepIntoThroughProgramRecordingStops(
236+
Stream<Event> debugStream,
237+
String isolateId,
238+
239+
/// A list to which the pause location is added after each single-step.
240+
List<String> recordedStops,
241+
242+
/// A limit on the number of stops to record.
243+
///
244+
/// The program will not be resumed after the length of [recordedStops]
245+
/// becomes [numStops].
246+
int numStops,
247+
) async {
248+
final completer = Completer<void>();
249+
250+
late StreamSubscription subscription;
251+
subscription = debugStream.listen((event) async {
252+
if (event.kind == EventKind.kPauseInterrupted) {
253+
final isolate = await service.getIsolate(isolateId);
254+
final frame = isolate.pauseEvent!.topFrame!;
255+
recordedStops.add(
256+
await _locationToString(service, isolateId, frame.location!),
257+
);
258+
if (recordedStops.length == numStops) {
259+
await subscription.cancel();
260+
completer.complete();
261+
}
262+
await service.resume(isolateId, step: StepOption.kInto);
263+
} else if (event.kind == EventKind.kPauseExit) {
264+
await subscription.cancel();
265+
completer.complete();
266+
}
267+
});
268+
await service.resume(isolateId, step: StepOption.kInto);
269+
await completer.future;
270+
}
217271
}
218272

219273
Map<String, InstanceRef> _associationsToMap(

dwds/test/instances/common/type_inspection_common.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void runTests({
8080
compilationMode: compilationMode,
8181
enableExpressionEvaluation: true,
8282
verboseCompiler: debug,
83-
experiments: ['records', 'patterns'],
83+
experiments: ['dot-shorthands'],
8484
canaryFeatures: canaryFeatures,
8585
),
8686
);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
@Tags(['daily'])
6+
@TestOn('vm')
7+
@Timeout(Duration(minutes: 2))
8+
library;
9+
10+
import 'package:dwds/expression_compiler.dart';
11+
import 'package:test/test.dart';
12+
import 'package:test_common/test_sdk_configuration.dart';
13+
14+
import '../fixtures/context.dart';
15+
import 'common/dot_shorthands_common.dart';
16+
17+
void main() {
18+
// Enable verbose logging for debugging.
19+
final debug = false;
20+
final canaryFeatures = true;
21+
22+
group('canary: $canaryFeatures |', () {
23+
final provider = TestSdkConfigurationProvider(
24+
verbose: debug,
25+
canaryFeatures: canaryFeatures,
26+
ddcModuleFormat: ModuleFormat.amd,
27+
);
28+
tearDownAll(provider.dispose);
29+
30+
for (final compilationMode in CompilationMode.values) {
31+
runTests(
32+
provider: provider,
33+
compilationMode: compilationMode,
34+
canaryFeatures: canaryFeatures,
35+
debug: debug,
36+
);
37+
}
38+
});
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
@Tags(['daily'])
6+
@TestOn('vm')
7+
@Timeout(Duration(minutes: 2))
8+
library;
9+
10+
import 'package:dwds/src/services/expression_compiler.dart';
11+
import 'package:test/test.dart';
12+
import 'package:test_common/test_sdk_configuration.dart';
13+
14+
import '../fixtures/context.dart';
15+
import 'common/dot_shorthands_common.dart';
16+
17+
void main() {
18+
// Enable verbose logging for debugging.
19+
final debug = false;
20+
final canaryFeatures = false;
21+
22+
group('canary: $canaryFeatures |', () {
23+
final provider = TestSdkConfigurationProvider(
24+
verbose: debug,
25+
canaryFeatures: canaryFeatures,
26+
ddcModuleFormat: ModuleFormat.amd,
27+
);
28+
tearDownAll(provider.dispose);
29+
30+
for (final compilationMode in CompilationMode.values) {
31+
runTests(
32+
provider: provider,
33+
compilationMode: compilationMode,
34+
canaryFeatures: canaryFeatures,
35+
debug: debug,
36+
);
37+
}
38+
});
39+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
@Tags(['daily'])
6+
@TestOn('vm')
7+
@Timeout(Duration(minutes: 2))
8+
library;
9+
10+
import 'package:dwds/expression_compiler.dart';
11+
import 'package:test/test.dart';
12+
import 'package:test_common/test_sdk_configuration.dart';
13+
14+
import '../fixtures/context.dart';
15+
import 'common/dot_shorthands_common.dart';
16+
17+
void main() {
18+
// Enable verbose logging for debugging.
19+
final debug = false;
20+
final canaryFeatures = true;
21+
final compilationMode = CompilationMode.frontendServer;
22+
23+
group('canary: $canaryFeatures |', () {
24+
final provider = TestSdkConfigurationProvider(
25+
verbose: debug,
26+
canaryFeatures: canaryFeatures,
27+
ddcModuleFormat: ModuleFormat.ddc,
28+
);
29+
tearDownAll(provider.dispose);
30+
runTests(
31+
provider: provider,
32+
compilationMode: compilationMode,
33+
canaryFeatures: canaryFeatures,
34+
debug: debug,
35+
);
36+
});
37+
}

0 commit comments

Comments
 (0)