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

Add publish-port flag to disable mDNS port discovery (#67452)

parent e1b4142a
...@@ -55,6 +55,11 @@ class DriveCommand extends RunCommandBase { ...@@ -55,6 +55,11 @@ class DriveCommand extends RunCommandBase {
}) { }) {
requiresPubspecYaml(); requiresPubspecYaml();
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
// By default, the drive app should not publish the VM service port over mDNS
// to prevent a local network permission dialog on iOS 14+,
// which cannot be accepted or dismissed in a CI environment.
addPublishPort(enabledByDefault: false, verboseHelp: verboseHelp);
argParser argParser
..addFlag('keep-app-running', ..addFlag('keep-app-running',
defaultsTo: null, defaultsTo: null,
...@@ -215,7 +220,8 @@ class DriveCommand extends RunCommandBase { ...@@ -215,7 +220,8 @@ class DriveCommand extends RunCommandBase {
) )
: DebuggingOptions.enabled( : DebuggingOptions.enabled(
getBuildInfo(), getBuildInfo(),
port: stringArg('web-port') port: stringArg('web-port'),
disablePortPublication: disablePortPublication,
), ),
stayResident: false, stayResident: false,
urlTunneller: null, urlTunneller: null,
...@@ -501,6 +507,7 @@ Future<LaunchResult> _startApp( ...@@ -501,6 +507,7 @@ Future<LaunchResult> _startApp(
command.getBuildInfo(), command.getBuildInfo(),
startPaused: true, startPaused: true,
hostVmServicePort: webUri != null ? command.hostVmservicePort : 0, hostVmServicePort: webUri != null ? command.hostVmservicePort : 0,
disablePortPublication: command.disablePortPublication,
ddsPort: command.ddsPort, ddsPort: command.ddsPort,
verboseSystemLogs: command.verboseSystemLogs, verboseSystemLogs: command.verboseSystemLogs,
cacheSkSL: command.cacheSkSL, cacheSkSL: command.cacheSkSL,
......
...@@ -97,6 +97,11 @@ class RunCommand extends RunCommandBase { ...@@ -97,6 +97,11 @@ class RunCommand extends RunCommandBase {
usesFilesystemOptions(hide: !verboseHelp); usesFilesystemOptions(hide: !verboseHelp);
usesExtraFrontendOptions(); usesExtraFrontendOptions();
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
// By default, the app should to publish the VM service port over mDNS.
// This will allow subsequent "flutter attach" commands to connect to the VM
// without needing to know the port.
addPublishPort(enabledByDefault: true, verboseHelp: verboseHelp);
argParser argParser
..addFlag('start-paused', ..addFlag('start-paused',
negatable: false, negatable: false,
...@@ -407,6 +412,7 @@ class RunCommand extends RunCommandBase { ...@@ -407,6 +412,7 @@ class RunCommand extends RunCommandBase {
purgePersistentCache: purgePersistentCache, purgePersistentCache: purgePersistentCache,
deviceVmServicePort: deviceVmservicePort, deviceVmServicePort: deviceVmservicePort,
hostVmServicePort: hostVmservicePort, hostVmServicePort: hostVmservicePort,
disablePortPublication: disablePortPublication,
ddsPort: ddsPort, ddsPort: ddsPort,
verboseSystemLogs: boolArg('verbose-system-logs'), verboseSystemLogs: boolArg('verbose-system-logs'),
initializePlatform: boolArg('web-initialize-platform'), initializePlatform: boolArg('web-initialize-platform'),
......
...@@ -813,6 +813,7 @@ class DebuggingOptions { ...@@ -813,6 +813,7 @@ class DebuggingOptions {
this.useTestFonts = false, this.useTestFonts = false,
this.verboseSystemLogs = false, this.verboseSystemLogs = false,
this.hostVmServicePort, this.hostVmServicePort,
this.disablePortPublication = false,
this.deviceVmServicePort, this.deviceVmServicePort,
this.ddsPort, this.ddsPort,
this.initializePlatform = true, this.initializePlatform = true,
...@@ -855,6 +856,7 @@ class DebuggingOptions { ...@@ -855,6 +856,7 @@ class DebuggingOptions {
purgePersistentCache = false, purgePersistentCache = false,
verboseSystemLogs = false, verboseSystemLogs = false,
hostVmServicePort = null, hostVmServicePort = null,
disablePortPublication = false,
deviceVmServicePort = null, deviceVmServicePort = null,
ddsPort = null, ddsPort = null,
vmserviceOutFile = null, vmserviceOutFile = null,
...@@ -884,6 +886,7 @@ class DebuggingOptions { ...@@ -884,6 +886,7 @@ class DebuggingOptions {
final bool initializePlatform; final bool initializePlatform;
final int hostVmServicePort; final int hostVmServicePort;
final int deviceVmServicePort; final int deviceVmServicePort;
final bool disablePortPublication;
final int ddsPort; final int ddsPort;
final String port; final String port;
final String hostname; final String hostname;
......
...@@ -22,7 +22,6 @@ import '../convert.dart'; ...@@ -22,7 +22,6 @@ import '../convert.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
import '../macos/xcode.dart'; import '../macos/xcode.dart';
import '../mdns_discovery.dart';
import '../project.dart'; import '../project.dart';
import '../protocol_discovery.dart'; import '../protocol_discovery.dart';
import '../vmservice.dart'; import '../vmservice.dart';
...@@ -369,6 +368,7 @@ class IOSDevice extends Device { ...@@ -369,6 +368,7 @@ class IOSDevice extends Device {
'--enable-service-port-fallback', '--enable-service-port-fallback',
'--disable-service-auth-codes', '--disable-service-auth-codes',
'--observatory-port=$assumedObservatoryPort', '--observatory-port=$assumedObservatoryPort',
if (debuggingOptions.disablePortPublication) '--disable-observatory-publication',
if (debuggingOptions.startPaused) '--start-paused', if (debuggingOptions.startPaused) '--start-paused',
if (dartVmFlags.isNotEmpty) '--dart-flags="$dartVmFlags"', if (dartVmFlags.isNotEmpty) '--dart-flags="$dartVmFlags"',
if (debuggingOptions.useTestFonts) '--use-test-fonts', if (debuggingOptions.useTestFonts) '--use-test-fonts',
...@@ -453,7 +453,6 @@ class IOSDevice extends Device { ...@@ -453,7 +453,6 @@ class IOSDevice extends Device {
_logger.printTrace('Application launched on the device. Waiting for observatory port.'); _logger.printTrace('Application launched on the device. Waiting for observatory port.');
final FallbackDiscovery fallbackDiscovery = FallbackDiscovery( final FallbackDiscovery fallbackDiscovery = FallbackDiscovery(
logger: _logger, logger: _logger,
mDnsObservatoryDiscovery: MDnsObservatoryDiscovery.instance,
portForwarder: portForwarder, portForwarder: portForwarder,
protocolDiscovery: observatoryDiscovery, protocolDiscovery: observatoryDiscovery,
flutterUsage: globals.flutterUsage, flutterUsage: globals.flutterUsage,
......
...@@ -8,7 +8,6 @@ import 'package:vm_service/vm_service.dart'; ...@@ -8,7 +8,6 @@ import 'package:vm_service/vm_service.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../device.dart'; import '../device.dart';
import '../mdns_discovery.dart';
import '../protocol_discovery.dart'; import '../protocol_discovery.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
...@@ -17,36 +16,23 @@ typedef VmServiceConnector = Future<VmService> Function(String, {Log log}); ...@@ -17,36 +16,23 @@ typedef VmServiceConnector = Future<VmService> Function(String, {Log log});
/// A protocol for discovery of a vmservice on an attached iOS device with /// A protocol for discovery of a vmservice on an attached iOS device with
/// multiple fallbacks. /// multiple fallbacks.
/// ///
/// On versions of iOS 13 and greater, libimobiledevice can no longer listen to /// First, it tries to discover a vmservice by assigning a
/// logs directly. The only way to discover an active observatory is through the
/// mDNS protocol. However, there are a number of circumstances where this breaks
/// down, such as when the device is connected to certain wifi networks or with
/// certain hotspot connections enabled.
///
/// Another approach to discover a vmservice is to attempt to assign a
/// specific port and then attempt to connect. This may fail if the port is /// specific port and then attempt to connect. This may fail if the port is
/// not available. This port value should be either random, or otherwise /// not available. This port value should be either random, or otherwise
/// generated with application specific input. This reduces the chance of /// generated with application specific input. This reduces the chance of
/// accidentally connecting to another running flutter application. /// accidentally connecting to another running flutter application.
/// ///
/// Finally, if neither of the above approaches works, we can still attempt /// If that does not work, attempt to scan logs from the attached debugger
/// to parse logs. /// and parse the connected port logged by the engine.
///
/// To improve the overall resilience of the process, this class combines the
/// three discovery strategies. First it assigns a port and attempts to connect.
/// Then if this fails it falls back to mDNS, then finally attempting to scan
/// logs.
class FallbackDiscovery { class FallbackDiscovery {
FallbackDiscovery({ FallbackDiscovery({
@required DevicePortForwarder portForwarder, @required DevicePortForwarder portForwarder,
@required MDnsObservatoryDiscovery mDnsObservatoryDiscovery,
@required Logger logger, @required Logger logger,
@required ProtocolDiscovery protocolDiscovery, @required ProtocolDiscovery protocolDiscovery,
@required Usage flutterUsage, @required Usage flutterUsage,
@required VmServiceConnector vmServiceConnectUri, @required VmServiceConnector vmServiceConnectUri,
Duration pollingDelay, Duration pollingDelay,
}) : _logger = logger, }) : _logger = logger,
_mDnsObservatoryDiscovery = mDnsObservatoryDiscovery,
_portForwarder = portForwarder, _portForwarder = portForwarder,
_protocolDiscovery = protocolDiscovery, _protocolDiscovery = protocolDiscovery,
_flutterUsage = flutterUsage, _flutterUsage = flutterUsage,
...@@ -56,7 +42,6 @@ class FallbackDiscovery { ...@@ -56,7 +42,6 @@ class FallbackDiscovery {
static const String _kEventName = 'ios-handshake'; static const String _kEventName = 'ios-handshake';
final DevicePortForwarder _portForwarder; final DevicePortForwarder _portForwarder;
final MDnsObservatoryDiscovery _mDnsObservatoryDiscovery;
final Logger _logger; final Logger _logger;
final ProtocolDiscovery _protocolDiscovery; final ProtocolDiscovery _protocolDiscovery;
final Usage _flutterUsage; final Usage _flutterUsage;
...@@ -97,37 +82,13 @@ class FallbackDiscovery { ...@@ -97,37 +82,13 @@ class FallbackDiscovery {
} on Exception catch (err) { } on Exception catch (err) {
_logger.printTrace(err.toString()); _logger.printTrace(err.toString());
} }
_logger.printTrace('Failed to connect with log scanning, falling back to mDNS'); _logger.printTrace('Failed to connect with log scanning');
UsageEvent( UsageEvent(
_kEventName, _kEventName,
'log-failure', 'log-failure',
flutterUsage: _flutterUsage, flutterUsage: _flutterUsage,
).send(); ).send();
try {
final Uri result = await _mDnsObservatoryDiscovery.getObservatoryUri(
packageId,
device,
usesIpv6: usesIpv6,
hostVmservicePort: hostVmservicePort,
);
if (result != null) {
UsageEvent(
_kEventName,
'mdns-success',
flutterUsage: _flutterUsage,
).send();
return result;
}
} on Exception catch (err) {
_logger.printTrace(err.toString());
}
_logger.printTrace('Failed to connect with mDNS');
UsageEvent(
_kEventName,
'mdns-failure',
flutterUsage: _flutterUsage,
).send();
return null; return null;
} }
...@@ -200,7 +161,7 @@ class FallbackDiscovery { ...@@ -200,7 +161,7 @@ class FallbackDiscovery {
await Future<void>.delayed(_pollingDelay); await Future<void>.delayed(_pollingDelay);
attempts += 1; attempts += 1;
} }
_logger.printTrace('Failed to connect directly, falling back to mDNS'); _logger.printTrace('Failed to connect directly, falling back to log scanning');
_sendFailureEvent(firstException, assumedDevicePort); _sendFailureEvent(firstException, assumedDevicePort);
return null; return null;
} }
......
...@@ -51,6 +51,7 @@ class MDnsObservatoryDiscovery { ...@@ -51,6 +51,7 @@ class MDnsObservatoryDiscovery {
/// it will return that instance's information regardless of what application /// it will return that instance's information regardless of what application
/// the Observatory instance is for. /// the Observatory instance is for.
// TODO(jonahwilliams): use `deviceVmservicePort` to filter mdns results. // TODO(jonahwilliams): use `deviceVmservicePort` to filter mdns results.
@visibleForTesting
Future<MDnsObservatoryDiscoveryResult> query({String applicationId, int deviceVmservicePort}) async { Future<MDnsObservatoryDiscoveryResult> query({String applicationId, int deviceVmservicePort}) async {
globals.printTrace('Checking for advertised Dart observatories...'); globals.printTrace('Checking for advertised Dart observatories...');
try { try {
......
...@@ -369,6 +369,17 @@ abstract class FlutterCommand extends Command<void> { ...@@ -369,6 +369,17 @@ abstract class FlutterCommand extends Command<void> {
return null; return null;
} }
void addPublishPort({ bool enabledByDefault = true, bool verboseHelp = false }) {
argParser.addFlag('publish-port',
negatable: true,
hide: !verboseHelp,
help: 'Publish the VM service port over mDNS. Disable to prevent the'
'local network permission app dialog in debug and profile build modes (iOS devices only.)',
defaultsTo: enabledByDefault);
}
bool get disablePortPublication => !boolArg('publish-port');
void usesIpv6Flag() { void usesIpv6Flag() {
argParser.addFlag(ipv6Flag, argParser.addFlag(ipv6Flag,
hide: true, hide: true,
......
...@@ -708,6 +708,11 @@ void main() { ...@@ -708,6 +708,11 @@ void main() {
'--purge-persistent-cache', '--purge-persistent-cache',
() => debuggingOptions.purgePersistentCache, () => debuggingOptions.purgePersistentCache,
); );
testOptionThatDefaultsToFalse(
'--publish-port',
() => !debuggingOptions.disablePortPublication,
);
}); });
}); });
......
...@@ -7,7 +7,6 @@ import 'package:flutter_tools/src/base/platform.dart'; ...@@ -7,7 +7,6 @@ import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/ios/fallback_discovery.dart'; import 'package:flutter_tools/src/ios/fallback_discovery.dart';
import 'package:flutter_tools/src/mdns_discovery.dart';
import 'package:flutter_tools/src/protocol_discovery.dart'; import 'package:flutter_tools/src/protocol_discovery.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
...@@ -19,7 +18,6 @@ import '../../src/mocks.dart'; ...@@ -19,7 +18,6 @@ import '../../src/mocks.dart';
void main() { void main() {
BufferLogger logger; BufferLogger logger;
FallbackDiscovery fallbackDiscovery; FallbackDiscovery fallbackDiscovery;
MockMDnsObservatoryDiscovery mockMDnsObservatoryDiscovery;
MockPrototcolDiscovery mockPrototcolDiscovery; MockPrototcolDiscovery mockPrototcolDiscovery;
MockPortForwarder mockPortForwarder; MockPortForwarder mockPortForwarder;
MockVmService mockVmService; MockVmService mockVmService;
...@@ -30,12 +28,10 @@ void main() { ...@@ -30,12 +28,10 @@ void main() {
outputPreferences: OutputPreferences.test(), outputPreferences: OutputPreferences.test(),
); );
mockVmService = MockVmService(); mockVmService = MockVmService();
mockMDnsObservatoryDiscovery = MockMDnsObservatoryDiscovery();
mockPrototcolDiscovery = MockPrototcolDiscovery(); mockPrototcolDiscovery = MockPrototcolDiscovery();
mockPortForwarder = MockPortForwarder(); mockPortForwarder = MockPortForwarder();
fallbackDiscovery = FallbackDiscovery( fallbackDiscovery = FallbackDiscovery(
logger: logger, logger: logger,
mDnsObservatoryDiscovery: mockMDnsObservatoryDiscovery,
portForwarder: mockPortForwarder, portForwarder: mockPortForwarder,
protocolDiscovery: mockPrototcolDiscovery, protocolDiscovery: mockPrototcolDiscovery,
flutterUsage: Usage.test(), flutterUsage: Usage.test(),
...@@ -94,7 +90,7 @@ void main() { ...@@ -94,7 +90,7 @@ void main() {
), Uri.parse('http://localhost:1')); ), Uri.parse('http://localhost:1'));
}); });
testWithoutContext('Selects mdns discovery if VM service connecton fails due to Sentinel', () async { testWithoutContext('Selects log scanning if VM service connecton fails due to Sentinel', () async {
when(mockVmService.getVM()).thenAnswer((Invocation invocation) async { when(mockVmService.getVM()).thenAnswer((Invocation invocation) async {
return VM.parse(<String, Object>{})..isolates = <IsolateRef>[ return VM.parse(<String, Object>{})..isolates = <IsolateRef>[
IsolateRef( IsolateRef(
...@@ -106,12 +102,7 @@ void main() { ...@@ -106,12 +102,7 @@ void main() {
}); });
when(mockVmService.getIsolate(any)) when(mockVmService.getIsolate(any))
.thenThrow(SentinelException.parse('Something', <String, dynamic>{})); .thenThrow(SentinelException.parse('Something', <String, dynamic>{}));
when(mockMDnsObservatoryDiscovery.getObservatoryUri( when(mockPrototcolDiscovery.uri).thenAnswer((Invocation invocation) async {
'hello',
null, // Device
usesIpv6: false,
hostVmservicePort: 1,
)).thenAnswer((Invocation invocation) async {
return Uri.parse('http://localhost:1234'); return Uri.parse('http://localhost:1234');
}); });
...@@ -125,15 +116,10 @@ void main() { ...@@ -125,15 +116,10 @@ void main() {
), Uri.parse('http://localhost:1234')); ), Uri.parse('http://localhost:1234'));
}); });
testWithoutContext('Selects mdns discovery if VM service connecton fails', () async { testWithoutContext('Selects log scanning if VM service connecton fails', () async {
when(mockVmService.getVM()).thenThrow(Exception()); when(mockVmService.getVM()).thenThrow(Exception());
when(mockMDnsObservatoryDiscovery.getObservatoryUri( when(mockPrototcolDiscovery.uri).thenAnswer((Invocation invocation) async {
'hello',
null, // Device
usesIpv6: false,
hostVmservicePort: 1,
)).thenAnswer((Invocation invocation) async {
return Uri.parse('http://localhost:1234'); return Uri.parse('http://localhost:1234');
}); });
...@@ -147,17 +133,9 @@ void main() { ...@@ -147,17 +133,9 @@ void main() {
), Uri.parse('http://localhost:1234')); ), Uri.parse('http://localhost:1234'));
}); });
testWithoutContext('Selects log scanning if both VM Service and mDNS fails', () async { testWithoutContext('Fails if both VM Service and log scanning fails', () async {
when(mockVmService.getVM()).thenThrow(Exception()); when(mockVmService.getVM()).thenThrow(Exception());
when(mockMDnsObservatoryDiscovery.getObservatoryUri( when(mockPrototcolDiscovery.uri).thenAnswer((Invocation invocation) async => null);
'hello',
null, // Device
usesIpv6: false,
hostVmservicePort: 1,
)).thenThrow(Exception());
when(mockPrototcolDiscovery.uri).thenAnswer((Invocation invocation) async {
return Uri.parse('http://localhost:5678');
});
expect(await fallbackDiscovery.discover( expect(await fallbackDiscovery.discover(
assumedDevicePort: 23, assumedDevicePort: 23,
...@@ -166,11 +144,10 @@ void main() { ...@@ -166,11 +144,10 @@ void main() {
packageId: 'hello', packageId: 'hello',
usesIpv6: false, usesIpv6: false,
packageName: 'hello', packageName: 'hello',
), Uri.parse('http://localhost:5678')); ), isNull);
}); });
} }
class MockMDnsObservatoryDiscovery extends Mock implements MDnsObservatoryDiscovery {}
class MockPrototcolDiscovery extends Mock implements ProtocolDiscovery {} class MockPrototcolDiscovery extends Mock implements ProtocolDiscovery {}
class MockPortForwarder extends Mock implements DevicePortForwarder {} class MockPortForwarder extends Mock implements DevicePortForwarder {}
class MockVmService extends Mock implements VmService {} class MockVmService extends Mock implements VmService {}
...@@ -21,7 +21,6 @@ import 'package:flutter_tools/src/ios/fallback_discovery.dart'; ...@@ -21,7 +21,6 @@ import 'package:flutter_tools/src/ios/fallback_discovery.dart';
import 'package:flutter_tools/src/ios/ios_deploy.dart'; import 'package:flutter_tools/src/ios/ios_deploy.dart';
import 'package:flutter_tools/src/ios/iproxy.dart'; import 'package:flutter_tools/src/ios/iproxy.dart';
import 'package:flutter_tools/src/ios/mac.dart'; import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/mdns_discovery.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:vm_service/vm_service.dart'; import 'package:vm_service/vm_service.dart';
...@@ -123,63 +122,7 @@ void main() { ...@@ -123,63 +122,7 @@ void main() {
verify(devicePortForwarder.dispose()).called(1); verify(devicePortForwarder.dispose()).called(1);
}); });
// Still uses context for analytics and mDNS. // Still uses context for analytics.
testUsingContext('IOSDevice.startApp succeeds in debug mode via mDNS discovery when log reading fails', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
kDeployCommand,
kAttachDebuggerCommand,
]);
final IOSDevice device = setUpIOSDevice(
processManager: processManager,
fileSystem: fileSystem,
vmServiceConnector: (String string, {Log log}) async {
throw const io.SocketException(
'OS Error: Connection refused, errno = 61, address = localhost, port '
'= 58943',
);
},
);
final IOSApp iosApp = PrebuiltIOSApp(
projectBundleId: 'app',
bundleName: 'Runner',
bundleDir: fileSystem.currentDirectory,
);
final Uri uri = Uri(
scheme: 'http',
host: '127.0.0.1',
port: 1234,
path: 'observatory',
);
device.portForwarder = const NoOpDevicePortForwarder();
device.setLogReader(iosApp, FakeDeviceLogReader());
when(MDnsObservatoryDiscovery.instance.getObservatoryUri(
any,
any,
usesIpv6: anyNamed('usesIpv6'),
hostVmservicePort: anyNamed('hostVmservicePort')
)).thenAnswer((Invocation invocation) async => uri);
final LaunchResult launchResult = await device.startApp(iosApp,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
platformArgs: <String, dynamic>{},
fallbackPollingDelay: Duration.zero,
fallbackThrottleTimeout: const Duration(milliseconds: 10),
);
verify(globals.flutterUsage.sendEvent('ios-handshake', 'mdns-success')).called(1);
expect(launchResult.started, true);
expect(launchResult.hasObservatory, true);
expect(await device.stopApp(iosApp), false);
}, overrides: <Type, Generator>{
MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
Usage: () => MockUsage(),
});
// Still uses context for analytics and mDNS.
testUsingContext('IOSDevice.startApp attaches in debug mode via log reading on iOS 13+', () async { testUsingContext('IOSDevice.startApp attaches in debug mode via log reading on iOS 13+', () async {
final FileSystem fileSystem = MemoryFileSystem.test(); final FileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
...@@ -223,14 +166,12 @@ void main() { ...@@ -223,14 +166,12 @@ void main() {
expect(launchResult.started, true); expect(launchResult.started, true);
expect(launchResult.hasObservatory, true); expect(launchResult.hasObservatory, true);
verify(globals.flutterUsage.sendEvent('ios-handshake', 'log-success')).called(1); verify(globals.flutterUsage.sendEvent('ios-handshake', 'log-success')).called(1);
verifyNever(globals.flutterUsage.sendEvent('ios-handshake', 'mdns-failure'));
expect(await device.stopApp(iosApp), false); expect(await device.stopApp(iosApp), false);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
Usage: () => MockUsage(), Usage: () => MockUsage(),
}); });
// Still uses context for analytics and mDNS. // Still uses context for analytics.
testUsingContext('IOSDevice.startApp launches in debug mode via log reading on <iOS 13', () async { testUsingContext('IOSDevice.startApp launches in debug mode via log reading on <iOS 13', () async {
final FileSystem fileSystem = MemoryFileSystem.test(); final FileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
...@@ -275,14 +216,12 @@ void main() { ...@@ -275,14 +216,12 @@ void main() {
expect(launchResult.started, true); expect(launchResult.started, true);
expect(launchResult.hasObservatory, true); expect(launchResult.hasObservatory, true);
verify(globals.flutterUsage.sendEvent('ios-handshake', 'log-success')).called(1); verify(globals.flutterUsage.sendEvent('ios-handshake', 'log-success')).called(1);
verifyNever(globals.flutterUsage.sendEvent('ios-handshake', 'mdns-failure'));
expect(await device.stopApp(iosApp), false); expect(await device.stopApp(iosApp), false);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
Usage: () => MockUsage(), Usage: () => MockUsage(),
}); });
// Still uses context for analytics and mDNS. // Still uses context for analytics.
testUsingContext('IOSDevice.startApp fails in debug mode when Observatory URI is malformed', () async { testUsingContext('IOSDevice.startApp fails in debug mode when Observatory URI is malformed', () async {
final FileSystem fileSystem = MemoryFileSystem.test(); final FileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
...@@ -332,9 +271,7 @@ void main() { ...@@ -332,9 +271,7 @@ void main() {
value: anyNamed('value'), value: anyNamed('value'),
)).called(1); )).called(1);
verify(globals.flutterUsage.sendEvent('ios-handshake', 'log-failure')).called(1); verify(globals.flutterUsage.sendEvent('ios-handshake', 'log-failure')).called(1);
verify(globals.flutterUsage.sendEvent('ios-handshake', 'mdns-failure')).called(1);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
Usage: () => MockUsage(), Usage: () => MockUsage(),
}); });
...@@ -371,7 +308,7 @@ void main() { ...@@ -371,7 +308,7 @@ void main() {
Usage: () => MockUsage(), Usage: () => MockUsage(),
}); });
// Still uses context for analytics and mDNS. // Still uses context for analytics.
testUsingContext('IOSDevice.startApp forwards all supported debugging options', () async { testUsingContext('IOSDevice.startApp forwards all supported debugging options', () async {
final FileSystem fileSystem = MemoryFileSystem.test(); final FileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
...@@ -397,6 +334,7 @@ void main() { ...@@ -397,6 +334,7 @@ void main() {
'--enable-service-port-fallback', '--enable-service-port-fallback',
'--disable-service-auth-codes', '--disable-service-auth-codes',
'--observatory-port=60700', '--observatory-port=60700',
'--disable-observatory-publication',
'--start-paused', '--start-paused',
'--dart-flags="--foo,--null_assertions"', '--dart-flags="--foo,--null_assertions"',
'--enable-checked-mode', '--enable-checked-mode',
...@@ -449,6 +387,7 @@ void main() { ...@@ -449,6 +387,7 @@ void main() {
BuildInfo.debug, BuildInfo.debug,
startPaused: true, startPaused: true,
disableServiceAuthCodes: true, disableServiceAuthCodes: true,
disablePortPublication: true,
dartFlags: '--foo', dartFlags: '--foo',
enableSoftwareRendering: true, enableSoftwareRendering: true,
skiaDeterministicRendering: true, skiaDeterministicRendering: true,
...@@ -470,7 +409,6 @@ void main() { ...@@ -470,7 +409,6 @@ void main() {
expect(await device.stopApp(iosApp), false); expect(await device.stopApp(iosApp), false);
expect(processManager.hasRemainingExpectations, false); expect(processManager.hasRemainingExpectations, false);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
Usage: () => MockUsage(), Usage: () => MockUsage(),
}); });
} }
...@@ -525,6 +463,5 @@ IOSDevice setUpIOSDevice({ ...@@ -525,6 +463,5 @@ IOSDevice setUpIOSDevice({
class MockDevicePortForwarder extends Mock implements DevicePortForwarder {} class MockDevicePortForwarder extends Mock implements DevicePortForwarder {}
class MockDeviceLogReader extends Mock implements DeviceLogReader {} class MockDeviceLogReader extends Mock implements DeviceLogReader {}
class MockUsage extends Mock implements Usage {} class MockUsage extends Mock implements Usage {}
class MockMDnsObservatoryDiscovery extends Mock implements MDnsObservatoryDiscovery {}
class MockVmService extends Mock implements VmService {} class MockVmService extends Mock implements VmService {}
class MockDartDevelopmentService extends Mock implements DartDevelopmentService {} class MockDartDevelopmentService extends Mock implements DartDevelopmentService {}
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