@@ -24,6 +24,8 @@ import 'package:flutter_tools/src/commands/run.dart';
2424import 'package:flutter_tools/src/devfs.dart' ;
2525import 'package:flutter_tools/src/device.dart' ;
2626import 'package:flutter_tools/src/globals.dart' as globals;
27+ import 'package:flutter_tools/src/ios/devices.dart' ;
28+ import 'package:flutter_tools/src/ios/iproxy.dart' ;
2729import 'package:flutter_tools/src/project.dart' ;
2830import 'package:flutter_tools/src/reporting/reporting.dart' ;
2931import 'package:flutter_tools/src/resident_runner.dart' ;
@@ -426,7 +428,7 @@ void main() {
426428 TestUsageCommand ('run' , parameters: CustomDimensions .fromMap (< String , String > {
427429 'cd3' : 'false' , 'cd4' : 'ios' , 'cd22' : 'iOS 13' ,
428430 'cd23' : 'debug' , 'cd18' : 'false' , 'cd15' : 'swift' , 'cd31' : 'true' ,
429- 'cd56' : 'false' ,
431+ 'cd56' : 'false' , 'cd57' : 'usb' ,
430432 })
431433 )));
432434 }, overrides: < Type , Generator > {
@@ -664,6 +666,104 @@ void main() {
664666 FileSystem : () => MemoryFileSystem .test (),
665667 ProcessManager : () => FakeProcessManager .any (),
666668 });
669+
670+ group ('usageValues' , () {
671+ testUsingContext ('with only non-iOS usb device' , () async {
672+ final List <Device > devices = < Device > [
673+ FakeDevice (targetPlatform: TargetPlatform .android_arm, platformType: PlatformType .android),
674+ ];
675+ final TestRunCommandForUsageValues command = TestRunCommandForUsageValues (devices: devices);
676+ final CustomDimensions dimensions = await command.usageValues;
677+
678+ expect (dimensions, const CustomDimensions (
679+ commandRunIsEmulator: false ,
680+ commandRunTargetName: 'android-arm' ,
681+ commandRunTargetOsVersion: '' ,
682+ commandRunModeName: 'debug' ,
683+ commandRunProjectModule: false ,
684+ commandRunProjectHostLanguage: '' ,
685+ commandRunEnableImpeller: false ,
686+ ));
687+ }, overrides: < Type , Generator > {
688+ DeviceManager : () => testDeviceManager,
689+ Cache : () => Cache .test (processManager: FakeProcessManager .any ()),
690+ FileSystem : () => MemoryFileSystem .test (),
691+ ProcessManager : () => FakeProcessManager .any (),
692+ });
693+
694+ testUsingContext ('with only iOS usb device' , () async {
695+ final List <Device > devices = < Device > [
696+ FakeIOSDevice (interfaceType: IOSDeviceConnectionInterface .usb, sdkNameAndVersion: 'iOS 16.2' ),
697+ ];
698+ final TestRunCommandForUsageValues command = TestRunCommandForUsageValues (devices: devices);
699+ final CustomDimensions dimensions = await command.usageValues;
700+
701+ expect (dimensions, const CustomDimensions (
702+ commandRunIsEmulator: false ,
703+ commandRunTargetName: 'ios' ,
704+ commandRunTargetOsVersion: 'iOS 16.2' ,
705+ commandRunModeName: 'debug' ,
706+ commandRunProjectModule: false ,
707+ commandRunProjectHostLanguage: '' ,
708+ commandRunEnableImpeller: false ,
709+ commandRunIOSInterfaceType: 'usb' ,
710+ ));
711+ }, overrides: < Type , Generator > {
712+ DeviceManager : () => testDeviceManager,
713+ Cache : () => Cache .test (processManager: FakeProcessManager .any ()),
714+ FileSystem : () => MemoryFileSystem .test (),
715+ ProcessManager : () => FakeProcessManager .any (),
716+ });
717+
718+ testUsingContext ('with only iOS network device' , () async {
719+ final List <Device > devices = < Device > [
720+ FakeIOSDevice (interfaceType: IOSDeviceConnectionInterface .network, sdkNameAndVersion: 'iOS 16.2' ),
721+ ];
722+ final TestRunCommandForUsageValues command = TestRunCommandForUsageValues (devices: devices);
723+ final CustomDimensions dimensions = await command.usageValues;
724+
725+ expect (dimensions, const CustomDimensions (
726+ commandRunIsEmulator: false ,
727+ commandRunTargetName: 'ios' ,
728+ commandRunTargetOsVersion: 'iOS 16.2' ,
729+ commandRunModeName: 'debug' ,
730+ commandRunProjectModule: false ,
731+ commandRunProjectHostLanguage: '' ,
732+ commandRunEnableImpeller: false ,
733+ commandRunIOSInterfaceType: 'wireless' ,
734+ ));
735+ }, overrides: < Type , Generator > {
736+ DeviceManager : () => testDeviceManager,
737+ Cache : () => Cache .test (processManager: FakeProcessManager .any ()),
738+ FileSystem : () => MemoryFileSystem .test (),
739+ ProcessManager : () => FakeProcessManager .any (),
740+ });
741+
742+ testUsingContext ('with both iOS usb and network devices' , () async {
743+ final List <Device > devices = < Device > [
744+ FakeIOSDevice (interfaceType: IOSDeviceConnectionInterface .network, sdkNameAndVersion: 'iOS 16.2' ),
745+ FakeIOSDevice (interfaceType: IOSDeviceConnectionInterface .usb, sdkNameAndVersion: 'iOS 16.2' ),
746+ ];
747+ final TestRunCommandForUsageValues command = TestRunCommandForUsageValues (devices: devices);
748+ final CustomDimensions dimensions = await command.usageValues;
749+
750+ expect (dimensions, const CustomDimensions (
751+ commandRunIsEmulator: false ,
752+ commandRunTargetName: 'multiple' ,
753+ commandRunTargetOsVersion: 'multiple' ,
754+ commandRunModeName: 'debug' ,
755+ commandRunProjectModule: false ,
756+ commandRunProjectHostLanguage: '' ,
757+ commandRunEnableImpeller: false ,
758+ commandRunIOSInterfaceType: 'wireless' ,
759+ ));
760+ }, overrides: < Type , Generator > {
761+ DeviceManager : () => testDeviceManager,
762+ Cache : () => Cache .test (processManager: FakeProcessManager .any ()),
763+ FileSystem : () => MemoryFileSystem .test (),
764+ ProcessManager : () => FakeProcessManager .any (),
765+ });
766+ });
667767 });
668768
669769 group ('dart-defines and web-renderer options' , () {
@@ -1032,6 +1132,49 @@ class FakeDevice extends Fake implements Device {
10321132 }
10331133}
10341134
1135+ // Unfortunately Device, despite not being immutable, has an `operator ==`.
1136+ // Until we fix that, we have to also ignore related lints here.
1137+ // ignore: avoid_implementing_value_types
1138+ class FakeIOSDevice extends Fake implements IOSDevice {
1139+ FakeIOSDevice ({
1140+ this .interfaceType = IOSDeviceConnectionInterface .none,
1141+ bool isLocalEmulator = false ,
1142+ String sdkNameAndVersion = '' ,
1143+ }): _isLocalEmulator = isLocalEmulator,
1144+ _sdkNameAndVersion = sdkNameAndVersion;
1145+
1146+ final bool _isLocalEmulator;
1147+ final String _sdkNameAndVersion;
1148+
1149+ @override
1150+ Future <bool > get isLocalEmulator => Future <bool >.value (_isLocalEmulator);
1151+
1152+ @override
1153+ Future <String > get sdkNameAndVersion => Future <String >.value (_sdkNameAndVersion);
1154+
1155+ @override
1156+ final IOSDeviceConnectionInterface interfaceType;
1157+
1158+ @override
1159+ Future <TargetPlatform > get targetPlatform async => TargetPlatform .ios;
1160+ }
1161+
1162+ class TestRunCommandForUsageValues extends RunCommand {
1163+ TestRunCommandForUsageValues ({
1164+ this .devices,
1165+ });
1166+
1167+ @override
1168+ // devices is not set within usageValues, so we override the field
1169+ // ignore: overridden_fields
1170+ List <Device >? devices;
1171+
1172+ @override
1173+ Future <BuildInfo > getBuildInfo ({ BuildMode ? forcedBuildMode, File ? forcedTargetFile }) async {
1174+ return const BuildInfo (BuildMode .debug, null , treeShakeIcons: false );
1175+ }
1176+ }
1177+
10351178class TestRunCommandWithFakeResidentRunner extends RunCommand {
10361179 late FakeResidentRunner fakeResidentRunner;
10371180
0 commit comments