[flutter_tools] refactor iOS tests for Device.startApp into new file (#52854)
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index 6c4613d..88015c1 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -383,7 +383,7 @@
@override
DevicePortForwarder get portForwarder => _portForwarder ??= IOSDevicePortForwarder(
processManager: globals.processManager,
- logger: globals.logger,
+ logger: _logger,
dyLdLibEntry: globals.cache.dyLdLibEntry,
id: id,
iproxyPath: _iproxyPath,
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
index 4f40715..9d27189 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
@@ -30,6 +30,7 @@
import '../../src/common.dart';
import '../../src/context.dart';
+import '../../src/fakes.dart';
import '../../src/mocks.dart';
@@ -54,7 +55,7 @@
const int devicePort = 499;
const int hostPort = 42;
- MockDeviceLogReader mockLogReader;
+ FakeDeviceLogReader mockLogReader;
MockPortForwarder portForwarder;
MockAndroidDevice device;
MockProcessManager mockProcessManager;
@@ -63,7 +64,7 @@
setUp(() {
mockProcessManager = MockProcessManager();
- mockLogReader = MockDeviceLogReader();
+ mockLogReader = FakeDeviceLogReader();
portForwarder = MockPortForwarder();
device = MockAndroidDevice();
vmServiceDoneCompleter = Completer<void>();
@@ -374,7 +375,7 @@
testUsingContext('selects specified target', () async {
const int devicePort = 499;
const int hostPort = 42;
- final MockDeviceLogReader mockLogReader = MockDeviceLogReader();
+ final FakeDeviceLogReader mockLogReader = FakeDeviceLogReader();
final MockPortForwarder portForwarder = MockPortForwarder();
final MockAndroidDevice device = MockAndroidDevice();
final MockHotRunner mockHotRunner = MockHotRunner();
@@ -434,7 +435,7 @@
testUsingContext('fallbacks to protocol observatory if MDNS failed on iOS', () async {
const int devicePort = 499;
const int hostPort = 42;
- final MockDeviceLogReader mockLogReader = MockDeviceLogReader();
+ final FakeDeviceLogReader mockLogReader = FakeDeviceLogReader();
final MockPortForwarder portForwarder = MockPortForwarder();
final MockIOSDevice device = MockIOSDevice();
final MockHotRunner mockHotRunner = MockHotRunner();
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
index 2e04041..d694b5f 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
@@ -21,6 +21,7 @@
import '../../src/common.dart';
import '../../src/context.dart';
+import '../../src/fakes.dart';
import '../../src/mocks.dart';
void main() {
@@ -351,7 +352,7 @@
final Device mockDevice = MockDevice();
testDeviceManager.addDevice(mockDevice);
- final MockDeviceLogReader mockDeviceLogReader = MockDeviceLogReader();
+ final FakeDeviceLogReader mockDeviceLogReader = FakeDeviceLogReader();
when(mockDevice.getLogReader()).thenReturn(mockDeviceLogReader);
final MockLaunchResult mockLaunchResult = MockLaunchResult();
when(mockLaunchResult.started).thenReturn(true);
@@ -481,7 +482,7 @@
final Device mockDevice = MockDevice();
testDeviceManager.addDevice(mockDevice);
- final MockDeviceLogReader mockDeviceLogReader = MockDeviceLogReader();
+ final FakeDeviceLogReader mockDeviceLogReader = FakeDeviceLogReader();
when(mockDevice.getLogReader()).thenReturn(mockDeviceLogReader);
final MockLaunchResult mockLaunchResult = MockLaunchResult();
when(mockLaunchResult.started).thenReturn(true);
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
index aab1f3b..ded8172 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
@@ -32,6 +32,7 @@
import '../../src/common.dart';
import '../../src/context.dart';
+import '../../src/fakes.dart';
import '../../src/mocks.dart';
import '../../src/testbed.dart';
@@ -279,7 +280,7 @@
applyMocksToCommand(command);
final MockDevice mockDevice = MockDevice(TargetPlatform.ios);
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) => Future<bool>.value(false));
- when(mockDevice.getLogReader(app: anyNamed('app'))).thenReturn(MockDeviceLogReader());
+ when(mockDevice.getLogReader(app: anyNamed('app'))).thenReturn(FakeDeviceLogReader());
when(mockDevice.supportsFastStart).thenReturn(true);
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) => Future<String>.value('iOS 13'));
// App fails to start because we're only interested in usage
@@ -633,7 +634,7 @@
@override
DeviceLogReader getLogReader({ ApplicationPackage app }) {
- return MockDeviceLogReader();
+ return FakeDeviceLogReader();
}
@override
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 cf8f386..e454554 100644
--- a/packages/flutter_tools/test/general.shard/ios/devices_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
@@ -36,6 +36,7 @@
import '../../src/common.dart';
import '../../src/context.dart';
+import '../../src/fakes.dart';
import '../../src/mocks.dart';
void main() {
@@ -395,12 +396,10 @@
MockFileSystem mockFileSystem;
MockPlatform mockPlatform;
MockProcessManager mockProcessManager;
- MockDeviceLogReader mockLogReader;
- MockMDnsObservatoryDiscovery mockMDnsObservatoryDiscovery;
+ FakeDeviceLogReader mockLogReader;
MockPortForwarder mockPortForwarder;
MockIMobileDevice mockIMobileDevice;
MockIOSDeploy mockIosDeploy;
- MockUsage mockUsage;
Directory tempDir;
Directory projectDir;
@@ -428,13 +427,11 @@
mockFileSystem = MockFileSystem();
mockPlatform = MockPlatform();
when(mockPlatform.isMacOS).thenReturn(true);
- mockMDnsObservatoryDiscovery = MockMDnsObservatoryDiscovery();
mockProcessManager = MockProcessManager();
- mockLogReader = MockDeviceLogReader();
+ mockLogReader = FakeDeviceLogReader();
mockPortForwarder = MockPortForwarder();
mockIMobileDevice = MockIMobileDevice();
mockIosDeploy = MockIOSDeploy();
- mockUsage = MockUsage();
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_create_test.');
projectDir = tempDir.childDirectory('flutter_project');
@@ -493,367 +490,6 @@
Cache.enableLocking();
});
- testWithoutContext('disposing device disposes the portForwarder', () async {
- final IOSDevice device = IOSDevice(
- '123',
- artifacts: mockArtifacts,
- fileSystem: mockFileSystem,
- platform: macPlatform,
- iosDeploy: iosDeploy,
- logger: logger,
- name: 'iPhone 1',
- sdkVersion: '13.3',
- cpuArchitecture: DarwinArch.arm64,
- );
- device.portForwarder = mockPortForwarder;
- device.setLogReader(mockApp, mockLogReader);
- await device.dispose();
- verify(mockPortForwarder.dispose()).called(1);
- });
-
- testUsingContext('succeeds in debug mode via mDNS', () async {
- final IOSDevice device = IOSDevice(
- '123',
- name: 'iPhone 1',
- sdkVersion: '13.3',
- artifacts: mockArtifacts,
- fileSystem: mockFileSystem,
- logger: logger,
- platform: macPlatform,
- iosDeploy: mockIosDeploy,
- cpuArchitecture: DarwinArch.arm64,
- );
- when(mockIosDeploy.installApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: <String>[],
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- when(mockIosDeploy.runApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- device.portForwarder = mockPortForwarder;
- device.setLogReader(mockApp, mockLogReader);
- final Uri uri = Uri(
- scheme: 'http',
- host: '127.0.0.1',
- port: 1234,
- path: 'observatory',
- );
- when(mockMDnsObservatoryDiscovery.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
- .thenAnswer((Invocation invocation) => Future<Uri>.value(uri));
-
- final LaunchResult launchResult = await device.startApp(mockApp,
- prebuiltApplication: true,
- debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)),
- platformArgs: <String, dynamic>{},
- );
- verify(mockUsage.sendEvent('ios-handshake', 'mdns-success')).called(1);
- expect(launchResult.started, isTrue);
- expect(launchResult.hasObservatory, isTrue);
- expect(await device.stopApp(mockApp), isFalse);
- }, overrides: <Type, Generator>{
- MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
- Usage: () => mockUsage,
- });
-
- testUsingContext('succeeds in debug mode when mDNS fails by falling back to manual protocol discovery', () async {
- final IOSDevice device = IOSDevice(
- '123',
- artifacts: mockArtifacts,
- fileSystem: mockFileSystem,
- logger: logger,
- platform: macPlatform,
- iosDeploy: mockIosDeploy,
- name: 'iPhone 1',
- sdkVersion: '13.3',
- cpuArchitecture: DarwinArch.arm64,
- );
- when(
- mockIosDeploy.installApp(deviceId: device.id, bundlePath: anyNamed('bundlePath'), launchArguments: <String>[])
- ).thenAnswer((Invocation invocation) => Future<int>.value(0));
- when(mockIosDeploy.runApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- device.portForwarder = mockPortForwarder;
- device.setLogReader(mockApp, mockLogReader);
- // Now that the reader is used, start writing messages to it.
- Timer.run(() {
- mockLogReader.addLine('Foo');
- mockLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort');
- });
- when(mockMDnsObservatoryDiscovery.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
- .thenAnswer((Invocation invocation) => Future<Uri>.value(null));
-
- final LaunchResult launchResult = await device.startApp(mockApp,
- prebuiltApplication: true,
- debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)),
- platformArgs: <String, dynamic>{},
- );
- expect(launchResult.started, isTrue);
- expect(launchResult.hasObservatory, isTrue);
- verify(mockUsage.sendEvent('ios-handshake', 'mdns-failure')).called(1);
- verify(mockUsage.sendEvent('ios-handshake', 'fallback-success')).called(1);
- expect(await device.stopApp(mockApp), isFalse);
- }, overrides: <Type, Generator>{
- FileSystem: () => mockFileSystem,
- MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
- ProcessManager: () => mockProcessManager,
- Usage: () => mockUsage,
- });
-
- testUsingContext('fails in debug mode when mDNS fails and when Observatory URI is malformed', () async {
- final IOSDevice device = IOSDevice(
- '123',
- artifacts: mockArtifacts,
- fileSystem: mockFileSystem,
- logger: logger,
- platform: macPlatform,
- iosDeploy: mockIosDeploy,
- name: 'iPhone 1',
- sdkVersion: '13.3',
- cpuArchitecture: DarwinArch.arm64,
- );
- when(mockIosDeploy.installApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: <String>[],
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- when(mockIosDeploy.runApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- device.portForwarder = mockPortForwarder;
- device.setLogReader(mockApp, mockLogReader);
-
- // Now that the reader is used, start writing messages to it.
- Timer.run(() {
- mockLogReader.addLine('Foo');
- mockLogReader.addLine('Observatory listening on http:/:/127.0.0.1:$devicePort');
- });
- when(mockMDnsObservatoryDiscovery.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
- .thenAnswer((Invocation invocation) => Future<Uri>.value(null));
-
- final LaunchResult launchResult = await device.startApp(mockApp,
- prebuiltApplication: true,
- debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)),
- platformArgs: <String, dynamic>{},
- );
- expect(launchResult.started, isFalse);
- expect(launchResult.hasObservatory, isFalse);
- verify(mockUsage.sendEvent(
- 'ios-handshake',
- 'failure-other',
- label: anyNamed('label'),
- value: anyNamed('value'),
- )).called(1);
- verify(mockUsage.sendEvent('ios-handshake', 'mdns-failure')).called(1);
- verify(mockUsage.sendEvent('ios-handshake', 'fallback-failure')).called(1);
- }, overrides: <Type, Generator>{
- FileSystem: () => mockFileSystem,
- MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
- ProcessManager: () => mockProcessManager,
- Usage: () => mockUsage,
- });
-
- testUsingContext('succeeds in release mode', () async {
- final IOSDevice device = IOSDevice(
- '123',
- name: 'iPhone 1',
- fileSystem: mockFileSystem,
- sdkVersion: '13.3',
- cpuArchitecture: DarwinArch.arm64,
- logger: logger,
- platform: mockPlatform,
- artifacts: mockArtifacts,
- iosDeploy: mockIosDeploy,
- );
- when(mockIosDeploy.installApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: <String>[],
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- when(mockIosDeploy.runApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- final LaunchResult launchResult = await device.startApp(mockApp,
- prebuiltApplication: true,
- debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null, treeShakeIcons: false)),
- platformArgs: <String, dynamic>{},
- );
- verify(mockIosDeploy.installApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: <String>[],
- ));
- verify(mockIosDeploy.runApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- ));
- expect(launchResult.started, isTrue);
- expect(launchResult.hasObservatory, isFalse);
- expect(await device.stopApp(mockApp), isFalse);
- });
-
- testUsingContext('trace whitelist flags', () async {
- final IOSDevice device = IOSDevice(
- '123',
- name: 'iPhone 1',
- fileSystem: mockFileSystem,
- sdkVersion: '13.3',
- cpuArchitecture: DarwinArch.arm64,
- logger: logger,
- platform: mockPlatform,
- artifacts: mockArtifacts,
- iosDeploy: mockIosDeploy,
- );
- when(mockIosDeploy.installApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: <String>[],
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- when(mockIosDeploy.runApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- await device.startApp(mockApp,
- prebuiltApplication: true,
- debuggingOptions: DebuggingOptions.disabled(
- const BuildInfo(BuildMode.release, null, treeShakeIcons: false),
- traceWhitelist: 'foo'),
- platformArgs: <String, dynamic>{},
- );
- final VerificationResult toVerify = verify(mockIosDeploy.runApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: captureAnyNamed('launchArguments'),
- ));
- expect(toVerify.captured[0], contains('--trace-whitelist="foo"'));
- await device.stopApp(mockApp);
- });
-
- testUsingContext('succeeds with --cache-sksl', () async {
- final IOSDevice device = IOSDevice(
- '123',
- name: 'iPhone 1',
- sdkVersion: '13.3',
- artifacts: mockArtifacts,
- fileSystem: mockFileSystem,
- logger: logger,
- platform: macPlatform,
- iosDeploy: mockIosDeploy,
- cpuArchitecture: DarwinArch.arm64,
- );
- device.setLogReader(mockApp, mockLogReader);
- final Uri uri = Uri(
- scheme: 'http',
- host: '127.0.0.1',
- port: 1234,
- path: 'observatory',
- );
- when(mockMDnsObservatoryDiscovery.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
- .thenAnswer((Invocation invocation) => Future<Uri>.value(uri));
-
- List<String> args;
- when(mockIosDeploy.runApp(
- deviceId: anyNamed('deviceId'),
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation inv) {
- args = inv.namedArguments[const Symbol('launchArguments')] as List<String>;
- return Future<int>.value(0);
- });
- when(mockIosDeploy.installApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
-
- final LaunchResult launchResult = await device.startApp(mockApp,
- prebuiltApplication: true,
- debuggingOptions: DebuggingOptions.enabled(
- const BuildInfo(BuildMode.debug, null, treeShakeIcons: false),
- cacheSkSL: true,
- ),
- platformArgs: <String, dynamic>{},
- );
- expect(launchResult.started, isTrue);
- expect(args, contains('--cache-sksl'));
- expect(await device.stopApp(mockApp), isFalse);
- }, overrides: <Type, Generator>{
- Artifacts: () => mockArtifacts,
- Cache: () => mockCache,
- FileSystem: () => mockFileSystem,
- MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
- Platform: () => macPlatform,
- ProcessManager: () => mockProcessManager,
- Usage: () => mockUsage,
- IOSDeploy: () => mockIosDeploy,
- });
-
- testUsingContext('succeeds with --device-vmservice-port', () async {
- final IOSDevice device = IOSDevice(
- '123',
- name: 'iPhone 1',
- sdkVersion: '13.3',
- artifacts: mockArtifacts,
- fileSystem: mockFileSystem,
- logger: logger,
- platform: macPlatform,
- iosDeploy: mockIosDeploy,
- cpuArchitecture: DarwinArch.arm64,
- );
- device.setLogReader(mockApp, mockLogReader);
- final Uri uri = Uri(
- scheme: 'http',
- host: '127.0.0.1',
- port: 1234,
- path: 'observatory',
- );
- when(mockMDnsObservatoryDiscovery.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
- .thenAnswer((Invocation invocation) => Future<Uri>.value(uri));
-
- List<String> args;
- when(mockIosDeploy.runApp(
- deviceId: anyNamed('deviceId'),
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation inv) {
- args = inv.namedArguments[const Symbol('launchArguments')] as List<String>;
- return Future<int>.value(0);
- });
-
- when(mockIosDeploy.installApp(
- deviceId: device.id,
- bundlePath: anyNamed('bundlePath'),
- launchArguments: anyNamed('launchArguments'),
- )).thenAnswer((Invocation invocation) => Future<int>.value(0));
- final LaunchResult launchResult = await device.startApp(mockApp,
- prebuiltApplication: true,
- debuggingOptions: DebuggingOptions.enabled(
- const BuildInfo(BuildMode.debug, null, treeShakeIcons: false),
- deviceVmServicePort: 8181,
- ),
- platformArgs: <String, dynamic>{},
- );
- expect(launchResult.started, isTrue);
- expect(args, contains('--observatory-port=8181'));
- expect(await device.stopApp(mockApp), isFalse);
- }, overrides: <Type, Generator>{
- Cache: () => mockCache,
- MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
- ProcessManager: () => mockProcessManager,
- Usage: () => mockUsage,
- });
-
void testNonPrebuilt(
String name, {
@required bool showBuildSettingsFlakes,
diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart
new file mode 100644
index 0000000..826e0a9
--- /dev/null
+++ b/packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart
@@ -0,0 +1,402 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:file/memory.dart';
+import 'package:flutter_tools/src/application_package.dart';
+import 'package:flutter_tools/src/artifacts.dart';
+import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/base/logger.dart';
+import 'package:flutter_tools/src/build_info.dart';
+import 'package:flutter_tools/src/cache.dart';
+import 'package:flutter_tools/src/device.dart';
+import 'package:flutter_tools/src/ios/devices.dart';
+import 'package:flutter_tools/src/ios/ios_deploy.dart';
+import 'package:flutter_tools/src/mdns_discovery.dart';
+import 'package:flutter_tools/src/reporting/reporting.dart';
+import 'package:mockito/mockito.dart';
+import 'package:platform/platform.dart';
+import 'package:flutter_tools/src/globals.dart' as globals;
+
+import '../../src/common.dart';
+import '../../src/context.dart';
+import '../../src/fakes.dart';
+
+const FakeCommand kDeployCommand = FakeCommand(
+ command: <String>[
+ 'ios-deploy',
+ '--id',
+ '123',
+ '--bundle',
+ '/',
+ '--no-wifi',
+ ],
+ environment: <String, String>{
+ 'PATH': '/usr/bin:null',
+ 'DYLD_LIBRARY_PATH': '/path/to/libraries',
+ }
+);
+
+// The command used to actually launch the app with args in release/profile.
+const FakeCommand kLaunchReleaseCommand = FakeCommand(
+ command: <String>[
+ 'ios-deploy',
+ '--id',
+ '123',
+ '--bundle',
+ '/',
+ '--no-wifi',
+ '--justlaunch',
+ // These args are the default on DebuggingOptions.
+ '--args',
+ '--enable-dart-profiling --enable-service-port-fallback --disable-service-auth-codes --observatory-port=60700',
+ ],
+ environment: <String, String>{
+ 'PATH': '/usr/bin:null',
+ 'DYLD_LIBRARY_PATH': '/path/to/libraries',
+ }
+);
+
+// The command used to actually launch the app with args in debug.
+const FakeCommand kLaunchDebugCommand = FakeCommand(command: <String>[
+ 'ios-deploy',
+ '--id',
+ '123',
+ '--bundle',
+ '/',
+ '--no-wifi',
+ '--justlaunch',
+ '--args',
+ '--enable-dart-profiling --enable-service-port-fallback --disable-service-auth-codes --observatory-port=60700 --enable-checked-mode --verify-entry-points'
+], environment: <String, String>{
+ 'PATH': '/usr/bin:null',
+ 'DYLD_LIBRARY_PATH': '/path/to/libraries',
+});
+
+void main() {
+ // TODO(jonahwilliams): This test doesn't really belong here but
+ // I don't have a better place for it for now.
+ testWithoutContext('disposing device disposes the portForwarder and logReader', () async {
+ final IOSDevice device = setUpIOSDevice();
+ final DevicePortForwarder devicePortForwarder = MockDevicePortForwarder();
+ final DeviceLogReader deviceLogReader = MockDeviceLogReader();
+ final IOSApp iosApp = PrebuiltIOSApp(
+ projectBundleId: 'app',
+ bundleName: 'Runner',
+ );
+
+ device.portForwarder = devicePortForwarder;
+ device.setLogReader(iosApp, deviceLogReader);
+ await device.dispose();
+
+ verify(deviceLogReader.dispose()).called(1);
+ verify(devicePortForwarder.dispose()).called(1);
+ });
+
+ // Still uses context for analytics and mDNS.
+ testUsingContext('IOSDevice.startApp succeeds in debug mode via mDNS discovery', () async {
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
+ kDeployCommand,
+ kLaunchDebugCommand,
+ ]);
+ final IOSDevice device = setUpIOSDevice(
+ processManager: processManager,
+ fileSystem: fileSystem,
+ );
+ 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')))
+ .thenAnswer((Invocation invocation) async => uri);
+
+ final LaunchResult launchResult = await device.startApp(iosApp,
+ prebuiltApplication: true,
+ debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
+ platformArgs: <String, dynamic>{},
+ );
+
+ 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 succeeds in debug mode when mDNS fails', () async {
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
+ kDeployCommand,
+ kLaunchDebugCommand,
+ ]);
+ final IOSDevice device = setUpIOSDevice(
+ processManager: processManager,
+ fileSystem: fileSystem,
+ );
+ final IOSApp iosApp = PrebuiltIOSApp(
+ projectBundleId: 'app',
+ bundleName: 'Runner',
+ bundleDir: fileSystem.currentDirectory,
+ );
+ final FakeDeviceLogReader deviceLogReader = FakeDeviceLogReader();
+
+ device.portForwarder = const NoOpDevicePortForwarder();
+ device.setLogReader(iosApp, deviceLogReader);
+
+ // Now that the reader is used, start writing messages to it.
+ Timer.run(() {
+ deviceLogReader.addLine('Foo');
+ deviceLogReader.addLine('Observatory listening on http://127.0.0.1:456');
+ });
+ when(MDnsObservatoryDiscovery.instance.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
+ .thenAnswer((Invocation invocation) async => null);
+
+ final LaunchResult launchResult = await device.startApp(iosApp,
+ prebuiltApplication: true,
+ debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
+ platformArgs: <String, dynamic>{},
+ );
+
+ expect(launchResult.started, true);
+ expect(launchResult.hasObservatory, true);
+ verify(globals.flutterUsage.sendEvent('ios-handshake', 'mdns-failure')).called(1);
+ verify(globals.flutterUsage.sendEvent('ios-handshake', 'fallback-success')).called(1);
+ expect(await device.stopApp(iosApp), false);
+ }, overrides: <Type, Generator>{
+ Usage: () => MockUsage(),
+ MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
+ });
+
+ // Still uses context for analytics and mDNS.
+ testUsingContext('IOSDevice.startApp fails in debug mode when mDNS fails and '
+ 'when Observatory URI is malformed', () async {
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
+ kDeployCommand,
+ kLaunchDebugCommand,
+ ]);
+ final IOSDevice device = setUpIOSDevice(
+ processManager: processManager,
+ fileSystem: fileSystem,
+ );
+ final IOSApp iosApp = PrebuiltIOSApp(
+ projectBundleId: 'app',
+ bundleName: 'Runner',
+ bundleDir: fileSystem.currentDirectory,
+ );
+ final FakeDeviceLogReader deviceLogReader = FakeDeviceLogReader();
+
+ device.portForwarder = const NoOpDevicePortForwarder();
+ device.setLogReader(iosApp, deviceLogReader);
+
+ // Now that the reader is used, start writing messages to it.
+ Timer.run(() {
+ deviceLogReader.addLine('Foo');
+ deviceLogReader.addLine('Observatory listening on http:/:/127.0.0.1:456');
+ });
+ when(MDnsObservatoryDiscovery.instance.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
+ .thenAnswer((Invocation invocation) async => null);
+
+ final LaunchResult launchResult = await device.startApp(iosApp,
+ prebuiltApplication: true,
+ debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
+ platformArgs: <String, dynamic>{},
+ );
+
+ expect(launchResult.started, false);
+ expect(launchResult.hasObservatory, false);
+ verify(globals.flutterUsage.sendEvent(
+ 'ios-handshake',
+ 'failure-other',
+ label: anyNamed('label'),
+ value: anyNamed('value'),
+ )).called(1);
+ verify(globals.flutterUsage.sendEvent('ios-handshake', 'mdns-failure')).called(1);
+ verify(globals.flutterUsage.sendEvent('ios-handshake', 'fallback-failure')).called(1);
+ }, overrides: <Type, Generator>{
+ MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
+ Usage: () => MockUsage(),
+ });
+
+ // Still uses context for TimeoutConfiguration and usage
+ testUsingContext('IOSDevice.startApp succeeds in release mode', () async {
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
+ kDeployCommand,
+ kLaunchReleaseCommand,
+ ]);
+ final IOSDevice device = setUpIOSDevice(
+ processManager: processManager,
+ fileSystem: fileSystem,
+ );
+ final IOSApp iosApp = PrebuiltIOSApp(
+ projectBundleId: 'app',
+ bundleName: 'Runner',
+ bundleDir: fileSystem.currentDirectory,
+ );
+
+ final LaunchResult launchResult = await device.startApp(iosApp,
+ prebuiltApplication: true,
+ debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
+ platformArgs: <String, dynamic>{},
+ );
+
+ expect(launchResult.started, true);
+ expect(launchResult.hasObservatory, false);
+ expect(await device.stopApp(iosApp), false);
+ expect(processManager.hasRemainingExpectations, false);
+ }, overrides: <Type, Generator>{
+ Usage: () => MockUsage(),
+ });
+
+ // Still uses context for analytics and mDNS.
+ testUsingContext('IOSDevice.startApp forwards all supported debugging options', () async {
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
+ kDeployCommand,
+ FakeCommand(
+ command: <String>[
+ 'ios-deploy',
+ '--id',
+ '123',
+ '--bundle',
+ '/',
+ '--no-wifi',
+ '--justlaunch',
+ // The arguments below are determined by what is passed into
+ // the debugging options argument to startApp.
+ '--args',
+ <String>[
+ '--enable-dart-profiling',
+ '--enable-service-port-fallback',
+ '--disable-service-auth-codes',
+ '--observatory-port=60700',
+ '--start-paused',
+ '--dart-flags="--foo"',
+ '--enable-checked-mode',
+ '--verify-entry-points',
+ '--enable-software-rendering',
+ '--skia-deterministic-rendering',
+ '--trace-skia',
+ '--endless-trace-buffer',
+ '--dump-skp-on-shader-compilation',
+ '--verbose-logging',
+ '--cache-sksl',
+ ].join(' '),
+ ], environment: const <String, String>{
+ 'PATH': '/usr/bin:null',
+ 'DYLD_LIBRARY_PATH': '/path/to/libraries',
+ }
+ )
+ ]);
+ final IOSDevice device = setUpIOSDevice(
+ sdkVersion: '13.3',
+ processManager: processManager,
+ fileSystem: fileSystem,
+ );
+ 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.setLogReader(iosApp, FakeDeviceLogReader());
+ device.portForwarder = const NoOpDevicePortForwarder();
+
+ when(MDnsObservatoryDiscovery.instance.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
+ .thenAnswer((Invocation invocation) async => uri);
+
+ final LaunchResult launchResult = await device.startApp(iosApp,
+ prebuiltApplication: true,
+ debuggingOptions: DebuggingOptions.enabled(
+ BuildInfo.debug,
+ startPaused: true,
+ disableServiceAuthCodes: true,
+ dartFlags: '--foo',
+ enableSoftwareRendering: true,
+ skiaDeterministicRendering: true,
+ traceSkia: true,
+ traceSystrace: true,
+ endlessTraceBuffer: true,
+ dumpSkpOnShaderCompilation: true,
+ cacheSkSL: true,
+ verboseSystemLogs: true,
+ ),
+ platformArgs: <String, dynamic>{},
+ );
+
+ expect(launchResult.started, true);
+ expect(await device.stopApp(iosApp), false);
+ expect(processManager.hasRemainingExpectations, false);
+ }, overrides: <Type, Generator>{
+ MDnsObservatoryDiscovery: () => MockMDnsObservatoryDiscovery(),
+ Usage: () => MockUsage(),
+ });
+}
+
+IOSDevice setUpIOSDevice({
+ String sdkVersion = '13.0.1',
+ FileSystem fileSystem,
+ Logger logger,
+ ProcessManager processManager,
+}) {
+ const MapEntry<String, String> dyldLibraryEntry = MapEntry<String, String>(
+ 'DYLD_LIBRARY_PATH',
+ '/path/to/libraries',
+ );
+ final MockCache cache = MockCache();
+ final MockArtifacts artifacts = MockArtifacts();
+ final FakePlatform macPlatform = FakePlatform(
+ operatingSystem: 'macos',
+ environment: <String, String>{},
+ );
+ when(cache.dyLdLibEntry).thenReturn(dyldLibraryEntry);
+ when(artifacts.getArtifactPath(Artifact.iosDeploy, platform: anyNamed('platform')))
+ .thenReturn('ios-deploy');
+ return IOSDevice('123',
+ name: 'iPhone 1',
+ sdkVersion: sdkVersion,
+ fileSystem: fileSystem ?? MemoryFileSystem.test(),
+ platform: macPlatform,
+ artifacts: artifacts,
+ logger: BufferLogger.test(),
+ iosDeploy: IOSDeploy(
+ logger: logger ?? BufferLogger.test(),
+ platform: macPlatform,
+ processManager: processManager ?? FakeProcessManager.any(),
+ artifacts: artifacts,
+ cache: cache,
+ ),
+ cpuArchitecture: DarwinArch.arm64,
+ );
+}
+
+class MockDevicePortForwarder extends Mock implements DevicePortForwarder {}
+class MockDeviceLogReader extends Mock implements DeviceLogReader {}
+class MockUsage extends Mock implements Usage {}
+class MockMDnsObservatoryDiscovery extends Mock implements MDnsObservatoryDiscovery {}
+class MockArtifacts extends Mock implements Artifacts {}
+class MockCache extends Mock implements Cache {}
diff --git a/packages/flutter_tools/test/general.shard/protocol_discovery_test.dart b/packages/flutter_tools/test/general.shard/protocol_discovery_test.dart
index 983af77..70811d1 100644
--- a/packages/flutter_tools/test/general.shard/protocol_discovery_test.dart
+++ b/packages/flutter_tools/test/general.shard/protocol_discovery_test.dart
@@ -10,11 +10,11 @@
import '../src/common.dart';
import '../src/context.dart';
-import '../src/mocks.dart';
+import '../src/fakes.dart';
void main() {
group('service_protocol discovery', () {
- MockDeviceLogReader logReader;
+ FakeDeviceLogReader logReader;
ProtocolDiscovery discoverer;
/// Performs test set-up functionality that must be performed as part of
@@ -37,7 +37,7 @@
int devicePort,
Duration throttleDuration = const Duration(milliseconds: 200),
}) {
- logReader = MockDeviceLogReader();
+ logReader = FakeDeviceLogReader();
discoverer = ProtocolDiscovery.observatory(
logReader,
ipv6: false,
@@ -261,7 +261,7 @@
group('port forwarding', () {
testUsingContext('default port', () async {
- final MockDeviceLogReader logReader = MockDeviceLogReader();
+ final FakeDeviceLogReader logReader = FakeDeviceLogReader();
final ProtocolDiscovery discoverer = ProtocolDiscovery.observatory(
logReader,
portForwarder: MockPortForwarder(99),
@@ -282,7 +282,7 @@
});
testUsingContext('specified port', () async {
- final MockDeviceLogReader logReader = MockDeviceLogReader();
+ final FakeDeviceLogReader logReader = FakeDeviceLogReader();
final ProtocolDiscovery discoverer = ProtocolDiscovery.observatory(
logReader,
portForwarder: MockPortForwarder(99),
@@ -303,7 +303,7 @@
});
testUsingContext('specified port zero', () async {
- final MockDeviceLogReader logReader = MockDeviceLogReader();
+ final FakeDeviceLogReader logReader = FakeDeviceLogReader();
final ProtocolDiscovery discoverer = ProtocolDiscovery.observatory(
logReader,
portForwarder: MockPortForwarder(99),
@@ -324,7 +324,7 @@
});
testUsingContext('ipv6', () async {
- final MockDeviceLogReader logReader = MockDeviceLogReader();
+ final FakeDeviceLogReader logReader = FakeDeviceLogReader();
final ProtocolDiscovery discoverer = ProtocolDiscovery.observatory(
logReader,
portForwarder: MockPortForwarder(99),
@@ -345,7 +345,7 @@
});
testUsingContext('ipv6 with Ascii Escape code', () async {
- final MockDeviceLogReader logReader = MockDeviceLogReader();
+ final FakeDeviceLogReader logReader = FakeDeviceLogReader();
final ProtocolDiscovery discoverer = ProtocolDiscovery.observatory(
logReader,
portForwarder: MockPortForwarder(99),
diff --git a/packages/flutter_tools/test/src/fake_process_manager.dart b/packages/flutter_tools/test/src/fake_process_manager.dart
index a0cebc4..a911c8e 100644
--- a/packages/flutter_tools/test/src/fake_process_manager.dart
+++ b/packages/flutter_tools/test/src/fake_process_manager.dart
@@ -82,39 +82,14 @@
/// resolves.
final Completer<void> completer;
- static bool _listEquals<T>(List<T> a, List<T> b) {
- if (a == null) {
- return b == null;
- }
- if (b == null || a.length != b.length) {
- return false;
- }
- for (int index = 0; index < a.length; index += 1) {
- if (a[index] != b[index]) {
- return false;
- }
- }
- return true;
- }
-
- bool _matches(List<String> command, String workingDirectory, Map<String, String> environment) {
- if (!_listEquals(command, this.command)) {
- return false;
- }
- if (this.workingDirectory != null && workingDirectory != this.workingDirectory) {
- return false;
+ void _matches(List<String> command, String workingDirectory, Map<String, String> environment) {
+ expect(command, equals(this.command));
+ if (this.workingDirectory != null) {
+ expect(this.workingDirectory, workingDirectory);
}
if (this.environment != null) {
- if (environment == null) {
- return false;
- }
- for (final String key in environment.keys) {
- if (environment[key] != this.environment[key]) {
- return false;
- }
- }
+ expect(this.environment, environment);
}
- return true;
}
}
@@ -322,12 +297,7 @@
reason: 'ProcessManager was told to execute $command (in $workingDirectory) '
'but the FakeProcessManager.list expected no more processes.'
);
- expect(_commands.first._matches(command, workingDirectory, environment), isTrue,
- reason: 'ProcessManager was told to execute $command '
- '(in $workingDirectory, with environment $environment) '
- 'but the next process that was expected was ${_commands.first.command} '
- '(in ${_commands.first.workingDirectory}, with environment ${_commands.first.environment})}.'
- );
+ _commands.first._matches(command, workingDirectory, environment);
return _commands.removeAt(0);
}
diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart
new file mode 100644
index 0000000..b2cc65e
--- /dev/null
+++ b/packages/flutter_tools/test/src/fakes.dart
@@ -0,0 +1,42 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:flutter_tools/src/device.dart';
+
+/// A fake implementation of the [DeviceLogReader].
+class FakeDeviceLogReader extends DeviceLogReader {
+ @override
+ String get name => 'FakeLogReader';
+
+ StreamController<String> _cachedLinesController;
+
+ final List<String> _lineQueue = <String>[];
+ StreamController<String> get _linesController {
+ _cachedLinesController ??= StreamController<String>
+ .broadcast(onListen: () {
+ _lineQueue.forEach(_linesController.add);
+ _lineQueue.clear();
+ });
+ return _cachedLinesController;
+ }
+
+ @override
+ Stream<String> get logLines => _linesController.stream;
+
+ void addLine(String line) {
+ if (_linesController.hasListener) {
+ _linesController.add(line);
+ } else {
+ _lineQueue.add(line);
+ }
+ }
+
+ @override
+ Future<void> dispose() async {
+ _lineQueue.clear();
+ await _linesController.close();
+ }
+}
diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart
index 47808de..006b6b9 100644
--- a/packages/flutter_tools/test/src/mocks.dart
+++ b/packages/flutter_tools/test/src/mocks.dart
@@ -612,40 +612,6 @@
bool isSupportedForProject(FlutterProject flutterProject) => true;
}
-class MockDeviceLogReader extends DeviceLogReader {
- @override
- String get name => 'MockLogReader';
-
- StreamController<String> _cachedLinesController;
-
- final List<String> _lineQueue = <String>[];
- StreamController<String> get _linesController {
- _cachedLinesController ??= StreamController<String>
- .broadcast(onListen: () {
- _lineQueue.forEach(_linesController.add);
- _lineQueue.clear();
- });
- return _cachedLinesController;
- }
-
- @override
- Stream<String> get logLines => _linesController.stream;
-
- void addLine(String line) {
- if (_linesController.hasListener) {
- _linesController.add(line);
- } else {
- _lineQueue.add(line);
- }
- }
-
- @override
- Future<void> dispose() async {
- _lineQueue.clear();
- await _linesController.close();
- }
-}
-
void applyMocksToCommand(FlutterCommand command) {
command.applicationPackages = MockApplicationPackageStore();
}