Unverified Commit c8cefce3 authored by Lau Ching Jun's avatar Lau Ching Jun Committed by GitHub

Move findTargetDevices to DeviceManager (#35084)

This allows us to override the behavior internally.
parent 259151c3
......@@ -167,6 +167,35 @@ class DeviceManager {
}
return diagnostics;
}
/// Find and return a list of devices based on the current project and environment.
///
/// Returns a list of deviecs specified by the user. If the user has not specified
/// all devices and has multiple connected then filter the list by those supported
/// in the current project and remove non-ephemeral device types.
Future<List<Device>> findTargetDevices(FlutterProject flutterProject) async {
List<Device> devices = await getDevices().toList();
if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices && !deviceManager.hasSpecifiedDeviceId) {
devices = devices
.where((Device device) => isDeviceSupportedForProject(device, flutterProject))
.toList();
// Note: ephemeral is nullable for device types where this is not well
// defined.
if (devices.any((Device device) => device.ephemeral == true)) {
devices = devices
.where((Device device) => device.ephemeral == true)
.toList();
}
}
return devices;
}
/// Returns whether the device is supported for the project.
bool isDeviceSupportedForProject(Device device, FlutterProject flutterProject) {
return device.isSupportedForProject(flutterProject);
}
}
/// An abstract class to discover and enumerate a specific type of devices.
......
......@@ -503,7 +503,7 @@ abstract class FlutterCommand extends Command<void> {
return null;
}
List<Device> devices = await deviceManager.getDevices().toList();
List<Device> devices = await deviceManager.findTargetDevices(FlutterProject.current());
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId));
......@@ -512,16 +512,6 @@ abstract class FlutterCommand extends Command<void> {
printStatus(userMessages.flutterNoDevicesFound);
return null;
} else if (devices.isEmpty) {
printNoConnectedDevices();
return null;
}
devices = devices.where((Device device) => device.isSupported()).toList();
if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices && !deviceManager.hasSpecifiedDeviceId) {
devices = filterDevices(devices);
}
if (devices.isEmpty) {
printStatus(userMessages.flutterNoSupportedDevices);
return null;
} else if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices) {
......@@ -694,24 +684,3 @@ abstract class FastFlutterCommand extends FlutterCommand {
);
}
}
// If the user has not specified all devices and has multiple connected
// then filter the list by those supported in the current project and
// remove non-ephemeral device types. If this ends up with a single
// device we can proceed as normal.
@visibleForTesting
List<Device> filterDevices(List<Device> devices) {
final FlutterProject flutterProject = FlutterProject.current();
devices = devices
.where((Device device) => device.isSupportedForProject(flutterProject))
.toList();
// Note: ephemeral is nullable for device types where this is not well
// defined.
if (devices.any((Device device) => device.ephemeral == true)) {
devices = devices
.where((Device device) => device.ephemeral == true)
.toList();
}
return devices;
}
......@@ -398,7 +398,7 @@ void main() {
createTestCommandRunner(command).run(<String>['attach']),
throwsA(isInstanceOf<ToolExit>()),
);
expect(testLogger.statusText, contains('No connected devices'));
expect(testLogger.statusText, contains('No supported devices connected'));
}, overrides: <Type, Generator>{
FileSystem: () => testFileSystem,
});
......
......@@ -5,6 +5,7 @@
import 'dart:async';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/project.dart';
import 'src/common.dart';
import 'src/context.dart';
......@@ -36,6 +37,49 @@ void main() {
await expectDevice('Nexus', <Device>[device1, device2]);
});
});
group('Filter devices', () {
_MockDevice ephemeral;
_MockDevice nonEphemeralOne;
_MockDevice nonEphemeralTwo;
_MockDevice unsupported;
setUp(() {
ephemeral = _MockDevice('ephemeral', 'ephemeral', true);
nonEphemeralOne = _MockDevice('nonEphemeralOne', 'nonEphemeralOne', false);
nonEphemeralTwo = _MockDevice('nonEphemeralTwo', 'nonEphemeralTwo', false);
unsupported = _MockDevice('unsupported', 'unsupported', true, false);
});
testUsingContext('chooses ephemeral device', () async {
final List<Device> devices = <Device>[
ephemeral,
nonEphemeralOne,
nonEphemeralTwo,
unsupported,
];
final DeviceManager deviceManager = TestDeviceManager(devices);
final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
expect(filtered.single, ephemeral);
});
testUsingContext('does not remove all non-ephemeral', () async {
final List<Device> devices = <Device>[
nonEphemeralOne,
nonEphemeralTwo,
];
final DeviceManager deviceManager = TestDeviceManager(devices);
final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
expect(filtered, <Device>[
nonEphemeralOne,
nonEphemeralTwo,
]);
});
});
}
class TestDeviceManager extends DeviceManager {
......@@ -50,16 +94,21 @@ class TestDeviceManager extends DeviceManager {
}
class _MockDevice extends Device {
_MockDevice(this.name, String id) : super(
_MockDevice(this.name, String id, [bool ephemeral = true, this._isSupported = true]) : super(
id,
platformType: PlatformType.web,
category: Category.mobile,
ephemeral: true,
ephemeral: ephemeral,
);
final bool _isSupported;
@override
final String name;
@override
void noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
bool isSupportedForProject(FlutterProject flutterProject) => _isSupported;
}
......@@ -4,8 +4,6 @@
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/usage.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
......@@ -291,43 +289,6 @@ void main() {
FlutterVersion: () => betaVersion,
});
});
group('Filter devices', () {
MockDevice ephemeral;
MockDevice nonEphemeralOne;
MockDevice nonEphemeralTwo;
MockDevice unsupported;
setUp(() {
ephemeral = MockDevice(true);
nonEphemeralOne = MockDevice(false);
nonEphemeralTwo = MockDevice(false);
unsupported = MockDevice(true, false);
});
test('chooses ephemeral device', () {
final List<Device> filtered = filterDevices(<Device>[
ephemeral,
nonEphemeralOne,
nonEphemeralTwo,
unsupported,
]);
expect(filtered.single, ephemeral);
});
test('does not remove all non-ephemeral', () {
final List<Device> filtered = filterDevices(<Device>[
nonEphemeralOne,
nonEphemeralTwo,
]);
expect(filtered, <Device>[
nonEphemeralOne,
nonEphemeralTwo,
]);
});
});
}
......@@ -348,15 +309,3 @@ class FakeCommand extends FlutterCommand {
}
class MockVersion extends Mock implements FlutterVersion {}
class MockDevice extends Mock implements Device {
MockDevice(this.ephemeral, [this._isSupported = true]);
@override
final bool ephemeral;
final bool _isSupported;
@override
bool isSupportedForProject(FlutterProject flutterProject) => _isSupported;
}
......@@ -20,6 +20,7 @@ import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/simulators.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/usage.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:meta/meta.dart';
......@@ -185,6 +186,16 @@ class MockDeviceManager implements DeviceManager {
@override
List<DeviceDiscovery> get deviceDiscoverers => <DeviceDiscovery>[];
@override
Future<List<Device>> findTargetDevices(FlutterProject flutterProject) {
return getDevices().toList();
}
@override
bool isDeviceSupportedForProject(Device device, FlutterProject flutterProject) {
return device.isSupportedForProject(flutterProject);
}
}
class MockAndroidLicenseValidator extends AndroidLicenseValidator {
......
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