Skip to content

Commit 3599b3a

Browse files
authored
Add support for expression compilation when debugging integration tests (#113481)
Fixes #79439.
1 parent 5304a24 commit 3599b3a

File tree

6 files changed

+59
-12
lines changed

6 files changed

+59
-12
lines changed

packages/flutter_tools/lib/src/test/flutter_platform.dart

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ class FlutterPlatform extends PlatformPlugin {
418418
debuggingOptions: debuggingOptions,
419419
device: integrationTestDevice!,
420420
userIdentifier: integrationTestUserIdentifier,
421+
compileExpression: _compileExpressionService
421422
);
422423
}
423424
return FlutterTesterTestDevice(
@@ -457,21 +458,22 @@ class FlutterPlatform extends PlatformPlugin {
457458
controllerSinkClosed = true;
458459
}));
459460

461+
// When start paused is specified, it means that the user is likely
462+
// running this with a debugger attached. Initialize the resident
463+
// compiler in this case.
464+
if (debuggingOptions.startPaused) {
465+
compiler ??= TestCompiler(debuggingOptions.buildInfo, flutterProject, precompiledDillPath: precompiledDillPath, testTimeRecorder: testTimeRecorder);
466+
final Uri testUri = globals.fs.file(testPath).uri;
467+
// Trigger a compilation to initialize the resident compiler.
468+
unawaited(compiler!.compile(testUri));
469+
}
470+
460471
// If a kernel file is given, then use that to launch the test.
461472
// If mapping is provided, look kernel file from mapping.
462473
// If all fails, create a "listener" dart that invokes actual test.
463474
String? mainDart;
464475
if (precompiledDillPath != null) {
465476
mainDart = precompiledDillPath;
466-
// When start paused is specified, it means that the user is likely
467-
// running this with a debugger attached. Initialize the resident
468-
// compiler in this case.
469-
if (debuggingOptions.startPaused) {
470-
compiler ??= TestCompiler(debuggingOptions.buildInfo, flutterProject, precompiledDillPath: precompiledDillPath, testTimeRecorder: testTimeRecorder);
471-
final Uri testUri = globals.fs.file(testPath).uri;
472-
// Trigger a compilation to initialize the resident compiler.
473-
unawaited(compiler!.compile(testUri));
474-
}
475477
} else if (precompiledDillFiles != null) {
476478
mainDart = precompiledDillFiles![testPath];
477479
} else {

packages/flutter_tools/lib/src/test/integration_test_device.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ class IntegrationTestTestDevice implements TestDevice {
2424
required this.device,
2525
required this.debuggingOptions,
2626
required this.userIdentifier,
27+
required this.compileExpression,
2728
});
2829

2930
final int id;
3031
final Device device;
3132
final DebuggingOptions debuggingOptions;
3233
final String? userIdentifier;
34+
final CompileExpression? compileExpression;
3335

3436
ApplicationPackage? _applicationPackage;
3537
final Completer<void> _finished = Completer<void>();
@@ -70,7 +72,11 @@ class IntegrationTestTestDevice implements TestDevice {
7072
_gotProcessObservatoryUri.complete(observatoryUri);
7173

7274
globals.printTrace('test $id: Connecting to vm service');
73-
final FlutterVmService vmService = await connectToVmService(observatoryUri, logger: globals.logger).timeout(
75+
final FlutterVmService vmService = await connectToVmService(
76+
observatoryUri,
77+
logger: globals.logger,
78+
compileExpression: compileExpression,
79+
).timeout(
7480
const Duration(seconds: 5),
7581
onTimeout: () => throw TimeoutException('Connecting to the VM Service timed out.'),
7682
);

packages/flutter_tools/test/general.shard/integration_test_device_test.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void main() {
7777
BuildInfo.debug,
7878
),
7979
userIdentifier: '',
80+
compileExpression: null,
8081
);
8182

8283
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
@@ -173,6 +174,7 @@ void main() {
173174
BuildInfo.debug,
174175
),
175176
userIdentifier: '',
177+
compileExpression: null,
176178
);
177179

178180
expect(() => testDevice.start('entrypointPath'), throwsA(isA<TestDeviceException>()));
@@ -201,6 +203,7 @@ void main() {
201203
BuildInfo.debug,
202204
),
203205
userIdentifier: '',
206+
compileExpression: null,
204207
);
205208

206209
expect(() => testDevice.start('entrypointPath'), throwsA(isA<TestDeviceException>()));

packages/flutter_tools/test/integration.shard/expression_evaluation_test.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:vm_service/vm_service.dart';
88

99
import '../src/common.dart';
1010
import 'test_data/basic_project.dart';
11+
import 'test_data/integration_tests_project.dart';
1112
import 'test_data/tests_project.dart';
1213
import 'test_driver.dart';
1314
import 'test_utils.dart';
@@ -141,6 +142,37 @@ void batch2() {
141142
});
142143
}
143144

145+
void batch3() {
146+
final IntegrationTestsProject project = IntegrationTestsProject();
147+
late Directory tempDir;
148+
late FlutterTestTestDriver flutter;
149+
150+
Future<void> initProject() async {
151+
tempDir = createResolvedTempDirectorySync('integration_test_expression_eval_test.');
152+
await project.setUpIn(tempDir);
153+
flutter = FlutterTestTestDriver(tempDir);
154+
}
155+
156+
Future<void> cleanProject() async {
157+
await flutter.waitForCompletion();
158+
tryToDelete(tempDir);
159+
}
160+
161+
testWithoutContext('flutter integration test expression evaluation - can evaluate expressions in a test', () async {
162+
await initProject();
163+
await flutter.test(
164+
deviceId: 'flutter-tester',
165+
testFile: project.testFilePath,
166+
withDebugger: true,
167+
beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
168+
);
169+
await flutter.waitForPause();
170+
await evaluateTrivialExpressions(flutter);
171+
await cleanProject();
172+
});
173+
174+
}
175+
144176
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
145177
ObjRef res;
146178

@@ -189,4 +221,5 @@ void expectValue(ObjRef result, String message) {
189221
void main() {
190222
batch1();
191223
batch2();
224+
batch3();
192225
}

packages/flutter_tools/test/integration.shard/test_data/integration_tests_project.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ class IntegrationTestsProject extends Project implements TestsProject {
5858
String get testFilePath => fileSystem.path.join(dir.path, 'integration_test', 'app_test.dart');
5959

6060
@override
61-
Uri get breakpointUri => throw UnimplementedError();
61+
Uri get breakpointUri => Uri.file(testFilePath);
6262

6363
@override
6464
Uri get breakpointAppUri => throw UnimplementedError();
6565

6666
@override
67-
int get breakpointLine => throw UnimplementedError();
67+
int get breakpointLine => lineContaining(testContent, '// BREAKPOINT');
6868
}

packages/flutter_tools/test/integration.shard/test_driver.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ class FlutterTestTestDriver extends FlutterTestDriver {
763763

764764
Future<void> test({
765765
String testFile = 'test/test.dart',
766+
String? deviceId,
766767
bool withDebugger = false,
767768
bool pauseOnExceptions = false,
768769
bool coverage = false,
@@ -775,6 +776,8 @@ class FlutterTestTestDriver extends FlutterTestDriver {
775776
'--machine',
776777
if (coverage)
777778
'--coverage',
779+
if (deviceId != null)
780+
...<String>['-d', deviceId],
778781
], script: testFile, withDebugger: withDebugger, pauseOnExceptions: pauseOnExceptions, beforeStart: beforeStart);
779782
}
780783

0 commit comments

Comments
 (0)