diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index 33f91398d5..4bf17f2f93 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart @@ -14,6 +14,7 @@ import '../artifacts.dart'; import '../base/file_system.dart'; import '../base/io.dart'; import '../base/logger.dart'; +import '../base/os.dart'; import '../base/platform.dart'; import '../base/process.dart'; import '../base/utils.dart'; @@ -493,6 +494,7 @@ class IOSDevice extends Device { dyLdLibEntry: globals.cache.dyLdLibEntry, id: id, iproxyPath: _iproxyPath, + operatingSystemUtils: globals.os, ); @visibleForTesting @@ -763,11 +765,13 @@ class IOSDevicePortForwarder extends DevicePortForwarder { @required MapEntry dyLdLibEntry, @required String id, @required String iproxyPath, + @required OperatingSystemUtils operatingSystemUtils, }) : _logger = logger, _dyLdLibEntry = dyLdLibEntry, _id = id, _iproxyPath = iproxyPath, - _processUtils = ProcessUtils(processManager: processManager, logger: logger); + _processUtils = ProcessUtils(processManager: processManager, logger: logger), + _operatingSystemUtils = operatingSystemUtils; /// Create a [IOSDevicePortForwarder] for testing. /// @@ -779,6 +783,7 @@ class IOSDevicePortForwarder extends DevicePortForwarder { @required ProcessManager processManager, @required Logger logger, String id, + OperatingSystemUtils operatingSystemUtils, }) { return IOSDevicePortForwarder( processManager: processManager, @@ -788,6 +793,7 @@ class IOSDevicePortForwarder extends DevicePortForwarder { dyLdLibEntry: const MapEntry( 'DYLD_LIBRARY_PATH', '/path/to/libs', ), + operatingSystemUtils: operatingSystemUtils, ); } @@ -796,6 +802,7 @@ class IOSDevicePortForwarder extends DevicePortForwarder { final MapEntry _dyLdLibEntry; final String _id; final String _iproxyPath; + final OperatingSystemUtils _operatingSystemUtils; @override List forwardedPorts = []; @@ -811,7 +818,9 @@ class IOSDevicePortForwarder extends DevicePortForwarder { Future forward(int devicePort, { int hostPort }) async { final bool autoselect = hostPort == null || hostPort == 0; if (autoselect) { - hostPort = 1024; + final int freePort = await _operatingSystemUtils?.findFreePort(); + // Dynamic port range 49152 - 65535. + hostPort = freePort == null || freePort == 0 ? 49152 : freePort; } Process process; diff --git a/packages/flutter_tools/test/general.shard/ios/devices_test.dart b/packages/flutter_tools/test/general.shard/ios/devices_test.dart index 01cf31b35c..0d4df19b94 100644 --- a/packages/flutter_tools/test/general.shard/ios/devices_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/devices_test.dart @@ -11,6 +11,7 @@ import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -226,6 +227,12 @@ void main() { iproxyPath: mockArtifacts.getArtifactPath(Artifact.iproxy, platform: TargetPlatform.ios), logger: logger, processManager: FakeProcessManager.any(), + operatingSystemUtils: OperatingSystemUtils( + fileSystem: mockFileSystem, + logger: logger, + platform: FakePlatform(operatingSystem: 'macos'), + processManager: FakeProcessManager.any(), + ), ); portForwarder.addForwardedPorts([forwardedPort]); return portForwarder; diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_port_forwarder_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_port_forwarder_test.dart index 6714f7fba2..e7ae055e37 100644 --- a/packages/flutter_tools/test/general.shard/ios/ios_device_port_forwarder_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/ios_device_port_forwarder_test.dart @@ -3,7 +3,9 @@ // found in the LICENSE file. import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/ios/devices.dart'; +import 'package:mockito/mockito.dart'; import '../../src/common.dart'; import '../../src/context.dart'; @@ -20,27 +22,33 @@ void main() { const int devicePort = 456; final FakeProcessManager processManager = FakeProcessManager.list([ const FakeCommand( - command: ['iproxy', '1024', '456', '1234'], + command: ['iproxy', '49154', '456', '1234'], // iproxy does not exit with 0 when it cannot forward. exitCode: 0, stdout: null, // no stdout indicates failure. environment: kDyLdLibEntry, ), const FakeCommand( - command: ['iproxy', '1025', '456', '1234'], + command: ['iproxy', '49155', '456', '1234'], exitCode: 0, stdout: 'not empty', environment: kDyLdLibEntry, ), ]); + final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils(); + when(operatingSystemUtils.findFreePort()).thenAnswer((Invocation invocation) => Future.value(49154)); + final IOSDevicePortForwarder portForwarder = IOSDevicePortForwarder.test( processManager: processManager, logger: BufferLogger.test(), + operatingSystemUtils: operatingSystemUtils, ); final int hostPort = await portForwarder.forward(devicePort); - // First port tried (1024) should fail, then succeed on the next - expect(hostPort, 1024 + 1); + // First port tried (49154) should fail, then succeed on the next + expect(hostPort, 49154 + 1); expect(processManager.hasRemainingExpectations, false); }); } + +class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}