mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
635 lines
21 KiB
Dart
635 lines
21 KiB
Dart
// 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 'dart:io' as io;
|
|
|
|
import 'package:file/file.dart';
|
|
import 'package:file/memory.dart';
|
|
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';
|
|
import 'package:flutter_tools/src/device.dart';
|
|
import 'package:flutter_tools/src/device_port_forwarder.dart';
|
|
import 'package:flutter_tools/src/ios/application_package.dart';
|
|
import 'package:flutter_tools/src/ios/devices.dart';
|
|
import 'package:flutter_tools/src/ios/ios_deploy.dart';
|
|
import 'package:flutter_tools/src/ios/ios_workflow.dart';
|
|
import 'package:flutter_tools/src/ios/iproxy.dart';
|
|
import 'package:flutter_tools/src/ios/mac.dart';
|
|
import 'package:flutter_tools/src/macos/xcdevice.dart';
|
|
import 'package:test/fake.dart';
|
|
|
|
import '../../src/common.dart';
|
|
import '../../src/fake_process_manager.dart';
|
|
|
|
void main() {
|
|
final FakePlatform macPlatform = FakePlatform(operatingSystem: 'macos');
|
|
final FakePlatform linuxPlatform = FakePlatform();
|
|
final FakePlatform windowsPlatform = FakePlatform(operatingSystem: 'windows');
|
|
|
|
group('IOSDevice', () {
|
|
final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform];
|
|
late Cache cache;
|
|
late Logger logger;
|
|
late IOSDeploy iosDeploy;
|
|
late IMobileDevice iMobileDevice;
|
|
late FileSystem fileSystem;
|
|
|
|
setUp(() {
|
|
final Artifacts artifacts = Artifacts.test();
|
|
cache = Cache.test(processManager: FakeProcessManager.any());
|
|
logger = BufferLogger.test();
|
|
fileSystem = MemoryFileSystem.test();
|
|
iosDeploy = IOSDeploy(
|
|
artifacts: artifacts,
|
|
cache: cache,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
processManager: FakeProcessManager.any(),
|
|
);
|
|
iMobileDevice = IMobileDevice(
|
|
artifacts: artifacts,
|
|
cache: cache,
|
|
logger: logger,
|
|
processManager: FakeProcessManager.any(),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('successfully instantiates on Mac OS', () {
|
|
final IOSDevice device = IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
sdkVersion: '13.3',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
expect(device.isSupported(), isTrue);
|
|
});
|
|
|
|
testWithoutContext('32-bit devices are unsupported', () {
|
|
final IOSDevice device = IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
cpuArchitecture: DarwinArch.armv7,
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
expect(device.isSupported(), isFalse);
|
|
});
|
|
|
|
testWithoutContext('parses major version', () {
|
|
expect(IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
sdkVersion: '1.0.0',
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
).majorSdkVersion, 1);
|
|
expect(IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
sdkVersion: '13.1.1',
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
).majorSdkVersion, 13);
|
|
expect(IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
sdkVersion: '10',
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
).majorSdkVersion, 10);
|
|
expect(IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
sdkVersion: '0',
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
).majorSdkVersion, 0);
|
|
expect(IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
sdkVersion: 'bogus',
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
).majorSdkVersion, 0);
|
|
});
|
|
|
|
testWithoutContext('has build number in sdkNameAndVersion', () async {
|
|
final IOSDevice device = IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
sdkVersion: '13.3 17C54',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
|
|
expect(await device.sdkNameAndVersion,'iOS 13.3 17C54');
|
|
});
|
|
|
|
testWithoutContext('Supports debug, profile, and release modes', () {
|
|
final IOSDevice device = IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
sdkVersion: '13.3',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
|
|
expect(device.supportsRuntimeMode(BuildMode.debug), true);
|
|
expect(device.supportsRuntimeMode(BuildMode.profile), true);
|
|
expect(device.supportsRuntimeMode(BuildMode.release), true);
|
|
expect(device.supportsRuntimeMode(BuildMode.jitRelease), false);
|
|
});
|
|
|
|
for (final Platform platform in unsupportedPlatforms) {
|
|
testWithoutContext('throws UnsupportedError exception if instantiated on ${platform.operatingSystem}', () {
|
|
expect(
|
|
() {
|
|
IOSDevice(
|
|
'device-123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: platform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
sdkVersion: '13.3',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
},
|
|
throwsAssertionError,
|
|
);
|
|
});
|
|
}
|
|
|
|
group('.dispose()', () {
|
|
late IOSDevice device;
|
|
late FakeIOSApp appPackage1;
|
|
late FakeIOSApp appPackage2;
|
|
late IOSDeviceLogReader logReader1;
|
|
late IOSDeviceLogReader logReader2;
|
|
late FakeProcess process1;
|
|
late FakeProcess process2;
|
|
late FakeProcess process3;
|
|
late IOSDevicePortForwarder portForwarder;
|
|
late ForwardedPort forwardedPort;
|
|
late Cache cache;
|
|
late Logger logger;
|
|
late IOSDeploy iosDeploy;
|
|
late FileSystem fileSystem;
|
|
late IProxy iproxy;
|
|
|
|
IOSDevicePortForwarder createPortForwarder(
|
|
ForwardedPort forwardedPort,
|
|
IOSDevice device) {
|
|
iproxy = IProxy.test(logger: logger, processManager: FakeProcessManager.any());
|
|
final IOSDevicePortForwarder portForwarder = IOSDevicePortForwarder(
|
|
id: device.id,
|
|
logger: logger,
|
|
operatingSystemUtils: OperatingSystemUtils(
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: FakePlatform(operatingSystem: 'macos'),
|
|
processManager: FakeProcessManager.any(),
|
|
),
|
|
iproxy: iproxy,
|
|
);
|
|
portForwarder.addForwardedPorts(<ForwardedPort>[forwardedPort]);
|
|
return portForwarder;
|
|
}
|
|
|
|
IOSDeviceLogReader createLogReader(
|
|
IOSDevice device,
|
|
IOSApp appPackage,
|
|
Process process) {
|
|
final IOSDeviceLogReader logReader = IOSDeviceLogReader.create(
|
|
device: device,
|
|
app: appPackage,
|
|
iMobileDevice: IMobileDevice.test(processManager: FakeProcessManager.any()),
|
|
);
|
|
logReader.idevicesyslogProcess = process;
|
|
return logReader;
|
|
}
|
|
|
|
setUp(() {
|
|
appPackage1 = FakeIOSApp('flutterApp1');
|
|
appPackage2 = FakeIOSApp('flutterApp2');
|
|
process1 = FakeProcess();
|
|
process2 = FakeProcess();
|
|
process3 = FakeProcess();
|
|
forwardedPort = ForwardedPort.withContext(123, 456, process3);
|
|
cache = Cache.test(
|
|
processManager: FakeProcessManager.any(),
|
|
);
|
|
fileSystem = MemoryFileSystem.test();
|
|
logger = BufferLogger.test();
|
|
iosDeploy = IOSDeploy(
|
|
artifacts: Artifacts.test(),
|
|
cache: cache,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
processManager: FakeProcessManager.any(),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('kills all log readers & port forwarders', () async {
|
|
device = IOSDevice(
|
|
'123',
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
name: 'iPhone 1',
|
|
sdkVersion: '13.3',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
logReader1 = createLogReader(device, appPackage1, process1);
|
|
logReader2 = createLogReader(device, appPackage2, process2);
|
|
portForwarder = createPortForwarder(forwardedPort, device);
|
|
device.setLogReader(appPackage1, logReader1);
|
|
device.setLogReader(appPackage2, logReader2);
|
|
device.portForwarder = portForwarder;
|
|
|
|
await device.dispose();
|
|
|
|
expect(process1.killed, true);
|
|
expect(process2.killed, true);
|
|
expect(process3.killed, true);
|
|
});
|
|
});
|
|
});
|
|
|
|
group('polling', () {
|
|
late FakeXcdevice xcdevice;
|
|
late Cache cache;
|
|
late FakeProcessManager fakeProcessManager;
|
|
late BufferLogger logger;
|
|
late IOSDeploy iosDeploy;
|
|
late IMobileDevice iMobileDevice;
|
|
late IOSWorkflow iosWorkflow;
|
|
late IOSDevice device1;
|
|
late IOSDevice device2;
|
|
|
|
setUp(() {
|
|
xcdevice = FakeXcdevice();
|
|
final Artifacts artifacts = Artifacts.test();
|
|
cache = Cache.test(processManager: FakeProcessManager.any());
|
|
logger = BufferLogger.test();
|
|
iosWorkflow = FakeIOSWorkflow();
|
|
fakeProcessManager = FakeProcessManager.any();
|
|
iosDeploy = IOSDeploy(
|
|
artifacts: artifacts,
|
|
cache: cache,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
processManager: fakeProcessManager,
|
|
);
|
|
iMobileDevice = IMobileDevice(
|
|
artifacts: artifacts,
|
|
cache: cache,
|
|
processManager: fakeProcessManager,
|
|
logger: logger,
|
|
);
|
|
|
|
device1 = IOSDevice(
|
|
'd83d5bc53967baa0ee18626ba87b6254b2ab5418',
|
|
name: 'Paired iPhone',
|
|
sdkVersion: '13.3',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
fileSystem: MemoryFileSystem.test(),
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
|
|
device2 = IOSDevice(
|
|
'00008027-00192736010F802E',
|
|
name: 'iPad Pro',
|
|
sdkVersion: '13.3',
|
|
cpuArchitecture: DarwinArch.arm64,
|
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
|
iosDeploy: iosDeploy,
|
|
iMobileDevice: iMobileDevice,
|
|
logger: logger,
|
|
platform: macPlatform,
|
|
fileSystem: MemoryFileSystem.test(),
|
|
interfaceType: IOSDeviceConnectionInterface.usb,
|
|
);
|
|
});
|
|
|
|
testWithoutContext('start polling without Xcode', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: macPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = false;
|
|
|
|
await iosDevices.startPolling();
|
|
expect(xcdevice.getAvailableIOSDevicesCount, 0);
|
|
});
|
|
|
|
testWithoutContext('start polling', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: macPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = true;
|
|
xcdevice.devices
|
|
..add(<IOSDevice>[])
|
|
..add(<IOSDevice>[device1, device2]);
|
|
|
|
int addedCount = 0;
|
|
final Completer<void> added = Completer<void>();
|
|
iosDevices.onAdded.listen((Device device) {
|
|
addedCount++;
|
|
// 2 devices will be added.
|
|
// Will throw over-completion if called more than twice.
|
|
if (addedCount >= 2) {
|
|
added.complete();
|
|
}
|
|
});
|
|
|
|
final Completer<void> removed = Completer<void>();
|
|
iosDevices.onRemoved.listen((Device device) {
|
|
// Will throw over-completion if called more than once.
|
|
removed.complete();
|
|
});
|
|
|
|
await iosDevices.startPolling();
|
|
expect(xcdevice.getAvailableIOSDevicesCount, 1);
|
|
|
|
expect(iosDevices.deviceNotifier!.items, isEmpty);
|
|
expect(xcdevice.deviceEventController.hasListener, isTrue);
|
|
|
|
xcdevice.deviceEventController.add(<XCDeviceEvent, String>{
|
|
XCDeviceEvent.attach: 'd83d5bc53967baa0ee18626ba87b6254b2ab5418',
|
|
});
|
|
await added.future;
|
|
expect(iosDevices.deviceNotifier!.items.length, 2);
|
|
expect(iosDevices.deviceNotifier!.items, contains(device1));
|
|
expect(iosDevices.deviceNotifier!.items, contains(device2));
|
|
|
|
xcdevice.deviceEventController.add(<XCDeviceEvent, String>{
|
|
XCDeviceEvent.detach: 'd83d5bc53967baa0ee18626ba87b6254b2ab5418',
|
|
});
|
|
await removed.future;
|
|
expect(iosDevices.deviceNotifier!.items, <Device>[device2]);
|
|
|
|
// Remove stream will throw over-completion if called more than once
|
|
// which proves this is ignored.
|
|
xcdevice.deviceEventController.add(<XCDeviceEvent, String>{
|
|
XCDeviceEvent.detach: 'bogus',
|
|
});
|
|
|
|
expect(addedCount, 2);
|
|
|
|
await iosDevices.stopPolling();
|
|
|
|
expect(xcdevice.deviceEventController.hasListener, isFalse);
|
|
});
|
|
|
|
testWithoutContext('polling can be restarted if stream is closed', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: macPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = true;
|
|
xcdevice.devices.add(<IOSDevice>[]);
|
|
xcdevice.devices.add(<IOSDevice>[]);
|
|
|
|
final StreamController<Map<XCDeviceEvent, String>> rescheduledStream = StreamController<Map<XCDeviceEvent, String>>();
|
|
|
|
unawaited(xcdevice.deviceEventController.done.whenComplete(() {
|
|
xcdevice.deviceEventController = rescheduledStream;
|
|
}));
|
|
|
|
await iosDevices.startPolling();
|
|
expect(xcdevice.deviceEventController.hasListener, isTrue);
|
|
expect(xcdevice.getAvailableIOSDevicesCount, 1);
|
|
|
|
// Pretend xcdevice crashed.
|
|
await xcdevice.deviceEventController.close();
|
|
expect(logger.traceText, contains('xcdevice observe stopped'));
|
|
|
|
// Confirm a restart still gets streamed events.
|
|
await iosDevices.startPolling();
|
|
|
|
expect(rescheduledStream.hasListener, isTrue);
|
|
|
|
await iosDevices.stopPolling();
|
|
expect(rescheduledStream.hasListener, isFalse);
|
|
});
|
|
|
|
testWithoutContext('dispose cancels polling subscription', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: macPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = true;
|
|
xcdevice.devices.add(<IOSDevice>[]);
|
|
|
|
await iosDevices.startPolling();
|
|
expect(iosDevices.deviceNotifier!.items, isEmpty);
|
|
expect(xcdevice.deviceEventController.hasListener, isTrue);
|
|
|
|
iosDevices.dispose();
|
|
expect(xcdevice.deviceEventController.hasListener, isFalse);
|
|
});
|
|
|
|
final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform];
|
|
for (final Platform unsupportedPlatform in unsupportedPlatforms) {
|
|
testWithoutContext('pollingGetDevices throws Unsupported Operation exception on ${unsupportedPlatform.operatingSystem}', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: unsupportedPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = false;
|
|
expect(
|
|
() async { await iosDevices.pollingGetDevices(); },
|
|
throwsUnsupportedError,
|
|
);
|
|
});
|
|
}
|
|
|
|
testWithoutContext('pollingGetDevices returns attached devices', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: macPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = true;
|
|
xcdevice.devices.add(<IOSDevice>[device1]);
|
|
|
|
final List<Device> devices = await iosDevices.pollingGetDevices();
|
|
|
|
expect(devices, hasLength(1));
|
|
expect(devices.first, same(device1));
|
|
});
|
|
});
|
|
|
|
group('getDiagnostics', () {
|
|
late FakeXcdevice xcdevice;
|
|
late IOSWorkflow iosWorkflow;
|
|
late Logger logger;
|
|
|
|
setUp(() {
|
|
xcdevice = FakeXcdevice();
|
|
iosWorkflow = FakeIOSWorkflow();
|
|
logger = BufferLogger.test();
|
|
});
|
|
|
|
final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform];
|
|
for (final Platform unsupportedPlatform in unsupportedPlatforms) {
|
|
testWithoutContext('throws returns platform diagnostic exception on ${unsupportedPlatform.operatingSystem}', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: unsupportedPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = false;
|
|
expect((await iosDevices.getDiagnostics()).first, 'Control of iOS devices or simulators only supported on macOS.');
|
|
});
|
|
}
|
|
|
|
testWithoutContext('returns diagnostics', () async {
|
|
final IOSDevices iosDevices = IOSDevices(
|
|
platform: macPlatform,
|
|
xcdevice: xcdevice,
|
|
iosWorkflow: iosWorkflow,
|
|
logger: logger,
|
|
);
|
|
xcdevice.isInstalled = true;
|
|
xcdevice.diagnostics.add('Generic pairing error');
|
|
|
|
final List<String> diagnostics = await iosDevices.getDiagnostics();
|
|
expect(diagnostics, hasLength(1));
|
|
expect(diagnostics.first, 'Generic pairing error');
|
|
});
|
|
});
|
|
}
|
|
|
|
class FakeIOSApp extends Fake implements IOSApp {
|
|
FakeIOSApp(this.name);
|
|
|
|
@override
|
|
final String name;
|
|
}
|
|
|
|
class FakeIOSWorkflow extends Fake implements IOSWorkflow { }
|
|
|
|
class FakeXcdevice extends Fake implements XCDevice {
|
|
int getAvailableIOSDevicesCount = 0;
|
|
final List<List<IOSDevice>> devices = <List<IOSDevice>>[];
|
|
final List<String> diagnostics = <String>[];
|
|
StreamController<Map<XCDeviceEvent, String>> deviceEventController = StreamController<Map<XCDeviceEvent, String>>();
|
|
|
|
@override
|
|
bool isInstalled = true;
|
|
|
|
@override
|
|
Future<List<String>> getDiagnostics() async {
|
|
return diagnostics;
|
|
}
|
|
|
|
@override
|
|
Stream<Map<XCDeviceEvent, String>> observedDeviceEvents() {
|
|
return deviceEventController.stream;
|
|
}
|
|
|
|
@override
|
|
Future<List<IOSDevice>> getAvailableIOSDevices({Duration? timeout}) async {
|
|
return devices[getAvailableIOSDevicesCount++];
|
|
}
|
|
}
|
|
|
|
class FakeProcess extends Fake implements Process {
|
|
bool killed = false;
|
|
|
|
@override
|
|
bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
|
|
killed = true;
|
|
return true;
|
|
}
|
|
}
|