Unverified Commit aaff3290 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove all mocks from attach.dart (#84118)

parent 094a75e6
...@@ -9,6 +9,7 @@ import 'dart:io'; ...@@ -9,6 +9,7 @@ import 'dart:io';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/application_package.dart';
import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/dds.dart'; import 'package:flutter_tools/src/base/dds.dart';
...@@ -28,7 +29,7 @@ import 'package:flutter_tools/src/resident_runner.dart'; ...@@ -28,7 +29,7 @@ import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/run_hot.dart'; import 'package:flutter_tools/src/run_hot.dart';
import 'package:flutter_tools/src/vmservice.dart'; import 'package:flutter_tools/src/vmservice.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart'; import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart' as vm_service; import 'package:vm_service/vm_service.dart' as vm_service;
import '../../src/common.dart'; import '../../src/common.dart';
...@@ -78,29 +79,17 @@ void main() { ...@@ -78,29 +79,17 @@ void main() {
const int hostPort = 42; const int hostPort = 42;
FakeDeviceLogReader fakeLogReader; FakeDeviceLogReader fakeLogReader;
MockPortForwarder portForwarder; RecordingPortForwarder portForwarder;
FakeDartDevelopmentService fakeDds; FakeDartDevelopmentService fakeDds;
MockAndroidDevice device; FakeAndroidDevice device;
setUp(() { setUp(() {
fakeLogReader = FakeDeviceLogReader(); fakeLogReader = FakeDeviceLogReader();
portForwarder = MockPortForwarder(); portForwarder = RecordingPortForwarder(hostPort);
device = MockAndroidDevice();
fakeDds = FakeDartDevelopmentService(); fakeDds = FakeDartDevelopmentService();
when(device.portForwarder) device = FakeAndroidDevice(id: '1')
.thenReturn(portForwarder); ..portForwarder = portForwarder
when(portForwarder.forward(devicePort, hostPort: anyNamed('hostPort'))) ..dds = fakeDds;
.thenAnswer((_) async => hostPort);
when(portForwarder.forwardedPorts)
.thenReturn(<ForwardedPort>[ForwardedPort(hostPort, devicePort)]);
when(portForwarder.unforward(any))
.thenAnswer((_) async {});
when(device.dds).thenReturn(fakeDds);
// We cannot add the device to a device manager because that is
// only enabled by the context of each testUsingContext call.
//
// Instead each test will add the device to the device manager
// on its own.
}); });
tearDown(() { tearDown(() {
...@@ -108,13 +97,11 @@ void main() { ...@@ -108,13 +97,11 @@ void main() {
}); });
testUsingContext('finds observatory port and forwards', () async { testUsingContext('finds observatory port and forwards', () async {
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs'))) device.onGetLogReader = () {
.thenAnswer((_) { fakeLogReader.addLine('Foo');
// Now that the reader is used, start writing messages to it. fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort');
fakeLogReader.addLine('Foo'); return fakeLogReader;
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort'); };
return fakeLogReader;
});
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
final Completer<void> completer = Completer<void>(); final Completer<void> completer = Completer<void>();
final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) { final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) {
...@@ -125,9 +112,10 @@ void main() { ...@@ -125,9 +112,10 @@ void main() {
}); });
final Future<void> task = createTestCommandRunner(AttachCommand()).run(<String>['attach']); final Future<void> task = createTestCommandRunner(AttachCommand()).run(<String>['attach']);
await completer.future; await completer.future;
verify(
portForwarder.forward(devicePort, hostPort: anyNamed('hostPort')), expect(portForwarder.devicePort, devicePort);
).called(1); expect(portForwarder.hostPort, hostPort);
await fakeLogReader.dispose(); await fakeLogReader.dispose();
await expectLoggerInterruptEndsTask(task, logger); await expectLoggerInterruptEndsTask(task, logger);
await loggerSubscription.cancel(); await loggerSubscription.cancel();
...@@ -138,17 +126,14 @@ void main() { ...@@ -138,17 +126,14 @@ void main() {
}); });
testUsingContext('Fails with tool exit on bad Observatory uri', () async { testUsingContext('Fails with tool exit on bad Observatory uri', () async {
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs'))) device.onGetLogReader = () {
.thenAnswer((_) { fakeLogReader.addLine('Foo');
// Now that the reader is used, start writing messages to it. fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort');
fakeLogReader.addLine('Foo'); fakeLogReader.dispose();
fakeLogReader.addLine('Observatory listening on http:/:/127.0.0.1:$devicePort'); return fakeLogReader;
fakeLogReader.dispose(); };
return fakeLogReader;
});
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
expect(createTestCommandRunner(AttachCommand()).run(<String>['attach']), expect(() => createTestCommandRunner(AttachCommand()).run(<String>['attach']), throwsToolExit());
throwsToolExit());
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => testFileSystem, FileSystem: () => testFileSystem,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
...@@ -156,13 +141,11 @@ void main() { ...@@ -156,13 +141,11 @@ void main() {
}); });
testUsingContext('accepts filesystem parameters', () async { testUsingContext('accepts filesystem parameters', () async {
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs'))) device.onGetLogReader = () {
.thenAnswer((_) { fakeLogReader.addLine('Foo');
// Now that the reader is used, start writing messages to it. fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort');
fakeLogReader.addLine('Foo'); return fakeLogReader;
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort'); };
return fakeLogReader;
});
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
const String filesystemScheme = 'foo'; const String filesystemScheme = 'foo';
...@@ -170,31 +153,21 @@ void main() { ...@@ -170,31 +153,21 @@ void main() {
const String projectRoot = '/build-output/project-root'; const String projectRoot = '/build-output/project-root';
const String outputDill = '/tmp/output.dill'; const String outputDill = '/tmp/output.dill';
final MockHotRunner mockHotRunner = MockHotRunner(); final FakeHotRunner hotRunner = FakeHotRunner();
when(mockHotRunner.attach( hotRunner.onAttach = (
appStartedCompleter: anyNamed('appStartedCompleter'), Completer<DebugConnectionInfo> connectionInfoCompleter,
allowExistingDdsInstance: true, Completer<void> appStartedCompleter,
enableDevTools: anyNamed('enableDevTools'), bool allowExistingDdsInstance,
)).thenAnswer((_) async => 0); bool enableDevTools,
when(mockHotRunner.exited).thenReturn(false); ) async => 0;
when(mockHotRunner.isWaitingForObservatory).thenReturn(false); hotRunner.exited = false;
hotRunner.isWaitingForObservatory = false;
final MockHotRunnerFactory mockHotRunnerFactory = MockHotRunnerFactory();
when( final FakeHotRunnerFactory hotRunnerFactory = FakeHotRunnerFactory()
mockHotRunnerFactory.build( ..hotRunner = hotRunner;
any,
target: anyNamed('target'),
projectRootPath: anyNamed('projectRootPath'),
dillOutputPath: anyNamed('dillOutputPath'),
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
),
).thenReturn(mockHotRunner);
final AttachCommand command = AttachCommand( final AttachCommand command = AttachCommand(
hotRunnerFactory: mockHotRunnerFactory, hotRunnerFactory: hotRunnerFactory,
); );
await createTestCommandRunner(command).run(<String>[ await createTestCommandRunner(command).run(<String>[
'attach', 'attach',
...@@ -209,27 +182,15 @@ void main() { ...@@ -209,27 +182,15 @@ void main() {
'-v', // enables verbose logging '-v', // enables verbose logging
]); ]);
// Validate the attach call built a mock runner with the right // Validate the attach call built a fake runner with the right
// project root and output dill. // project root and output dill.
final VerificationResult verificationResult = verify( expect(hotRunnerFactory.projectRootPath, projectRoot);
mockHotRunnerFactory.build( expect(hotRunnerFactory.dillOutputPath, outputDill);
captureAny, expect(hotRunnerFactory.devices, hasLength(1));
target: anyNamed('target'),
projectRootPath: projectRoot,
dillOutputPath: outputDill,
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
),
)..called(1);
final List<FlutterDevice> flutterDevices = verificationResult.captured.first as List<FlutterDevice>;
expect(flutterDevices, hasLength(1));
// Validate that the attach call built a flutter device with the right // Validate that the attach call built a flutter device with the right
// output dill, filesystem scheme, and filesystem root. // output dill, filesystem scheme, and filesystem root.
final FlutterDevice flutterDevice = flutterDevices.first; final FlutterDevice flutterDevice = hotRunnerFactory.devices.first;
expect(flutterDevice.fileSystemScheme, filesystemScheme); expect(flutterDevice.fileSystemScheme, filesystemScheme);
expect(flutterDevice.fileSystemRoots, const <String>[filesystemRoot]); expect(flutterDevice.fileSystemRoots, const <String>[filesystemRoot]);
...@@ -239,13 +200,6 @@ void main() { ...@@ -239,13 +200,6 @@ void main() {
}); });
testUsingContext('exits when ipv6 is specified and debug-port is not', () async { testUsingContext('exits when ipv6 is specified and debug-port is not', () async {
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs')))
.thenAnswer((_) {
// Now that the reader is used, start writing messages to it.
fakeLogReader.addLine('Foo');
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort');
return fakeLogReader;
});
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
final AttachCommand command = AttachCommand(); final AttachCommand command = AttachCommand();
...@@ -262,13 +216,11 @@ void main() { ...@@ -262,13 +216,11 @@ void main() {
},); },);
testUsingContext('exits when observatory-port is specified and debug-port is not', () async { testUsingContext('exits when observatory-port is specified and debug-port is not', () async {
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs'))) device.onGetLogReader = () {
.thenAnswer((_) { fakeLogReader.addLine('Foo');
// Now that the reader is used, start writing messages to it. fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort');
fakeLogReader.addLine('Foo'); return fakeLogReader;
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort'); };
return fakeLogReader;
});
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
final AttachCommand command = AttachCommand(); final AttachCommand command = AttachCommand();
...@@ -285,162 +237,18 @@ void main() { ...@@ -285,162 +237,18 @@ void main() {
},); },);
}); });
testUsingContext('selects specified target', () async {
const int devicePort = 499;
const int hostPort = 42;
final FakeDeviceLogReader fakeLogReader = FakeDeviceLogReader();
final MockPortForwarder portForwarder = MockPortForwarder();
final FakeDartDevelopmentService fakeDds = FakeDartDevelopmentService();
final MockAndroidDevice device = MockAndroidDevice();
final MockHotRunner mockHotRunner = MockHotRunner();
final MockHotRunnerFactory mockHotRunnerFactory = MockHotRunnerFactory();
when(device.portForwarder)
.thenReturn(portForwarder);
when(device.dds)
.thenReturn(fakeDds);
when(portForwarder.forward(devicePort, hostPort: anyNamed('hostPort')))
.thenAnswer((_) async => hostPort);
when(portForwarder.forwardedPorts)
.thenReturn(<ForwardedPort>[ForwardedPort(hostPort, devicePort)]);
when(portForwarder.unforward(any))
.thenAnswer((_) async {});
when(mockHotRunner.attach(
appStartedCompleter: anyNamed('appStartedCompleter'),
allowExistingDdsInstance: true,
enableDevTools: anyNamed('enableDevTools'),
)).thenAnswer((_) async => 0);
when(mockHotRunnerFactory.build(
any,
target: anyNamed('target'),
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
)).thenReturn(mockHotRunner);
when(mockHotRunner.exited).thenReturn(false);
when(mockHotRunner.isWaitingForObservatory).thenReturn(false);
testDeviceManager.addDevice(device);
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs')))
.thenAnswer((_) {
// Now that the reader is used, start writing messages to it.
fakeLogReader.addLine('Foo');
fakeLogReader.addLine(
'Observatory listening on http://127.0.0.1:$devicePort');
return fakeLogReader;
});
final File foo = globals.fs.file('lib/foo.dart')
..createSync();
// Delete the main.dart file to be sure that attach works without it.
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).deleteSync();
final AttachCommand command = AttachCommand(hotRunnerFactory: mockHotRunnerFactory);
await createTestCommandRunner(command).run(<String>[
'attach',
'-t',
foo.path,
'-v',
'--device-user',
'10',
'--device-timeout',
'15',
]);
final VerificationResult verificationResult = verify(
mockHotRunnerFactory.build(
captureAny,
target: foo.path,
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
),
)..called(1);
final List<FlutterDevice> flutterDevices = verificationResult.captured.first as List<FlutterDevice>;
expect(flutterDevices, hasLength(1));
final FlutterDevice flutterDevice = flutterDevices.first;
expect(flutterDevice.userIdentifier, '10');
}, overrides: <Type, Generator>{
FileSystem: () => testFileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('fallbacks to protocol observatory if MDNS failed on iOS', () async {
const int devicePort = 499;
const int hostPort = 42;
final FakeDeviceLogReader fakeLogReader = FakeDeviceLogReader();
final MockPortForwarder portForwarder = MockPortForwarder();
final FakeDartDevelopmentService mockDds = FakeDartDevelopmentService();
final FakeIOSDevice device = FakeIOSDevice(dds: mockDds, portForwarder: portForwarder, logReader: fakeLogReader);
final MockHotRunner mockHotRunner = MockHotRunner();
final MockHotRunnerFactory mockHotRunnerFactory = MockHotRunnerFactory();
when(portForwarder.forward(devicePort, hostPort: anyNamed('hostPort')))
.thenAnswer((_) async => hostPort);
when(portForwarder.forwardedPorts)
.thenReturn(<ForwardedPort>[ForwardedPort(hostPort, devicePort)]);
when(portForwarder.unforward(any))
.thenAnswer((_) async {});
when(mockHotRunner.attach(
appStartedCompleter: anyNamed('appStartedCompleter'),
allowExistingDdsInstance: true,
enableDevTools: anyNamed('enableDevTools'),
)).thenAnswer((_) async => 0);
when(mockHotRunnerFactory.build(
any,
target: anyNamed('target'),
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
)).thenReturn(mockHotRunner);
when(mockHotRunner.exited).thenReturn(false);
when(mockHotRunner.isWaitingForObservatory).thenReturn(false);
testDeviceManager.addDevice(device);
final File foo = globals.fs.file('lib/foo.dart')..createSync();
// Delete the main.dart file to be sure that attach works without it.
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).deleteSync();
final AttachCommand command = AttachCommand(hotRunnerFactory: mockHotRunnerFactory);
await createTestCommandRunner(command).run(<String>['attach', '-t', foo.path, '-v']);
verify(mockHotRunnerFactory.build(
any,
target: foo.path,
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
)).called(1);
}, overrides: <Type, Generator>{
FileSystem: () => testFileSystem,
ProcessManager: () => FakeProcessManager.any(),
}, skip: Platform.isWindows); // mDNS does not work on Windows.
group('forwarding to given port', () { group('forwarding to given port', () {
const int devicePort = 499; const int devicePort = 499;
const int hostPort = 42; const int hostPort = 42;
MockPortForwarder portForwarder; RecordingPortForwarder portForwarder;
MockAndroidDevice device; FakeAndroidDevice device;
setUp(() { setUp(() {
portForwarder = MockPortForwarder();
final FakeDartDevelopmentService fakeDds = FakeDartDevelopmentService(); final FakeDartDevelopmentService fakeDds = FakeDartDevelopmentService();
device = MockAndroidDevice(); portForwarder = RecordingPortForwarder(hostPort);
device = FakeAndroidDevice(id: '1')
when(device.portForwarder) ..portForwarder = portForwarder
.thenReturn(portForwarder); ..dds = fakeDds;
when(portForwarder.forward(devicePort))
.thenAnswer((_) async => hostPort);
when(portForwarder.forwardedPorts)
.thenReturn(<ForwardedPort>[ForwardedPort(hostPort, devicePort)]);
when(portForwarder.unforward(any))
.thenAnswer((_) async {});
when(device.dds)
.thenReturn(fakeDds);
}); });
testUsingContext('succeeds in ipv4 mode', () async { testUsingContext('succeeds in ipv4 mode', () async {
...@@ -457,7 +265,8 @@ void main() { ...@@ -457,7 +265,8 @@ void main() {
final Future<void> task = createTestCommandRunner(AttachCommand()) final Future<void> task = createTestCommandRunner(AttachCommand())
.run(<String>['attach', '--debug-port', '$devicePort']); .run(<String>['attach', '--debug-port', '$devicePort']);
await completer.future; await completer.future;
verify(portForwarder.forward(devicePort)).called(1); expect(portForwarder.devicePort, devicePort);
expect(portForwarder.hostPort, hostPort);
await expectLoggerInterruptEndsTask(task, logger); await expectLoggerInterruptEndsTask(task, logger);
await loggerSubscription.cancel(); await loggerSubscription.cancel();
...@@ -481,7 +290,9 @@ void main() { ...@@ -481,7 +290,9 @@ void main() {
final Future<void> task = createTestCommandRunner(AttachCommand()) final Future<void> task = createTestCommandRunner(AttachCommand())
.run(<String>['attach', '--debug-port', '$devicePort', '--ipv6']); .run(<String>['attach', '--debug-port', '$devicePort', '--ipv6']);
await completer.future; await completer.future;
verify(portForwarder.forward(devicePort)).called(1);
expect(portForwarder.devicePort, devicePort);
expect(portForwarder.hostPort, hostPort);
await expectLoggerInterruptEndsTask(task, logger); await expectLoggerInterruptEndsTask(task, logger);
await loggerSubscription.cancel(); await loggerSubscription.cancel();
...@@ -515,7 +326,8 @@ void main() { ...@@ -515,7 +326,8 @@ void main() {
], ],
); );
await completer.future; await completer.future;
verifyNever(portForwarder.forward(devicePort)); expect(portForwarder.devicePort, null);
expect(portForwarder.hostPort, 42);
await expectLoggerInterruptEndsTask(task, logger); await expectLoggerInterruptEndsTask(task, logger);
await loggerSubscription.cancel(); await loggerSubscription.cancel();
...@@ -550,7 +362,8 @@ void main() { ...@@ -550,7 +362,8 @@ void main() {
], ],
); );
await completer.future; await completer.future;
verifyNever(portForwarder.forward(devicePort)); expect(portForwarder.devicePort, null);
expect(portForwarder.hostPort, 42);
await expectLoggerInterruptEndsTask(task, logger); await expectLoggerInterruptEndsTask(task, logger);
await loggerSubscription.cancel(); await loggerSubscription.cancel();
...@@ -587,21 +400,9 @@ void main() { ...@@ -587,21 +400,9 @@ void main() {
}); });
testUsingContext('exits when multiple devices connected', () async { testUsingContext('exits when multiple devices connected', () async {
Device aDeviceWithId(String id) {
final MockAndroidDevice device = MockAndroidDevice();
when(device.name).thenReturn('d$id');
when(device.id).thenReturn(id);
when(device.isLocalEmulator).thenAnswer((_) async => false);
when(device.sdkNameAndVersion).thenAnswer((_) async => 'Android 46');
when(device.targetPlatformDisplayName)
.thenAnswer((_) async => 'android');
return device;
}
final AttachCommand command = AttachCommand(); final AttachCommand command = AttachCommand();
testDeviceManager.addDevice(aDeviceWithId('xx1')); testDeviceManager.addDevice(FakeAndroidDevice(id: 'xx1'));
testDeviceManager.addDevice(aDeviceWithId('yy2')); testDeviceManager.addDevice(FakeAndroidDevice(id: 'yy2'));
await expectLater( await expectLater(
createTestCommandRunner(command).run(<String>['attach']), createTestCommandRunner(command).run(<String>['attach']),
throwsToolExit(), throwsToolExit(),
...@@ -615,36 +416,26 @@ void main() { ...@@ -615,36 +416,26 @@ void main() {
}); });
testUsingContext('Catches service disappeared error', () async { testUsingContext('Catches service disappeared error', () async {
final MockAndroidDevice device = MockAndroidDevice(); final FakeAndroidDevice device = FakeAndroidDevice(id: '1')
final MockHotRunner mockHotRunner = MockHotRunner(); ..portForwarder = const NoOpDevicePortForwarder()
final MockHotRunnerFactory mockHotRunnerFactory = MockHotRunnerFactory(); ..onGetLogReader = () => NoOpDeviceLogReader('test');
when(device.portForwarder).thenReturn(const NoOpDevicePortForwarder()); final FakeHotRunner hotRunner = FakeHotRunner();
final FakeHotRunnerFactory hotRunnerFactory = FakeHotRunnerFactory()
when(mockHotRunner.attach( ..hotRunner = hotRunner;
appStartedCompleter: anyNamed('appStartedCompleter'), hotRunner.onAttach = (
allowExistingDdsInstance: true, Completer<DebugConnectionInfo> connectionInfoCompleter,
enableDevTools: anyNamed('enableDevTools'), Completer<void> appStartedCompleter,
)).thenAnswer((_) async { bool allowExistingDdsInstance,
bool enableDevTools,
) async {
await null; await null;
throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kServiceDisappeared, ''); throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kServiceDisappeared, '');
}); };
when(mockHotRunnerFactory.build(
any,
target: anyNamed('target'),
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
)).thenReturn(mockHotRunner);
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs')))
.thenAnswer((_) {
return NoOpDeviceLogReader('test');
});
testFileSystem.file('lib/main.dart').createSync(); testFileSystem.file('lib/main.dart').createSync();
final AttachCommand command = AttachCommand(hotRunnerFactory: mockHotRunnerFactory); final AttachCommand command = AttachCommand(hotRunnerFactory: hotRunnerFactory);
await expectLater(createTestCommandRunner(command).run(<String>[ await expectLater(createTestCommandRunner(command).run(<String>[
'attach', 'attach',
]), throwsToolExit(message: 'Lost connection to device.')); ]), throwsToolExit(message: 'Lost connection to device.'));
...@@ -654,36 +445,28 @@ void main() { ...@@ -654,36 +445,28 @@ void main() {
}); });
testUsingContext('Does not catch generic RPC error', () async { testUsingContext('Does not catch generic RPC error', () async {
final MockAndroidDevice device = MockAndroidDevice(); final FakeAndroidDevice device = FakeAndroidDevice(id: '1')
final MockHotRunner mockHotRunner = MockHotRunner(); ..portForwarder = const NoOpDevicePortForwarder()
final MockHotRunnerFactory mockHotRunnerFactory = MockHotRunnerFactory(); ..onGetLogReader = () => NoOpDeviceLogReader('test');
when(device.portForwarder).thenReturn(const NoOpDevicePortForwarder()); final FakeHotRunner hotRunner = FakeHotRunner();
final FakeHotRunnerFactory hotRunnerFactory = FakeHotRunnerFactory()
when(mockHotRunner.attach( ..hotRunner = hotRunner;
appStartedCompleter: anyNamed('appStartedCompleter'),
allowExistingDdsInstance: true, hotRunner.onAttach = (
enableDevTools: anyNamed('enableDevTools'), Completer<DebugConnectionInfo> connectionInfoCompleter,
)).thenAnswer((_) async { Completer<void> appStartedCompleter,
bool allowExistingDdsInstance,
bool enableDevTools,
) async {
await null; await null;
throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kInvalidParams, ''); throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kInvalidParams, '');
}); };
when(mockHotRunnerFactory.build(
any,
target: anyNamed('target'),
debuggingOptions: anyNamed('debuggingOptions'),
packagesFilePath: anyNamed('packagesFilePath'),
flutterProject: anyNamed('flutterProject'),
ipv6: false,
)).thenReturn(mockHotRunner);
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
when(device.getLogReader(includePastLogs: anyNamed('includePastLogs')))
.thenAnswer((_) {
return NoOpDeviceLogReader('test');
});
testFileSystem.file('lib/main.dart').createSync(); testFileSystem.file('lib/main.dart').createSync();
final AttachCommand command = AttachCommand(hotRunnerFactory: mockHotRunnerFactory); final AttachCommand command = AttachCommand(hotRunnerFactory: hotRunnerFactory);
await expectLater(createTestCommandRunner(command).run(<String>[ await expectLater(createTestCommandRunner(command).run(<String>[
'attach', 'attach',
]), throwsA(isA<vm_service.RPCError>())); ]), throwsA(isA<vm_service.RPCError>()));
...@@ -694,9 +477,76 @@ void main() { ...@@ -694,9 +477,76 @@ void main() {
}); });
} }
class MockHotRunner extends Mock implements HotRunner {} class FakeHotRunner extends Fake implements HotRunner {
class MockHotRunnerFactory extends Mock implements HotRunnerFactory {} Future<int> Function(Completer<DebugConnectionInfo>, Completer<void>, bool, bool) onAttach;
class MockPortForwarder extends Mock implements DevicePortForwarder {}
@override
bool exited = false;
@override
bool isWaitingForObservatory = true;
@override
Future<int> attach({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false,
}) {
return onAttach(connectionInfoCompleter, appStartedCompleter, allowExistingDdsInstance, enableDevTools);
}
}
class FakeHotRunnerFactory extends Fake implements HotRunnerFactory {
HotRunner hotRunner;
String dillOutputPath;
String projectRootPath;
List<FlutterDevice> devices;
@override
HotRunner build(
List<FlutterDevice> devices, {
String target,
DebuggingOptions debuggingOptions,
bool benchmarkMode = false,
File applicationBinary,
bool hostIsIde = false,
String projectRootPath,
String packagesFilePath,
String dillOutputPath,
bool stayResident = true,
bool ipv6 = false,
FlutterProject flutterProject,
}) {
this.devices = devices;
this.dillOutputPath = dillOutputPath;
this.projectRootPath = projectRootPath;
return hotRunner;
}
}
class RecordingPortForwarder implements DevicePortForwarder {
RecordingPortForwarder([this.hostPort]);
int devicePort;
int hostPort;
@override
Future<void> dispose() async { }
@override
Future<int> forward(int devicePort, {int hostPort}) async {
this.devicePort = devicePort;
this.hostPort ??= hostPort;
return this.hostPort;
}
@override
List<ForwardedPort> get forwardedPorts => <ForwardedPort>[];
@override
Future<void> unforward(ForwardedPort forwardedPort) async { }
}
class StreamLogger extends Logger { class StreamLogger extends Logger {
@override @override
...@@ -922,7 +772,27 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService ...@@ -922,7 +772,27 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
Uri get uri => Uri.parse('http://localhost:8181'); Uri get uri => Uri.parse('http://localhost:8181');
} }
class MockAndroidDevice extends Mock implements AndroidDevice { class FakeAndroidDevice extends Fake implements AndroidDevice {
FakeAndroidDevice({@required this.id});
@override
DartDevelopmentService dds;
@override
final String id;
@override
String get name => 'd$id';
@override
Future<bool> get isLocalEmulator async => false;
@override
Future<String> get sdkNameAndVersion async => 'Android 46';
@override
Future<String> get targetPlatformDisplayName async => 'android';
@override @override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm; Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm;
...@@ -937,6 +807,28 @@ class MockAndroidDevice extends Mock implements AndroidDevice { ...@@ -937,6 +807,28 @@ class MockAndroidDevice extends Mock implements AndroidDevice {
@override @override
bool isSupportedForProject(FlutterProject flutterProject) => true; bool isSupportedForProject(FlutterProject flutterProject) => true;
@override
DevicePortForwarder portForwarder;
DeviceLogReader Function() onGetLogReader;
@override
FutureOr<DeviceLogReader> getLogReader({
AndroidApk app,
bool includePastLogs = false,
}) {
return onGetLogReader();
}
@override
OverrideArtifacts get artifactOverrides => null;
@override
final PlatformType platformType = PlatformType.android;
@override
Category get category => Category.mobile;
} }
class FakeIOSDevice extends Fake implements IOSDevice { class FakeIOSDevice extends Fake implements IOSDevice {
......
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