Add --device-timeout flag to device-related commands (#64834)
This commit is contained in:
parent
608f0606af
commit
6175183545
@ -102,6 +102,7 @@ class AttachCommand extends FlutterCommand {
|
||||
);
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
addDdsOptions(verboseHelp: verboseHelp);
|
||||
usesDeviceTimeoutOption();
|
||||
hotRunnerFactory ??= HotRunnerFactory();
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,9 @@ class DevicesCommand extends FlutterCommand {
|
||||
'timeout',
|
||||
abbr: 't',
|
||||
defaultsTo: null,
|
||||
help: 'Time in seconds to wait for devices to attach. Longer timeouts may be necessary for networked devices.'
|
||||
help: '(deprecated) Use --device-timeout instead',
|
||||
);
|
||||
usesDeviceTimeoutOption();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -32,20 +33,25 @@ class DevicesCommand extends FlutterCommand {
|
||||
@override
|
||||
final String description = 'List all connected devices.';
|
||||
|
||||
Duration get timeout {
|
||||
if (argResults['timeout'] == null) {
|
||||
return null;
|
||||
}
|
||||
if (_timeout == null) {
|
||||
@override
|
||||
Duration get deviceDiscoveryTimeout {
|
||||
if (argResults['timeout'] != null) {
|
||||
final int timeoutSeconds = int.tryParse(stringArg('timeout'));
|
||||
if (timeoutSeconds == null) {
|
||||
throwToolExit( 'Could not parse -t/--timeout argument. It must be an integer.');
|
||||
}
|
||||
_timeout = Duration(seconds: timeoutSeconds);
|
||||
return Duration(seconds: timeoutSeconds);
|
||||
}
|
||||
return _timeout;
|
||||
return super.deviceDiscoveryTimeout;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> validateCommand() {
|
||||
if (argResults['timeout'] != null) {
|
||||
globals.printError('--timeout has been deprecated, use --${FlutterOptions.kDeviceTimeout} instead');
|
||||
}
|
||||
return super.validateCommand();
|
||||
}
|
||||
Duration _timeout;
|
||||
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
@ -56,7 +62,7 @@ class DevicesCommand extends FlutterCommand {
|
||||
exitCode: 1);
|
||||
}
|
||||
|
||||
final List<Device> devices = await globals.deviceManager.refreshAllConnectedDevices(timeout: timeout);
|
||||
final List<Device> devices = await globals.deviceManager.refreshAllConnectedDevices(timeout: deviceDiscoveryTimeout);
|
||||
|
||||
if (boolArg('machine')) {
|
||||
await printDevicesAsJson(devices);
|
||||
@ -68,8 +74,8 @@ class DevicesCommand extends FlutterCommand {
|
||||
status.writeln('Run "flutter emulators" to list and start any available device emulators.');
|
||||
status.writeln();
|
||||
status.write('If you expected your device to be detected, please run "flutter doctor" to diagnose potential issues. ');
|
||||
if (timeout == null) {
|
||||
status.write('You may also try increasing the time to wait for connected devices with the --timeout flag. ');
|
||||
if (deviceDiscoveryTimeout == null) {
|
||||
status.write('You may also try increasing the time to wait for connected devices with the --${FlutterOptions.kDeviceTimeout} flag. ');
|
||||
}
|
||||
status.write('Visit https://flutter.dev/setup/ for troubleshooting tips.');
|
||||
|
||||
|
@ -146,7 +146,7 @@ class DriveCommand extends RunCommandBase {
|
||||
@override
|
||||
Future<void> validateCommand() async {
|
||||
if (userIdentifier != null) {
|
||||
final Device device = await findTargetDevice();
|
||||
final Device device = await findTargetDevice(timeout: deviceDiscoveryTimeout);
|
||||
if (device is! AndroidDevice) {
|
||||
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
|
||||
}
|
||||
@ -161,7 +161,7 @@ class DriveCommand extends RunCommandBase {
|
||||
throwToolExit(null);
|
||||
}
|
||||
|
||||
_device = await findTargetDevice();
|
||||
_device = await findTargetDevice(timeout: deviceDiscoveryTimeout);
|
||||
if (device == null) {
|
||||
throwToolExit(null);
|
||||
}
|
||||
@ -388,9 +388,9 @@ $ex
|
||||
}
|
||||
}
|
||||
|
||||
Future<Device> findTargetDevice() async {
|
||||
Future<Device> findTargetDevice({ @required Duration timeout }) async {
|
||||
final DeviceManager deviceManager = globals.deviceManager;
|
||||
final List<Device> devices = await deviceManager.findTargetDevices(FlutterProject.current());
|
||||
final List<Device> devices = await deviceManager.findTargetDevices(FlutterProject.current(), timeout: timeout);
|
||||
|
||||
if (deviceManager.hasSpecifiedDeviceId) {
|
||||
if (devices.isEmpty) {
|
||||
|
@ -16,6 +16,7 @@ class InstallCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts
|
||||
InstallCommand() {
|
||||
requiresPubspecYaml();
|
||||
usesDeviceUserOption();
|
||||
usesDeviceTimeoutOption();
|
||||
argParser.addFlag('uninstall-only',
|
||||
negatable: true,
|
||||
defaultsTo: false,
|
||||
|
@ -18,6 +18,7 @@ class LogsCommand extends FlutterCommand {
|
||||
abbr: 'c',
|
||||
help: 'Clear log history before reading from logs.',
|
||||
);
|
||||
usesDeviceTimeoutOption();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -75,6 +75,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
addNullSafetyModeOptions(hide: !verboseHelp);
|
||||
usesDeviceUserOption();
|
||||
usesDeviceTimeoutOption();
|
||||
}
|
||||
|
||||
bool get traceStartup => boolArg('trace-startup');
|
||||
|
@ -51,6 +51,7 @@ class ScreenshotCommand extends FlutterCommand {
|
||||
},
|
||||
defaultsTo: _kDeviceType,
|
||||
);
|
||||
usesDeviceTimeoutOption();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -209,7 +209,12 @@ abstract class DeviceManager {
|
||||
/// * If the user did not specify a device id and there is more than one
|
||||
/// device connected, then filter out unsupported devices and prioritize
|
||||
/// ephemeral devices.
|
||||
Future<List<Device>> findTargetDevices(FlutterProject flutterProject) async {
|
||||
Future<List<Device>> findTargetDevices(FlutterProject flutterProject, { Duration timeout }) async {
|
||||
if (timeout != null) {
|
||||
// Reset the cache with the specified timeout.
|
||||
await refreshAllConnectedDevices(timeout: timeout);
|
||||
}
|
||||
|
||||
List<Device> devices = await getDevices();
|
||||
|
||||
// Always remove web and fuchsia devices from `--all`. This setting
|
||||
|
@ -113,6 +113,7 @@ class FlutterOptions {
|
||||
static const String kPerformanceMeasurementFile = 'performance-measurement-file';
|
||||
static const String kNullSafety = 'sound-null-safety';
|
||||
static const String kDeviceUser = 'device-user';
|
||||
static const String kDeviceTimeout = 'device-timeout';
|
||||
static const String kAnalyzeSize = 'analyze-size';
|
||||
static const String kNullAssertions = 'null-assertions';
|
||||
}
|
||||
@ -404,6 +405,28 @@ abstract class FlutterCommand extends Command<void> {
|
||||
valueHelp: '10');
|
||||
}
|
||||
|
||||
void usesDeviceTimeoutOption() {
|
||||
argParser.addOption(
|
||||
FlutterOptions.kDeviceTimeout,
|
||||
help: 'Time in seconds to wait for devices to attach. Longer timeouts may be necessary for networked devices.',
|
||||
valueHelp: '10'
|
||||
);
|
||||
}
|
||||
|
||||
Duration get deviceDiscoveryTimeout {
|
||||
if (_deviceDiscoveryTimeout == null
|
||||
&& argResults.options.contains(FlutterOptions.kDeviceTimeout)
|
||||
&& argResults.wasParsed(FlutterOptions.kDeviceTimeout)) {
|
||||
final int timeoutSeconds = int.tryParse(stringArg(FlutterOptions.kDeviceTimeout));
|
||||
if (timeoutSeconds == null) {
|
||||
throwToolExit( 'Could not parse --${FlutterOptions.kDeviceTimeout} argument. It must be an integer.');
|
||||
}
|
||||
_deviceDiscoveryTimeout = Duration(seconds: timeoutSeconds);
|
||||
}
|
||||
return _deviceDiscoveryTimeout;
|
||||
}
|
||||
Duration _deviceDiscoveryTimeout;
|
||||
|
||||
void addBuildModeFlags({ bool defaultToRelease = true, bool verboseHelp = false, bool excludeDebug = false }) {
|
||||
// A release build must be the default if a debug build is not possible.
|
||||
assert(defaultToRelease || !excludeDebug);
|
||||
@ -970,7 +993,7 @@ abstract class FlutterCommand extends Command<void> {
|
||||
return null;
|
||||
}
|
||||
final DeviceManager deviceManager = globals.deviceManager;
|
||||
List<Device> devices = await deviceManager.findTargetDevices(FlutterProject.current());
|
||||
List<Device> devices = await deviceManager.findTargetDevices(FlutterProject.current(), timeout: deviceDiscoveryTimeout);
|
||||
|
||||
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
|
||||
globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId));
|
||||
|
@ -342,6 +342,8 @@ void main() {
|
||||
'-v',
|
||||
'--device-user',
|
||||
'10',
|
||||
'--device-timeout',
|
||||
'15',
|
||||
]);
|
||||
final VerificationResult verificationResult = verify(
|
||||
mockHotRunnerFactory.build(
|
||||
|
@ -281,7 +281,7 @@ void main() {
|
||||
when(mockDevice.name).thenReturn('specified-device');
|
||||
when(mockDevice.id).thenReturn('123');
|
||||
|
||||
final Device device = await findTargetDevice();
|
||||
final Device device = await findTargetDevice(timeout: null);
|
||||
expect(device.name, 'specified-device');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
@ -293,7 +293,7 @@ void main() {
|
||||
Platform platform() => FakePlatform(operatingSystem: operatingSystem);
|
||||
|
||||
testUsingContext('returns null if no devices found', () async {
|
||||
expect(await findTargetDevice(), isNull);
|
||||
expect(await findTargetDevice(timeout: null), isNull);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
@ -305,7 +305,7 @@ void main() {
|
||||
when(mockDevice.name).thenReturn('mock-android-device');
|
||||
testDeviceManager.addDevice(mockDevice);
|
||||
|
||||
final Device device = await findTargetDevice();
|
||||
final Device device = await findTargetDevice(timeout: null);
|
||||
expect(device.name, 'mock-android-device');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
@ -337,7 +337,7 @@ void main() {
|
||||
testDeviceManager.addDevice(mockDevice);
|
||||
testDeviceManager.addDevice(mockUnsupportedDevice);
|
||||
|
||||
final Device device = await findTargetDevice();
|
||||
final Device device = await findTargetDevice(timeout: null);
|
||||
expect(device.name, 'mock-android-device');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
@ -366,7 +366,7 @@ void main() {
|
||||
when(mockDevice.isLocalEmulator)
|
||||
.thenAnswer((Invocation invocation) => Future<bool>.value(true));
|
||||
|
||||
final Device device = await findTargetDevice();
|
||||
final Device device = await findTargetDevice(timeout: null);
|
||||
expect(device.name, 'mock-simulator');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
|
@ -178,7 +178,7 @@ void main() {
|
||||
when(mockDeviceManager.getDevices()).thenAnswer(
|
||||
(Invocation invocation) => Future<List<Device>>.value(noDevices)
|
||||
);
|
||||
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
|
||||
when(mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout'))).thenAnswer(
|
||||
(Invocation invocation) => Future<List<Device>>.value(noDevices)
|
||||
);
|
||||
|
||||
@ -214,7 +214,7 @@ void main() {
|
||||
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) async {
|
||||
return <Device>[device];
|
||||
});
|
||||
when(mockDeviceManager.findTargetDevices(any)).thenAnswer((Invocation invocation) async {
|
||||
when(mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout'))).thenAnswer((Invocation invocation) async {
|
||||
return <Device>[device];
|
||||
});
|
||||
when(mockDeviceManager.hasSpecifiedAllDevices).thenReturn(false);
|
||||
@ -254,7 +254,7 @@ void main() {
|
||||
]);
|
||||
});
|
||||
|
||||
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
|
||||
when(mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout'))).thenAnswer(
|
||||
(Invocation invocation) => Future<List<Device>>.value(<Device>[]),
|
||||
);
|
||||
|
||||
@ -301,7 +301,8 @@ void main() {
|
||||
);
|
||||
// No devices are attached, we just want to verify update the cache
|
||||
// BEFORE checking for devices
|
||||
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
|
||||
const Duration timeout = Duration(seconds: 10);
|
||||
when(mockDeviceManager.findTargetDevices(any, timeout: timeout)).thenAnswer(
|
||||
(Invocation invocation) => Future<List<Device>>.value(<Device>[])
|
||||
);
|
||||
|
||||
@ -309,6 +310,8 @@ void main() {
|
||||
await createTestCommandRunner(command).run(<String>[
|
||||
'run',
|
||||
'--no-pub',
|
||||
'--device-timeout',
|
||||
'10',
|
||||
]);
|
||||
fail('Exception expected');
|
||||
} on ToolExit catch (e) {
|
||||
@ -324,7 +327,7 @@ void main() {
|
||||
// as part of gathering `requiredArtifacts`
|
||||
mockDeviceManager.getDevices(),
|
||||
// in validateCommand()
|
||||
mockDeviceManager.findTargetDevices(any),
|
||||
mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout')),
|
||||
]);
|
||||
}, overrides: <Type, Generator>{
|
||||
ApplicationPackageFactory: () => mockApplicationPackageFactory,
|
||||
@ -365,7 +368,7 @@ void main() {
|
||||
(Invocation invocation) => Future<List<Device>>.value(<Device>[mockDevice])
|
||||
);
|
||||
|
||||
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
|
||||
when(mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout'))).thenAnswer(
|
||||
(Invocation invocation) => Future<List<Device>>.value(<Device>[mockDevice])
|
||||
);
|
||||
|
||||
@ -434,7 +437,7 @@ void main() {
|
||||
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
|
||||
return Future<List<Device>>.value(<Device>[fakeDevice]);
|
||||
});
|
||||
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
|
||||
when(mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout'))).thenAnswer(
|
||||
(Invocation invocation) => Future<List<Device>>.value(<Device>[fakeDevice])
|
||||
);
|
||||
});
|
||||
|
@ -58,8 +58,10 @@ void main() {
|
||||
// 3. A device discoverer that succeeds.
|
||||
final DeviceManager deviceManager = TestDeviceManager(
|
||||
devices,
|
||||
testLongPollingDeviceDiscovery: true,
|
||||
testThrowingDeviceDiscovery: true,
|
||||
deviceDiscoveryOverrides: <DeviceDiscovery>[
|
||||
ThrowingPollingDeviceDiscovery(),
|
||||
LongPollingDeviceDiscovery(),
|
||||
],
|
||||
);
|
||||
|
||||
Future<void> expectDevice(String id, List<Device> expected) async {
|
||||
@ -89,7 +91,9 @@ void main() {
|
||||
// 2. A device discoverer that succeeds.
|
||||
final DeviceManager deviceManager = TestDeviceManager(
|
||||
devices,
|
||||
testThrowingDeviceDiscovery: true
|
||||
deviceDiscoveryOverrides: <DeviceDiscovery>[
|
||||
ThrowingPollingDeviceDiscovery(),
|
||||
],
|
||||
);
|
||||
|
||||
Future<void> expectDevice(String id, List<Device> expected) async {
|
||||
@ -387,7 +391,62 @@ void main() {
|
||||
Artifacts: () => Artifacts.test(),
|
||||
Cache: () => cache,
|
||||
});
|
||||
|
||||
testUsingContext('does not refresh device cache without a timeout', () async {
|
||||
final List<Device> devices = <Device>[
|
||||
ephemeralOne,
|
||||
];
|
||||
final MockDeviceDiscovery mockDeviceDiscovery = MockDeviceDiscovery();
|
||||
when(mockDeviceDiscovery.supportsPlatform).thenReturn(true);
|
||||
// when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
|
||||
when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices);
|
||||
// when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
|
||||
|
||||
final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[
|
||||
mockDeviceDiscovery
|
||||
]);
|
||||
deviceManager.specifiedDeviceId = ephemeralOne.id;
|
||||
final List<Device> filtered = await deviceManager.findTargetDevices(
|
||||
FlutterProject.current(),
|
||||
);
|
||||
|
||||
expect(filtered.single, ephemeralOne);
|
||||
verify(mockDeviceDiscovery.devices).called(1);
|
||||
verifyNever(mockDeviceDiscovery.discoverDevices(timeout: anyNamed('timeout')));
|
||||
}, overrides: <Type, Generator>{
|
||||
Artifacts: () => Artifacts.test(),
|
||||
Cache: () => cache,
|
||||
});
|
||||
|
||||
testUsingContext('refreshes device cache with a timeout', () async {
|
||||
final List<Device> devices = <Device>[
|
||||
ephemeralOne,
|
||||
];
|
||||
const Duration timeout = Duration(seconds: 2);
|
||||
final MockDeviceDiscovery mockDeviceDiscovery = MockDeviceDiscovery();
|
||||
when(mockDeviceDiscovery.supportsPlatform).thenReturn(true);
|
||||
when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
|
||||
when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices);
|
||||
// when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
|
||||
|
||||
final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[
|
||||
mockDeviceDiscovery
|
||||
]);
|
||||
deviceManager.specifiedDeviceId = ephemeralOne.id;
|
||||
final List<Device> filtered = await deviceManager.findTargetDevices(
|
||||
FlutterProject.current(),
|
||||
timeout: timeout,
|
||||
);
|
||||
|
||||
expect(filtered.single, ephemeralOne);
|
||||
verify(mockDeviceDiscovery.devices).called(1);
|
||||
verify(mockDeviceDiscovery.discoverDevices(timeout: anyNamed('timeout'))).called(1);
|
||||
}, overrides: <Type, Generator>{
|
||||
Artifacts: () => Artifacts.test(),
|
||||
Cache: () => cache,
|
||||
});
|
||||
});
|
||||
|
||||
group('ForwardedPort', () {
|
||||
group('dispose()', () {
|
||||
testUsingContext('does not throw exception if no process is present', () {
|
||||
@ -427,16 +486,13 @@ void main() {
|
||||
|
||||
class TestDeviceManager extends DeviceManager {
|
||||
TestDeviceManager(List<Device> allDevices, {
|
||||
bool testLongPollingDeviceDiscovery = false,
|
||||
bool testThrowingDeviceDiscovery = false,
|
||||
List<DeviceDiscovery> deviceDiscoveryOverrides,
|
||||
}) {
|
||||
_fakeDeviceDiscoverer = FakePollingDeviceDiscovery();
|
||||
_deviceDiscoverers = <DeviceDiscovery>[
|
||||
if (testLongPollingDeviceDiscovery)
|
||||
LongPollingDeviceDiscovery(),
|
||||
if (testThrowingDeviceDiscovery)
|
||||
ThrowingPollingDeviceDiscovery(),
|
||||
_fakeDeviceDiscoverer,
|
||||
if (deviceDiscoveryOverrides != null)
|
||||
...deviceDiscoveryOverrides
|
||||
];
|
||||
resetDevices(allDevices);
|
||||
}
|
||||
@ -464,3 +520,4 @@ class MockProcess extends Mock implements Process {}
|
||||
class MockTerminal extends Mock implements AnsiTerminal {}
|
||||
class MockStdio extends Mock implements Stdio {}
|
||||
class MockCache extends Mock implements Cache {}
|
||||
class MockDeviceDiscovery extends Mock implements DeviceDiscovery {}
|
||||
|
@ -248,7 +248,7 @@ class FakeDeviceManager implements DeviceManager {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Device>> findTargetDevices(FlutterProject flutterProject) async {
|
||||
Future<List<Device>> findTargetDevices(FlutterProject flutterProject, { Duration timeout }) async {
|
||||
return devices;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user