Skip to content

Commit 26fdfab

Browse files
committed
[VM/Service] Use the resident frontend server for expression evaluation when it's available
TEST=tests added to pkg/vm_service/test CoreLibraryReviewExempt: This CL does not include any core library API changes, only VM Service implementation changes within sdk/lib/vmservice/. Change-Id: I191bb7f3ec3abf1f42405a43ce72016796bc43f9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/394523 Reviewed-by: Ben Konyi <[email protected]>
1 parent 9a6f6c5 commit 26fdfab

23 files changed

+694
-380
lines changed

pkg/dartdev/test/commands/run_test.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,20 @@ void residentRun() {
10181018
});
10191019
});
10201020

1021+
test('running dartdev is a prerequisite for passing --resident', () async {
1022+
p = project(mainSrc: 'void main() {}');
1023+
final result = await p.run(['--resident', p.relativeFilePath]);
1024+
1025+
expect(result.exitCode, 255);
1026+
expect(
1027+
result.stderr,
1028+
contains(
1029+
'Passing the `--resident` flag to `dart` is invalid. It must be passed '
1030+
'to `dart run`.',
1031+
),
1032+
);
1033+
});
1034+
10211035
test(
10221036
'passing --resident is a prerequisite for passing --resident-compiler-info-file',
10231037
() async {

pkg/vm_service/test/common/test_helper.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class _ServiceTesteeLauncher {
115115
bool pauseOnUnhandledExceptions,
116116
bool testeeControlsServer,
117117
bool useAuthToken,
118+
bool shouldTesteeBeLaunchedWithDartRunResident,
118119
List<String>? experiments,
119120
List<String>? extraArgs,
120121
) {
@@ -124,6 +125,7 @@ class _ServiceTesteeLauncher {
124125
pauseOnUnhandledExceptions,
125126
testeeControlsServer,
126127
useAuthToken,
128+
shouldTesteeBeLaunchedWithDartRunResident,
127129
experiments,
128130
extraArgs,
129131
);
@@ -135,6 +137,7 @@ class _ServiceTesteeLauncher {
135137
bool pauseOnUnhandledExceptions,
136138
bool testeeControlsServer,
137139
bool useAuthToken,
140+
bool shouldTesteeBeLaunchedWithDartRunResident,
138141
List<String>? experiments,
139142
List<String>? extraArgs,
140143
) {
@@ -165,7 +168,12 @@ class _ServiceTesteeLauncher {
165168
if (!testeeControlsServer) {
166169
fullArgs.add('--enable-vm-service:0');
167170
}
171+
172+
if (shouldTesteeBeLaunchedWithDartRunResident) {
173+
fullArgs.addAll(['run', '--resident']);
174+
}
168175
fullArgs.addAll(args);
176+
169177
return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
170178
}
171179

@@ -194,6 +202,7 @@ class _ServiceTesteeLauncher {
194202
bool pauseOnUnhandledExceptions,
195203
bool testeeControlsServer,
196204
bool useAuthToken,
205+
bool shouldTesteeBeLaunchedWithDartRunResident,
197206
List<String>? experiments,
198207
List<String>? extraArgs,
199208
) {
@@ -203,6 +212,7 @@ class _ServiceTesteeLauncher {
203212
pauseOnUnhandledExceptions,
204213
testeeControlsServer,
205214
useAuthToken,
215+
shouldTesteeBeLaunchedWithDartRunResident,
206216
experiments,
207217
extraArgs,
208218
).then((p) {
@@ -272,6 +282,7 @@ class _ServiceTesterRunner {
272282
bool pauseOnUnhandledExceptions = false,
273283
bool testeeControlsServer = false,
274284
bool useAuthToken = false,
285+
bool shouldTesteeBeLaunchedWithDartRunResident = false,
275286
bool allowForNonZeroExitCode = false,
276287
VmServiceFactory serviceFactory = VmService.defaultFactory,
277288
}) async {
@@ -286,6 +297,7 @@ class _ServiceTesterRunner {
286297
pauseOnUnhandledExceptions,
287298
testeeControlsServer,
288299
useAuthToken,
300+
shouldTesteeBeLaunchedWithDartRunResident,
289301
experiments,
290302
extraArgs,
291303
)
@@ -410,6 +422,9 @@ Future<void> runIsolateTests(
410422
bool pauseOnUnhandledExceptions = false,
411423
bool testeeControlsServer = false,
412424
bool useAuthToken = false,
425+
426+
/// If [true], `dart run --resident` will be used to launch the testee.
427+
bool shouldTesteeBeLaunchedWithDartRunResident = false,
413428
bool allowForNonZeroExitCode = false,
414429
List<String>? experiments,
415430
List<String>? extraArgs,
@@ -435,6 +450,8 @@ Future<void> runIsolateTests(
435450
pauseOnUnhandledExceptions: pauseOnUnhandledExceptions,
436451
testeeControlsServer: testeeControlsServer,
437452
useAuthToken: useAuthToken,
453+
shouldTesteeBeLaunchedWithDartRunResident:
454+
shouldTesteeBeLaunchedWithDartRunResident,
438455
allowForNonZeroExitCode: allowForNonZeroExitCode,
439456
);
440457
}

pkg/vm_service/test/eval_test.dart

Lines changed: 3 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2,118 +2,12 @@
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:developer';
6-
import 'package:test/test.dart';
7-
import 'package:vm_service/vm_service.dart';
8-
import 'common/service_test_common.dart';
95
import 'common/test_helper.dart';
10-
11-
int globalVar = 100;
12-
13-
class MyClass {
14-
static int staticVar = 1000;
15-
16-
static void method(int value) {
17-
debugger();
18-
}
19-
}
20-
21-
class _MyClass {
22-
void foo() {
23-
debugger();
24-
}
25-
}
26-
27-
void testFunction() {
28-
int i = 0;
29-
while (true) {
30-
if (++i % 100000000 == 0) {
31-
MyClass.method(10000);
32-
_MyClass().foo();
33-
}
34-
}
35-
}
36-
37-
final tests = <IsolateTest>[
38-
hasStoppedAtBreakpoint,
39-
40-
// Evaluate against library, class, and instance.
41-
(VmService service, IsolateRef isolateRef) async {
42-
final isolateId = isolateRef.id!;
43-
final isolate = await service.getIsolate(isolateId);
44-
final stack = await service.getStack(isolateId);
45-
46-
// Make sure we are in the right place.
47-
expect(stack.frames!.length, greaterThanOrEqualTo(2));
48-
expect(stack.frames![0].function!.name, 'method');
49-
expect((stack.frames![0].function!.owner as ClassRef).name, 'MyClass');
50-
51-
final LibraryRef lib = isolate.rootLib!;
52-
final ClassRef cls = stack.frames![0].function!.owner;
53-
final InstanceRef instance = stack.frames![0].vars![0].value;
54-
55-
dynamic result =
56-
await service.evaluate(isolateId, lib.id!, 'globalVar + 5');
57-
print(result);
58-
expect(result.valueAsString, '105');
59-
60-
await expectError(
61-
() => service.evaluate(isolateId, lib.id!, 'globalVar + staticVar + 5'),
62-
);
63-
64-
result =
65-
await service.evaluate(isolateId, cls.id!, 'globalVar + staticVar + 5');
66-
print(result);
67-
expect(result.valueAsString, '1105');
68-
69-
await expectError(() => service.evaluate(isolateId, cls.id!, 'this + 5'));
70-
71-
result = await service.evaluate(isolateId, instance.id!, 'this + 5');
72-
print(result);
73-
expect(result.valueAsString, '10005');
74-
75-
await expectError(
76-
() => service.evaluate(isolateId, instance.id!, 'this + frog'),
77-
);
78-
},
79-
resumeIsolate,
80-
hasStoppedAtBreakpoint,
81-
(VmService service, IsolateRef isolate) async {
82-
final isolateId = isolate.id!;
83-
final stack = await service.getStack(isolateId);
84-
85-
// Make sure we are in the right place.
86-
expect(stack.frames!.length, greaterThanOrEqualTo(2));
87-
expect(stack.frames![0].function!.name, 'foo');
88-
expect((stack.frames![0].function!.owner as ClassRef).name, '_MyClass');
89-
90-
final ClassRef cls = stack.frames![0].function!.owner;
91-
92-
final InstanceRef result =
93-
await service.evaluate(isolateId, cls.id!, '1+1') as InstanceRef;
94-
print(result);
95-
expect(result.valueAsString, '2');
96-
}
97-
];
98-
99-
Future<void> expectError(func) async {
100-
bool gotException = false;
101-
dynamic result;
102-
try {
103-
result = await func();
104-
fail('Failed to throw');
105-
} on RPCError catch (e) {
106-
expect(e.code, 113); // Compile time error.
107-
gotException = true;
108-
}
109-
if (result?.type != 'Error') {
110-
expect(gotException, true); // dart2 semantics
111-
}
112-
}
6+
import 'eval_test_common.dart';
1137

1148
void main([args = const <String>[]]) => runIsolateTests(
1159
args,
116-
tests,
10+
evalTests,
11711
'eval_test.dart',
118-
testeeConcurrent: testFunction,
12+
testeeConcurrent: testeeMain,
11913
);
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright (c) 2024, 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 'dart:developer';
6+
import 'package:test/test.dart';
7+
import 'package:vm_service/vm_service.dart';
8+
import 'common/service_test_common.dart';
9+
10+
int globalVar = 100;
11+
12+
class MyClass {
13+
static int staticVar = 1000;
14+
15+
static void method(int value) {
16+
debugger();
17+
}
18+
}
19+
20+
class _MyClass {
21+
void foo() {
22+
debugger();
23+
}
24+
}
25+
26+
void testeeMain() {
27+
int i = 0;
28+
while (true) {
29+
if (++i % 100000000 == 0) {
30+
MyClass.method(10000);
31+
_MyClass().foo();
32+
}
33+
}
34+
}
35+
36+
final evalTests = <IsolateTest>[
37+
hasStoppedAtBreakpoint,
38+
39+
// Evaluate against library, class, and instance.
40+
(VmService service, IsolateRef isolateRef) async {
41+
final isolateId = isolateRef.id!;
42+
final isolate = await service.getIsolate(isolateId);
43+
final stack = await service.getStack(isolateId);
44+
45+
// Make sure we are in the right place.
46+
expect(stack.frames!.length, greaterThanOrEqualTo(2));
47+
expect(stack.frames![0].function!.name, 'method');
48+
expect((stack.frames![0].function!.owner as ClassRef).name, 'MyClass');
49+
50+
final LibraryRef lib = isolate.rootLib!;
51+
final ClassRef cls = stack.frames![0].function!.owner;
52+
final InstanceRef instance = stack.frames![0].vars![0].value;
53+
54+
dynamic result =
55+
await service.evaluate(isolateId, lib.id!, 'globalVar + 5');
56+
print(result);
57+
expect(result.valueAsString, '105');
58+
59+
await expectError(
60+
() => service.evaluate(isolateId, lib.id!, 'globalVar + staticVar + 5'),
61+
);
62+
63+
result =
64+
await service.evaluate(isolateId, cls.id!, 'globalVar + staticVar + 5');
65+
print(result);
66+
expect(result.valueAsString, '1105');
67+
68+
await expectError(() => service.evaluate(isolateId, cls.id!, 'this + 5'));
69+
70+
result = await service.evaluate(isolateId, instance.id!, 'this + 5');
71+
print(result);
72+
expect(result.valueAsString, '10005');
73+
74+
await expectError(
75+
() => service.evaluate(isolateId, instance.id!, 'this + frog'),
76+
);
77+
},
78+
resumeIsolate,
79+
hasStoppedAtBreakpoint,
80+
(VmService service, IsolateRef isolate) async {
81+
final isolateId = isolate.id!;
82+
final stack = await service.getStack(isolateId);
83+
84+
// Make sure we are in the right place.
85+
expect(stack.frames!.length, greaterThanOrEqualTo(2));
86+
expect(stack.frames![0].function!.name, 'foo');
87+
expect((stack.frames![0].function!.owner as ClassRef).name, '_MyClass');
88+
89+
final ClassRef cls = stack.frames![0].function!.owner;
90+
91+
final InstanceRef result =
92+
await service.evaluate(isolateId, cls.id!, '1+1') as InstanceRef;
93+
print(result);
94+
expect(result.valueAsString, '2');
95+
}
96+
];
97+
98+
Future<void> expectError(Future<Response> Function() func) async {
99+
try {
100+
await func();
101+
fail('Failed to throw');
102+
} on RPCError catch (e) {
103+
expect(e.code, 113); // Compile time error.
104+
}
105+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) 2024, 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 'common/test_helper.dart';
6+
import 'eval_test_common.dart';
7+
8+
void main([args = const <String>[]]) => runIsolateTests(
9+
args,
10+
evalTests,
11+
'eval_with_resident_compiler_test.dart',
12+
testeeConcurrent: testeeMain,
13+
shouldTesteeBeLaunchedWithDartRunResident: true,
14+
);

0 commit comments

Comments
 (0)