Add support for expression compilation when debugging integration tests (#113481)
Fixes #79439.
This commit is contained in:
parent
5304a24199
commit
3599b3a877
@ -418,6 +418,7 @@ class FlutterPlatform extends PlatformPlugin {
|
|||||||
debuggingOptions: debuggingOptions,
|
debuggingOptions: debuggingOptions,
|
||||||
device: integrationTestDevice!,
|
device: integrationTestDevice!,
|
||||||
userIdentifier: integrationTestUserIdentifier,
|
userIdentifier: integrationTestUserIdentifier,
|
||||||
|
compileExpression: _compileExpressionService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return FlutterTesterTestDevice(
|
return FlutterTesterTestDevice(
|
||||||
@ -457,21 +458,22 @@ class FlutterPlatform extends PlatformPlugin {
|
|||||||
controllerSinkClosed = true;
|
controllerSinkClosed = true;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// When start paused is specified, it means that the user is likely
|
||||||
|
// running this with a debugger attached. Initialize the resident
|
||||||
|
// compiler in this case.
|
||||||
|
if (debuggingOptions.startPaused) {
|
||||||
|
compiler ??= TestCompiler(debuggingOptions.buildInfo, flutterProject, precompiledDillPath: precompiledDillPath, testTimeRecorder: testTimeRecorder);
|
||||||
|
final Uri testUri = globals.fs.file(testPath).uri;
|
||||||
|
// Trigger a compilation to initialize the resident compiler.
|
||||||
|
unawaited(compiler!.compile(testUri));
|
||||||
|
}
|
||||||
|
|
||||||
// If a kernel file is given, then use that to launch the test.
|
// If a kernel file is given, then use that to launch the test.
|
||||||
// If mapping is provided, look kernel file from mapping.
|
// If mapping is provided, look kernel file from mapping.
|
||||||
// If all fails, create a "listener" dart that invokes actual test.
|
// If all fails, create a "listener" dart that invokes actual test.
|
||||||
String? mainDart;
|
String? mainDart;
|
||||||
if (precompiledDillPath != null) {
|
if (precompiledDillPath != null) {
|
||||||
mainDart = precompiledDillPath;
|
mainDart = precompiledDillPath;
|
||||||
// When start paused is specified, it means that the user is likely
|
|
||||||
// running this with a debugger attached. Initialize the resident
|
|
||||||
// compiler in this case.
|
|
||||||
if (debuggingOptions.startPaused) {
|
|
||||||
compiler ??= TestCompiler(debuggingOptions.buildInfo, flutterProject, precompiledDillPath: precompiledDillPath, testTimeRecorder: testTimeRecorder);
|
|
||||||
final Uri testUri = globals.fs.file(testPath).uri;
|
|
||||||
// Trigger a compilation to initialize the resident compiler.
|
|
||||||
unawaited(compiler!.compile(testUri));
|
|
||||||
}
|
|
||||||
} else if (precompiledDillFiles != null) {
|
} else if (precompiledDillFiles != null) {
|
||||||
mainDart = precompiledDillFiles![testPath];
|
mainDart = precompiledDillFiles![testPath];
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,12 +24,14 @@ class IntegrationTestTestDevice implements TestDevice {
|
|||||||
required this.device,
|
required this.device,
|
||||||
required this.debuggingOptions,
|
required this.debuggingOptions,
|
||||||
required this.userIdentifier,
|
required this.userIdentifier,
|
||||||
|
required this.compileExpression,
|
||||||
});
|
});
|
||||||
|
|
||||||
final int id;
|
final int id;
|
||||||
final Device device;
|
final Device device;
|
||||||
final DebuggingOptions debuggingOptions;
|
final DebuggingOptions debuggingOptions;
|
||||||
final String? userIdentifier;
|
final String? userIdentifier;
|
||||||
|
final CompileExpression? compileExpression;
|
||||||
|
|
||||||
ApplicationPackage? _applicationPackage;
|
ApplicationPackage? _applicationPackage;
|
||||||
final Completer<void> _finished = Completer<void>();
|
final Completer<void> _finished = Completer<void>();
|
||||||
@ -70,7 +72,11 @@ class IntegrationTestTestDevice implements TestDevice {
|
|||||||
_gotProcessObservatoryUri.complete(observatoryUri);
|
_gotProcessObservatoryUri.complete(observatoryUri);
|
||||||
|
|
||||||
globals.printTrace('test $id: Connecting to vm service');
|
globals.printTrace('test $id: Connecting to vm service');
|
||||||
final FlutterVmService vmService = await connectToVmService(observatoryUri, logger: globals.logger).timeout(
|
final FlutterVmService vmService = await connectToVmService(
|
||||||
|
observatoryUri,
|
||||||
|
logger: globals.logger,
|
||||||
|
compileExpression: compileExpression,
|
||||||
|
).timeout(
|
||||||
const Duration(seconds: 5),
|
const Duration(seconds: 5),
|
||||||
onTimeout: () => throw TimeoutException('Connecting to the VM Service timed out.'),
|
onTimeout: () => throw TimeoutException('Connecting to the VM Service timed out.'),
|
||||||
);
|
);
|
||||||
|
@ -77,6 +77,7 @@ void main() {
|
|||||||
BuildInfo.debug,
|
BuildInfo.debug,
|
||||||
),
|
),
|
||||||
userIdentifier: '',
|
userIdentifier: '',
|
||||||
|
compileExpression: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||||
@ -173,6 +174,7 @@ void main() {
|
|||||||
BuildInfo.debug,
|
BuildInfo.debug,
|
||||||
),
|
),
|
||||||
userIdentifier: '',
|
userIdentifier: '',
|
||||||
|
compileExpression: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(() => testDevice.start('entrypointPath'), throwsA(isA<TestDeviceException>()));
|
expect(() => testDevice.start('entrypointPath'), throwsA(isA<TestDeviceException>()));
|
||||||
@ -201,6 +203,7 @@ void main() {
|
|||||||
BuildInfo.debug,
|
BuildInfo.debug,
|
||||||
),
|
),
|
||||||
userIdentifier: '',
|
userIdentifier: '',
|
||||||
|
compileExpression: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(() => testDevice.start('entrypointPath'), throwsA(isA<TestDeviceException>()));
|
expect(() => testDevice.start('entrypointPath'), throwsA(isA<TestDeviceException>()));
|
||||||
|
@ -8,6 +8,7 @@ import 'package:vm_service/vm_service.dart';
|
|||||||
|
|
||||||
import '../src/common.dart';
|
import '../src/common.dart';
|
||||||
import 'test_data/basic_project.dart';
|
import 'test_data/basic_project.dart';
|
||||||
|
import 'test_data/integration_tests_project.dart';
|
||||||
import 'test_data/tests_project.dart';
|
import 'test_data/tests_project.dart';
|
||||||
import 'test_driver.dart';
|
import 'test_driver.dart';
|
||||||
import 'test_utils.dart';
|
import 'test_utils.dart';
|
||||||
@ -141,6 +142,37 @@ void batch2() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void batch3() {
|
||||||
|
final IntegrationTestsProject project = IntegrationTestsProject();
|
||||||
|
late Directory tempDir;
|
||||||
|
late FlutterTestTestDriver flutter;
|
||||||
|
|
||||||
|
Future<void> initProject() async {
|
||||||
|
tempDir = createResolvedTempDirectorySync('integration_test_expression_eval_test.');
|
||||||
|
await project.setUpIn(tempDir);
|
||||||
|
flutter = FlutterTestTestDriver(tempDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> cleanProject() async {
|
||||||
|
await flutter.waitForCompletion();
|
||||||
|
tryToDelete(tempDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
testWithoutContext('flutter integration test expression evaluation - can evaluate expressions in a test', () async {
|
||||||
|
await initProject();
|
||||||
|
await flutter.test(
|
||||||
|
deviceId: 'flutter-tester',
|
||||||
|
testFile: project.testFilePath,
|
||||||
|
withDebugger: true,
|
||||||
|
beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
|
||||||
|
);
|
||||||
|
await flutter.waitForPause();
|
||||||
|
await evaluateTrivialExpressions(flutter);
|
||||||
|
await cleanProject();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
|
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
|
||||||
ObjRef res;
|
ObjRef res;
|
||||||
|
|
||||||
@ -189,4 +221,5 @@ void expectValue(ObjRef result, String message) {
|
|||||||
void main() {
|
void main() {
|
||||||
batch1();
|
batch1();
|
||||||
batch2();
|
batch2();
|
||||||
|
batch3();
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,11 @@ class IntegrationTestsProject extends Project implements TestsProject {
|
|||||||
String get testFilePath => fileSystem.path.join(dir.path, 'integration_test', 'app_test.dart');
|
String get testFilePath => fileSystem.path.join(dir.path, 'integration_test', 'app_test.dart');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Uri get breakpointUri => throw UnimplementedError();
|
Uri get breakpointUri => Uri.file(testFilePath);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Uri get breakpointAppUri => throw UnimplementedError();
|
Uri get breakpointAppUri => throw UnimplementedError();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get breakpointLine => throw UnimplementedError();
|
int get breakpointLine => lineContaining(testContent, '// BREAKPOINT');
|
||||||
}
|
}
|
||||||
|
@ -763,6 +763,7 @@ class FlutterTestTestDriver extends FlutterTestDriver {
|
|||||||
|
|
||||||
Future<void> test({
|
Future<void> test({
|
||||||
String testFile = 'test/test.dart',
|
String testFile = 'test/test.dart',
|
||||||
|
String? deviceId,
|
||||||
bool withDebugger = false,
|
bool withDebugger = false,
|
||||||
bool pauseOnExceptions = false,
|
bool pauseOnExceptions = false,
|
||||||
bool coverage = false,
|
bool coverage = false,
|
||||||
@ -775,6 +776,8 @@ class FlutterTestTestDriver extends FlutterTestDriver {
|
|||||||
'--machine',
|
'--machine',
|
||||||
if (coverage)
|
if (coverage)
|
||||||
'--coverage',
|
'--coverage',
|
||||||
|
if (deviceId != null)
|
||||||
|
...<String>['-d', deviceId],
|
||||||
], script: testFile, withDebugger: withDebugger, pauseOnExceptions: pauseOnExceptions, beforeStart: beforeStart);
|
], script: testFile, withDebugger: withDebugger, pauseOnExceptions: pauseOnExceptions, beforeStart: beforeStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user