Unverified Commit a599c23b authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Disallow running on unsupported devices (#97338)

parent 4cca04dd
......@@ -247,8 +247,8 @@ class UserMessages {
String get flutterNoDevelopmentDevice =>
"Unable to locate a development device; please run 'flutter doctor' "
'for information about installing additional components.';
String flutterNoMatchingDevice(String deviceId) => 'No devices found with name or id '
"matching '$deviceId'";
String flutterNoMatchingDevice(String deviceId) => 'No supported devices found with name or id '
"matching '$deviceId'.";
String get flutterNoDevicesFound => 'No devices found';
String get flutterNoSupportedDevices => 'No supported devices connected.';
String flutterMissPlatformProjects(List<String> unsupportedDevicesType) =>
......
......@@ -254,7 +254,8 @@ abstract class DeviceManager {
await refreshAllConnectedDevices(timeout: timeout);
}
List<Device> devices = await getDevices();
List<Device> devices = (await getDevices())
.where((Device device) => device.isSupported()).toList();
// Always remove web and fuchsia devices from `--all`. This setting
// currently requires devices to share a frontend_server and resident
......
......@@ -1364,6 +1364,12 @@ abstract class FlutterCommand extends Command<void> {
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId!));
final List<Device> allDevices = await deviceManager.getAllConnectedDevices();
if (allDevices.isNotEmpty) {
globals.printStatus('');
globals.printStatus('The following devices were found:');
await Device.printDevices(allDevices, globals.logger);
}
return null;
} else if (devices.isEmpty) {
if (deviceManager.hasSpecifiedAllDevices) {
......
......@@ -195,6 +195,33 @@ void main() {
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('exits and lists available devices when specified device not found', () async {
final RunCommand command = RunCommand();
final FakeDevice device = FakeDevice(isLocalEmulator: true);
mockDeviceManager
..devices = <Device>[device]
..hasSpecifiedDeviceId = true;
await expectLater(
() => createTestCommandRunner(command).run(<String>[
'run',
'-d',
'invalid-device-id',
'--no-pub',
'--no-hot',
]),
throwsToolExit(),
);
expect(testLogger.statusText, contains("No supported devices found with name or id matching 'invalid-device-id'"));
expect(testLogger.statusText, contains('The following devices were found:'));
expect(testLogger.statusText, contains('FakeDevice (mobile) • fake_device • ios • (simulator)'));
}, overrides: <Type, Generator>{
DeviceManager: () => mockDeviceManager,
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('fails when targeted device is not Android with --device-user', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').writeAsStringSync('\n');
......@@ -642,6 +669,9 @@ class FakeDeviceManager extends Fake implements DeviceManager {
Future<List<Device>> findTargetDevices(FlutterProject flutterProject, {Duration timeout}) async {
return targetDevices;
}
@override
Future<List<Device>> getAllConnectedDevices() async => devices;
}
class FakeAndroidSdk extends Fake implements AndroidSdk {
......
......@@ -179,6 +179,7 @@ void main() {
final FakeDevice nonEphemeralOne = FakeDevice('nonEphemeralOne', 'nonEphemeralOne', ephemeral: false);
final FakeDevice nonEphemeralTwo = FakeDevice('nonEphemeralTwo', 'nonEphemeralTwo', ephemeral: false);
final FakeDevice unsupported = FakeDevice('unsupported', 'unsupported', isSupported: false);
final FakeDevice unsupportedForProject = FakeDevice('unsupportedForProject', 'unsupportedForProject', isSupportedForProject: false);
final FakeDevice webDevice = FakeDevice('webby', 'webby')
..targetPlatform = Future<TargetPlatform>.value(TargetPlatform.web_javascript);
final FakeDevice fuchsiaDevice = FakeDevice('fuchsiay', 'fuchsiay')
......@@ -190,6 +191,7 @@ void main() {
nonEphemeralOne,
nonEphemeralTwo,
unsupported,
unsupportedForProject,
];
final DeviceManager deviceManager = TestDeviceManager(
......@@ -327,9 +329,29 @@ void main() {
);
});
testWithoutContext('Removes a single unsupported device', () async {
testWithoutContext('Unsupported devices listed in all connected devices', () async {
final List<Device> devices = <Device>[
unsupported,
unsupportedForProject,
];
final DeviceManager deviceManager = TestDeviceManager(
devices,
logger: BufferLogger.test(),
terminal: Terminal.test(),
);
final List<Device> filtered = await deviceManager.getAllConnectedDevices();
expect(filtered, <Device>[
unsupported,
unsupportedForProject,
]);
});
testWithoutContext('Removes a unsupported devices', () async {
final List<Device> devices = <Device>[
unsupported,
unsupportedForProject,
];
final DeviceManager deviceManager = TestDeviceManager(
......@@ -342,9 +364,10 @@ void main() {
expect(filtered, <Device>[]);
});
testWithoutContext('Does not remove an unsupported device if FlutterProject is null', () async {
testWithoutContext('Retains devices unsupported by the project if FlutterProject is null', () async {
final List<Device> devices = <Device>[
unsupported,
unsupportedForProject,
];
final DeviceManager deviceManager = TestDeviceManager(
......@@ -354,7 +377,7 @@ void main() {
);
final List<Device> filtered = await deviceManager.findTargetDevices(null);
expect(filtered, <Device>[unsupported]);
expect(filtered, <Device>[unsupportedForProject]);
});
testWithoutContext('Removes web and fuchsia from --all', () async {
......@@ -374,11 +397,12 @@ void main() {
expect(filtered, <Device>[]);
});
testWithoutContext('Removes unsupported devices from --all', () async {
testWithoutContext('Removes devices unsupported by the project from --all', () async {
final List<Device> devices = <Device>[
nonEphemeralOne,
nonEphemeralTwo,
unsupported,
unsupportedForProject,
];
final DeviceManager deviceManager = TestDeviceManager(
devices,
......@@ -398,18 +422,19 @@ void main() {
testWithoutContext('uses DeviceManager.isDeviceSupportedForProject instead of device.isSupportedForProject', () async {
final List<Device> devices = <Device>[
unsupported,
unsupportedForProject,
];
final TestDeviceManager deviceManager = TestDeviceManager(
devices,
logger: BufferLogger.test(),
terminal: Terminal.test(),
);
deviceManager.isAlwaysSupportedOverride = true;
deviceManager.isAlwaysSupportedForProjectOverride = true;
final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
expect(filtered, <Device>[
unsupported,
unsupportedForProject,
]);
});
......@@ -513,12 +538,12 @@ class TestDeviceManager extends DeviceManager {
_fakeDeviceDiscoverer.setDevices(allDevices);
}
bool? isAlwaysSupportedOverride;
bool? isAlwaysSupportedForProjectOverride;
@override
bool isDeviceSupportedForProject(Device device, FlutterProject? flutterProject) {
if (isAlwaysSupportedOverride != null) {
return isAlwaysSupportedOverride!;
if (isAlwaysSupportedForProjectOverride != null) {
return isAlwaysSupportedForProjectOverride!;
}
return super.isDeviceSupportedForProject(device, flutterProject);
}
......
......@@ -45,7 +45,7 @@ void main() {
expect(proc.stdout, isNot(contains('flutter has exited unexpectedly')));
expect(proc.stderr, isNot(contains('flutter has exited unexpectedly')));
if (!proc.stderr.toString().contains('Unable to locate a development')
&& !proc.stdout.toString().contains('No devices found with name or id matching')) {
&& !proc.stdout.toString().contains('No supported devices found with name or id matching')) {
fail("'flutter run -d invalid-device-id' did not produce the expected error");
}
});
......
......@@ -61,9 +61,11 @@ class FakeDevice extends Device {
FakeDevice(this.name, String id, {
bool ephemeral = true,
bool isSupported = true,
bool isSupportedForProject = true,
PlatformType type = PlatformType.web,
LaunchResult? launchResult,
}) : _isSupported = isSupported,
_isSupportedForProject = isSupportedForProject,
_launchResult = launchResult ?? LaunchResult.succeeded(),
super(
id,
......@@ -73,6 +75,7 @@ class FakeDevice extends Device {
);
final bool _isSupported;
final bool _isSupportedForProject;
final LaunchResult _launchResult;
@override
......@@ -110,7 +113,7 @@ class FakeDevice extends Device {
void noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
bool isSupportedForProject(FlutterProject flutterProject) => _isSupported;
bool isSupportedForProject(FlutterProject flutterProject) => _isSupportedForProject;
@override
bool isSupported() => _isSupported;
......
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