Unverified Commit d306c37b authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] fix --use-existing-app (#69237)

parent 58a74af8
......@@ -82,6 +82,9 @@ void main() {
});
int result;
result = await drive.exitCode;
await flutter('install', options: <String>[
'--uninstall-only',
]);
if (result != 0)
throw 'Failed to drive test app (exit code $result).';
result = await run.exitCode;
......
......@@ -440,7 +440,6 @@ tasks:
Verifies that `flutter drive --route` still works. No performance numbers.
stage: devicelab
required_agent_capabilities: ["linux/android"]
flaky: true
linux_chrome_dev_mode:
description: >
......
......@@ -186,22 +186,35 @@ class DriveCommand extends RunCommandBase {
? null
: _fileSystem.file(stringArg('use-application-binary'));
await driverService.start(
buildInfo,
device,
debuggingOptions,
ipv6,
applicationBinary: applicationBinary,
route: route,
userIdentifier: userIdentifier,
mainPath: targetFile,
platformArgs: <String, Object>{
if (traceStartup)
'trace-startup': traceStartup,
if (web)
'--no-launch-chrome': true,
if (stringArg('use-existing-app') == null) {
await driverService.start(
buildInfo,
device,
debuggingOptions,
ipv6,
applicationBinary: applicationBinary,
route: route,
userIdentifier: userIdentifier,
mainPath: targetFile,
platformArgs: <String, Object>{
if (traceStartup)
'trace-startup': traceStartup,
if (web)
'--no-launch-chrome': true,
}
);
} else {
final Uri uri = Uri.tryParse(stringArg('use-existing-app'));
if (uri == null) {
throwToolExit('Invalid VM Service URI: ${stringArg('use-existing-app')}');
}
);
await driverService.reuseApplication(
uri,
device,
debuggingOptions,
ipv6,
);
}
final int testResult = await driverService.startTest(
testFile,
......
......@@ -64,6 +64,14 @@ abstract class DriverService {
Map<String, Object> platformArgs = const <String, Object>{},
});
/// If --use-existing-app is provided, configured the correct VM Service URI.
Future<void> reuseApplication(
Uri vmServiceUri,
Device device,
DebuggingOptions debuggingOptions,
bool ipv6,
);
/// Start the test file with the provided [arguments] and [environment], returning
/// the test process exit code.
Future<int> startTest(
......@@ -168,10 +176,26 @@ class FlutterDriverService extends DriverService {
if (result == null || !result.started) {
throwToolExit('Application failed to start. Will not run test. Quitting.', exitCode: 1);
}
_vmServiceUri = result.observatoryUri.toString();
return reuseApplication(
result.observatoryUri,
device,
debuggingOptions,
ipv6,
);
}
@override
Future<void> reuseApplication(
Uri vmServiceUri,
Device device,
DebuggingOptions debuggingOptions,
bool ipv6,
) async {
_vmServiceUri = vmServiceUri.toString();
_device = device;
try {
await device.dds.startDartDevelopmentService(
result.observatoryUri,
vmServiceUri,
debuggingOptions.ddsPort,
ipv6,
debuggingOptions.disableServiceAuthCodes,
......@@ -228,20 +252,24 @@ class FlutterDriverService extends DriverService {
);
await sharedSkSlWriter(_device, result, outputFile: writeSkslOnExit, logger: _logger);
}
try {
// If the application package is available, stop and uninstall.
if (_applicationPackage != null) {
if (!await _device.stopApp(_applicationPackage, userIdentifier: userIdentifier)) {
_logger.printError('Failed to stop app');
}
} on Exception catch (err) {
_logger.printError('Failed to stop app due to unhandled error: $err');
}
try {
if (!await _device.uninstallApp(_applicationPackage, userIdentifier: userIdentifier)) {
_logger.printError('Failed to uninstall app');
_logger.printError('Failed to uninstall app');
}
} on Exception catch (err) {
_logger.printError('Failed to uninstall app due to unhandled error: $err');
} else if (_device.supportsFlutterExit) {
// Otherwise use the VM Service URI to stop the app as a best effort approach.
final vm_service.VM vm = await _vmService.getVM();
final vm_service.IsolateRef isolateRef = vm.isolates
.firstWhere((vm_service.IsolateRef element) {
return !element.isSystemIsolate;
}, orElse: () => null);
unawaited(_vmService.flutterExit(isolateId: isolateRef.id));
} else {
_logger.printTrace('No application package for $_device, leaving app running');
}
await _device.dispose();
}
......
......@@ -153,6 +153,11 @@ class WebDriverService extends DriverService {
'ANDROID_CHROME_ON_EMULATOR': (_browserNameToEnum(browserName) == Browser.androidChrome && androidEmulator).toString(),
};
}
@override
Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async {
throwToolExit('--use-existing-app is not supported with flutter web driver');
}
}
/// A list of supported browsers.
......
......@@ -255,6 +255,47 @@ void main() {
'data': <String, Object>{'A': 'B'}
});
});
testWithoutContext('Can connect to existing application and stop it during cleanup', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <FakeVmServiceRequest>[
getVM,
getVM,
const FakeVmServiceRequest(
method: 'ext.flutter.exit',
args: <String, Object>{
'isolateId': '1',
}
)
]);
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[]);
final DriverService driverService = setUpDriverService(processManager: processManager, vmService: fakeVmServiceHost.vmService);
final FakeDevice device = FakeDevice(LaunchResult.failed());
await driverService.reuseApplication(
Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'),
device,
DebuggingOptions.enabled(BuildInfo.debug),
false,
);
await driverService.stop();
});
testWithoutContext('Does not call flutterExit on device types that do not support it', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <FakeVmServiceRequest>[
getVM,
]);
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[]);
final DriverService driverService = setUpDriverService(processManager: processManager, vmService: fakeVmServiceHost.vmService);
final FakeDevice device = FakeDevice(LaunchResult.failed(), supportsFlutterExit: false);
await driverService.reuseApplication(
Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'),
device,
DebuggingOptions.enabled(BuildInfo.debug),
false,
);
await driverService.stop();
});
}
FlutterDriverService setUpDriverService({
......@@ -301,7 +342,7 @@ class FakeApplicationPackageFactory extends Fake implements ApplicationPackageFa
class FakeApplicationPackage extends Fake implements ApplicationPackage {}
class FakeDevice extends Fake implements Device {
FakeDevice(this.result);
FakeDevice(this.result, {this.supportsFlutterExit = true});
LaunchResult result;
bool didStopApp = false;
......@@ -312,6 +353,9 @@ class FakeDevice extends Fake implements Device {
@override
String get name => 'test';
@override
final bool supportsFlutterExit;
@override
final DartDevelopmentService dds = FakeDartDevelopmentService();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment