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

Replace MockAndroidDevice and MockIOSDevice with fakes (#81352)

parent 41d0e1a9
......@@ -8,11 +8,13 @@ import 'dart:async';
import 'dart:io';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/dds.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/attach.dart';
import 'package:flutter_tools/src/device.dart';
......@@ -31,7 +33,6 @@ import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fake_devices.dart';
import '../../src/fake_vm_services.dart';
import '../../src/mocks.dart';
import '../../src/test_flutter_command_runner.dart';
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
......@@ -929,3 +930,20 @@ class TestHotRunnerFactory extends HotRunnerFactory {
}
class MockDartDevelopmentService extends Mock implements DartDevelopmentService {}
class MockAndroidDevice extends Mock implements AndroidDevice {
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm;
@override
bool isSupported() => true;
@override
bool get supportsHotRestart => true;
@override
bool get supportsFlutterExit => false;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
}
......@@ -7,23 +7,25 @@
import 'dart:async';
import 'package:fake_async/fake_async.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_workflow.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/utils.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/commands/daemon.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_workflow.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/ios/ios_workflow.dart';
import 'package:flutter_tools/src/resident_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fake_devices.dart';
import '../../src/fakes.dart';
import '../../src/mocks.dart';
/// Runs a callback using FakeAsync.run while continually pumping the
/// microtask queue. This avoids a deadlock when tests `await` a Future
......@@ -44,13 +46,11 @@ void main() {
Daemon daemon;
NotifyingLogger notifyingLogger;
BufferLogger bufferLogger;
DevtoolsLauncher mockDevToolsLauncher;
group('daemon', () {
setUp(() {
bufferLogger = BufferLogger.test();
notifyingLogger = NotifyingLogger(verbose: false, parent: bufferLogger);
mockDevToolsLauncher = MockDevToolsLauncher();
});
tearDown(() {
......@@ -241,7 +241,7 @@ void main() {
);
final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
daemon.deviceDomain.addDeviceDiscoverer(discoverer);
discoverer.addDevice(MockAndroidDevice());
discoverer.addDevice(FakeAndroidDevice());
commands.add(<String, dynamic>{'id': 0, 'method': 'device.getDevices'});
final Map<String, dynamic> response = await responses.stream.firstWhere(_notEvent);
expect(response['id'], 0);
......@@ -263,22 +263,22 @@ void main() {
final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
daemon.deviceDomain.addDeviceDiscoverer(discoverer);
discoverer.addDevice(MockAndroidDevice());
discoverer.addDevice(FakeAndroidDevice());
return responses.stream.skipWhile(_isConnectedEvent).first.then<void>((Map<String, dynamic> response) async {
expect(response['event'], 'device.added');
expect(response['params'], isMap);
final Map<String, dynamic> params = castStringKeyedMap(response['params']);
expect(params['platform'], isNotEmpty); // the mock device has a platform of 'android-arm'
expect(params['platform'], isNotEmpty); // the fake device has a platform of 'android-arm'
await responses.close();
await commands.close();
});
}, overrides: <Type, Generator>{
AndroidWorkflow: () => MockAndroidWorkflow(),
IOSWorkflow: () => MockIOSWorkflow(),
FuchsiaWorkflow: () => MockFuchsiaWorkflow(),
AndroidWorkflow: () => FakeAndroidWorkflow(),
IOSWorkflow: () => FakeIOSWorkflow(),
FuchsiaWorkflow: () => FakeFuchsiaWorkflow(),
});
testUsingContext('emulator.launch without an emulatorId should report an error', () async {
......@@ -350,7 +350,6 @@ void main() {
responses.add,
notifyingLogger: notifyingLogger,
);
when(mockDevToolsLauncher.serve()).thenAnswer((_) async => DevToolsServerAddress('127.0.0.1', 1234));
commands.add(<String, dynamic>{'id': 0, 'method': 'devtools.serve'});
final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> response) => response['id'] == 0);
......@@ -360,7 +359,7 @@ void main() {
await responses.close();
await commands.close();
}, overrides: <Type, Generator>{
DevtoolsLauncher: () => mockDevToolsLauncher,
DevtoolsLauncher: () => FakeDevtoolsLauncher(DevToolsServerAddress('127.0.0.1', 1234)),
});
testUsingContext('devtools.serve command should return null fields if null returned', () async {
......@@ -371,7 +370,6 @@ void main() {
responses.add,
notifyingLogger: notifyingLogger,
);
when(mockDevToolsLauncher.serve()).thenAnswer((_) async => null);
commands.add(<String, dynamic>{'id': 0, 'method': 'devtools.serve'});
final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> response) => response['id'] == 0);
......@@ -381,7 +379,7 @@ void main() {
await responses.close();
await commands.close();
}, overrides: <Type, Generator>{
DevtoolsLauncher: () => mockDevToolsLauncher,
DevtoolsLauncher: () => FakeDevtoolsLauncher(null),
});
});
......@@ -519,25 +517,61 @@ bool _notEvent(Map<String, dynamic> map) => map['event'] == null;
bool _isConnectedEvent(Map<String, dynamic> map) => map['event'] == 'daemon.connected';
class MockFuchsiaWorkflow extends FuchsiaWorkflow {
MockFuchsiaWorkflow({ this.canListDevices = true });
class FakeFuchsiaWorkflow extends Fake implements FuchsiaWorkflow {
FakeFuchsiaWorkflow({ this.canListDevices = true });
@override
final bool canListDevices;
}
class MockAndroidWorkflow extends AndroidWorkflow {
MockAndroidWorkflow({ this.canListDevices = true });
class FakeAndroidWorkflow extends Fake implements AndroidWorkflow {
FakeAndroidWorkflow({ this.canListDevices = true });
@override
final bool canListDevices;
}
class MockIOSWorkflow extends IOSWorkflow {
MockIOSWorkflow({ this.canListDevices = true });
class FakeIOSWorkflow extends Fake implements IOSWorkflow {
FakeIOSWorkflow({ this.canListDevices = true });
@override
final bool canListDevices;
}
class MockDevToolsLauncher extends Mock implements DevtoolsLauncher {}
class FakeAndroidDevice extends Fake implements AndroidDevice {
@override
final String id = 'device';
@override
final String name = 'device';
@override
Future<String> get emulatorId async => 'device';
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm;
@override
Future<bool> get isLocalEmulator async => false;
@override
final Category category = Category.mobile;
@override
final PlatformType platformType = PlatformType.android;
@override
final bool ephemeral = false;
}
class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher {
FakeDevtoolsLauncher(this._serverAddress);
final DevToolsServerAddress _serverAddress;
@override
Future<DevToolsServerAddress> serve() async => _serverAddress;
@override
Future<void> close() async {}
}
......@@ -5,6 +5,7 @@
// @dart = 2.8
import 'package:file/file.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/application_package.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -12,11 +13,11 @@ import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/install.dart';
import 'package:flutter_tools/src/ios/application_package.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/ios/devices.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/mocks.dart';
import '../../src/test_flutter_command_runner.dart';
void main() {
......@@ -29,11 +30,7 @@ void main() {
final InstallCommand command = InstallCommand();
command.applicationPackages = FakeApplicationPackageFactory(FakeAndroidApk());
final MockAndroidDevice device = MockAndroidDevice();
when(device.isAppInstalled(any, userIdentifier: anyNamed('userIdentifier')))
.thenAnswer((_) async => false);
when(device.installApp(any, userIdentifier: anyNamed('userIdentifier')))
.thenAnswer((_) async => true);
final FakeAndroidDevice device = FakeAndroidDevice();
testDeviceManager.addDevice(device);
await createTestCommandRunner(command).run(<String>['install']);
......@@ -45,11 +42,7 @@ void main() {
final InstallCommand command = InstallCommand();
command.applicationPackages = FakeApplicationPackageFactory(FakeAndroidApk());
final MockIOSDevice device = MockIOSDevice();
when(device.isAppInstalled(any, userIdentifier: anyNamed('userIdentifier')))
.thenAnswer((_) async => false);
when(device.installApp(any, userIdentifier: anyNamed('userIdentifier')))
.thenAnswer((_) async => true);
final FakeIOSDevice device = FakeIOSDevice();
testDeviceManager.addDevice(device);
expect(() async => createTestCommandRunner(command).run(<String>['install', '--device-user', '10']),
......@@ -62,9 +55,7 @@ void main() {
final InstallCommand command = InstallCommand();
command.applicationPackages = FakeApplicationPackageFactory(FakeIOSApp());
final MockIOSDevice device = MockIOSDevice();
when(device.isAppInstalled(any)).thenAnswer((_) async => false);
when(device.installApp(any)).thenAnswer((_) async => true);
final FakeIOSDevice device = FakeIOSDevice();
testDeviceManager.addDevice(device);
await createTestCommandRunner(command).run(<String>['install']);
......@@ -86,3 +77,37 @@ class FakeApplicationPackageFactory extends Fake implements ApplicationPackageFa
}
class FakeIOSApp extends Fake implements IOSApp {}
class FakeAndroidApk extends Fake implements AndroidApk {}
class FakeIOSDevice extends Fake implements IOSDevice {
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.ios;
@override
Future<bool> isAppInstalled(
IOSApp app, {
String userIdentifier,
}) async => false;
@override
Future<bool> installApp(
IOSApp app, {
String userIdentifier,
}) async => true;
}
class FakeAndroidDevice extends Fake implements AndroidDevice {
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm;
@override
Future<bool> isAppInstalled(
AndroidApk app, {
String userIdentifier,
}) async => false;
@override
Future<bool> installApp(
AndroidApk app, {
String userIdentifier,
}) async => true;
}
......@@ -16,8 +16,10 @@ import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build_bundle.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:mockito/mockito.dart';
import 'package:meta/meta.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
......@@ -28,23 +30,12 @@ import '../../src/test_flutter_command_runner.dart';
void main() {
Cache.disableLocking();
Directory tempDir;
MockBundleBuilder mockBundleBuilder;
FakeBundleBuilder fakeBundleBuilder;
setUp(() {
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_packages_test.');
mockBundleBuilder = MockBundleBuilder();
when(
mockBundleBuilder.build(
platform: anyNamed('platform'),
buildInfo: anyNamed('buildInfo'),
mainPath: anyNamed('mainPath'),
manifestPath: anyNamed('manifestPath'),
applicationKernelFilePath: anyNamed('applicationKernelFilePath'),
depfilePath: anyNamed('depfilePath'),
assetDirPath: anyNamed('assetDirPath'),
),
).thenAnswer((_) => Future<void>.value());
fakeBundleBuilder = FakeBundleBuilder();
});
tearDown(() {
......@@ -52,7 +43,7 @@ void main() {
});
Future<BuildBundleCommand> runCommandIn(String projectPath, { List<String> arguments }) async {
final BuildBundleCommand command = BuildBundleCommand(bundleBuilder: mockBundleBuilder);
final BuildBundleCommand command = BuildBundleCommand(bundleBuilder: fakeBundleBuilder);
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[
'bundle',
......@@ -98,7 +89,7 @@ void main() {
globals.fs.file('pubspec.yaml').createSync(recursive: true);
globals.fs.file('.packages').createSync(recursive: true);
final CommandRunner<void> runner = createTestCommandRunner(BuildBundleCommand()
..bundleBuilder = MockBundleBuilder());
..bundleBuilder = FakeBundleBuilder());
expect(() => runner.run(<String>[
'bundle',
......@@ -116,7 +107,7 @@ void main() {
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync();
final CommandRunner<void> runner = createTestCommandRunner(BuildBundleCommand()
..bundleBuilder = MockBundleBuilder());
..bundleBuilder = FakeBundleBuilder());
expect(() => runner.run(<String>[
'bundle',
......@@ -134,7 +125,7 @@ void main() {
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync();
final CommandRunner<void> runner = createTestCommandRunner(BuildBundleCommand()
..bundleBuilder = MockBundleBuilder());
..bundleBuilder = FakeBundleBuilder());
expect(() => runner.run(<String>[
'bundle',
......@@ -152,7 +143,7 @@ void main() {
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync();
final CommandRunner<void> runner = createTestCommandRunner(BuildBundleCommand()
..bundleBuilder = MockBundleBuilder());
..bundleBuilder = FakeBundleBuilder());
await runner.run(<String>[
'bundle',
......@@ -170,7 +161,7 @@ void main() {
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync();
final CommandRunner<void> runner = createTestCommandRunner(BuildBundleCommand()
..bundleBuilder = MockBundleBuilder());
..bundleBuilder = FakeBundleBuilder());
await runner.run(<String>[
'bundle',
......@@ -188,7 +179,7 @@ void main() {
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync();
final CommandRunner<void> runner = createTestCommandRunner(BuildBundleCommand()
..bundleBuilder = MockBundleBuilder());
..bundleBuilder = FakeBundleBuilder());
await runner.run(<String>[
'bundle',
......@@ -380,4 +371,17 @@ void main() {
});
}
class MockBundleBuilder extends Mock implements BundleBuilder {}
class FakeBundleBuilder extends Fake implements BundleBuilder {
@override
Future<void> build({
@required TargetPlatform platform,
@required BuildInfo buildInfo,
FlutterProject project,
String mainPath,
String manifestPath = defaultManifestPath,
String applicationKernelFilePath,
String depfilePath,
String assetDirPath,
@visibleForTesting BuildSystem buildSystem,
}) async {}
}
......@@ -23,10 +23,11 @@ import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/macos/xcode.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart';
import 'package:meta/meta.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/context.dart' hide FakeXcodeProjectInterpreter;
import '../../src/fake_process_manager.dart';
import '../../src/fakes.dart';
......@@ -84,35 +85,14 @@ void main() {
FakeProcessManager processManager;
BufferLogger logger;
Xcode xcode;
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
FakeXcodeProjectInterpreter fakeXcodeProjectInterpreter;
setUp(() {
logger = BufferLogger.test();
fileSystem = MemoryFileSystem.test();
processManager = FakeProcessManager.empty();
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.version).thenReturn(Version(1000, 0, 0));
when(mockXcodeProjectInterpreter.xcrunCommand()).thenReturn(<String>['xcrun']);
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer(
(_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(
<String>['Runner'],
<String>['Debug', 'Release'],
<String>['Runner'],
logger,
));
}
);
when(mockXcodeProjectInterpreter.getBuildSettings(any, buildContext: anyNamed('buildContext')))
.thenAnswer((_) async => <String, String>{
'TARGET_BUILD_DIR': 'build/ios/Release-iphoneos',
'WRAPPER_NAME': 'My Super Awesome App.app',
'DEVELOPMENT_TEAM': '3333CCCC33',
});
xcode = Xcode.test(processManager: FakeProcessManager.any(), xcodeProjectInterpreter: mockXcodeProjectInterpreter);
fakeXcodeProjectInterpreter = FakeXcodeProjectInterpreter();
xcode = Xcode.test(processManager: FakeProcessManager.any(), xcodeProjectInterpreter: fakeXcodeProjectInterpreter);
fileSystem.file('foo/.packages')
..createSync(recursive: true)
..writeAsStringSync('\n');
......@@ -172,7 +152,7 @@ void main() {
FileSystem: () => fileSystem,
Logger: () => logger,
Platform: () => macPlatform,
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
});
......@@ -232,7 +212,7 @@ void main() {
FileSystem: () => fileSystem,
Logger: () => logger,
Platform: () => macPlatform,
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
}, skip: true); // TODO(jonahwilliams): clean up with https://github.com/flutter/flutter/issues/60675
});
......@@ -289,4 +269,37 @@ IOSDevice setUpIOSDevice({
);
}
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterpreter {
@override
final bool isInstalled = true;
@override
final Version version = Version(1000, 0, 0);
@override
List<String> xcrunCommand() => <String>['xcrun'];
@override
Future<XcodeProjectInfo> getInfo(
String projectPath, {
String projectFilename,
}) async =>
XcodeProjectInfo(
<String>['Runner'],
<String>['Debug', 'Release'],
<String>['Runner'],
BufferLogger.test(),
);
@override
Future<Map<String, String>> getBuildSettings(
String projectPath, {
@required XcodeProjectBuildContext buildContext,
Duration timeout = const Duration(minutes: 1),
}) async =>
<String, String>{
'TARGET_BUILD_DIR': 'build/ios/Release-iphoneos',
'WRAPPER_NAME': 'My Super Awesome App.app',
'DEVELOPMENT_TEAM': '3333CCCC33',
};
}
......@@ -6,14 +6,10 @@
import 'dart:async';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_sdk.dart' show AndroidSdk;
import 'package:flutter_tools/src/base/file_system.dart' hide IOSink;
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
......@@ -154,31 +150,3 @@ _ProcessFactory flakyProcessFactory({
);
};
}
class MockAndroidDevice extends Mock implements AndroidDevice {
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm;
@override
bool isSupported() => true;
@override
bool get supportsHotRestart => true;
@override
bool get supportsFlutterExit => false;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
}
class MockIOSDevice extends Mock implements IOSDevice {
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.ios;
@override
bool isSupported() => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
}
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