2019-11-27 23:04:02 +00:00
|
|
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
2017-05-21 22:15:44 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
import 'dart:async';
|
2019-07-09 20:10:26 +00:00
|
|
|
|
2020-05-18 19:47:18 +00:00
|
|
|
import 'package:flutter_tools/src/cache.dart';
|
2020-04-16 22:48:21 +00:00
|
|
|
import 'package:vm_service/vm_service.dart' as vm_service;
|
2019-10-15 20:05:47 +00:00
|
|
|
import 'package:file/memory.dart';
|
2020-05-29 22:43:03 +00:00
|
|
|
import 'package:file_testing/file_testing.dart';
|
2019-10-23 03:35:05 +00:00
|
|
|
import 'package:flutter_tools/src/artifacts.dart';
|
2020-01-09 16:18:03 +00:00
|
|
|
import 'package:flutter_tools/src/base/command_help.dart';
|
2019-07-13 23:02:09 +00:00
|
|
|
import 'package:flutter_tools/src/base/common.dart';
|
2019-07-18 17:40:40 +00:00
|
|
|
import 'package:flutter_tools/src/base/context.dart';
|
|
|
|
import 'package:flutter_tools/src/base/file_system.dart';
|
2019-11-01 21:37:17 +00:00
|
|
|
import 'package:flutter_tools/src/base/io.dart' as io;
|
2019-04-16 04:02:20 +00:00
|
|
|
import 'package:flutter_tools/src/build_info.dart';
|
2019-10-23 03:35:05 +00:00
|
|
|
import 'package:flutter_tools/src/compile.dart';
|
2020-04-07 19:17:39 +00:00
|
|
|
import 'package:flutter_tools/src/convert.dart';
|
2019-07-09 20:10:26 +00:00
|
|
|
import 'package:flutter_tools/src/devfs.dart';
|
2017-05-21 22:15:44 +00:00
|
|
|
import 'package:flutter_tools/src/device.dart';
|
2020-01-06 19:04:20 +00:00
|
|
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
2019-10-23 03:35:05 +00:00
|
|
|
import 'package:flutter_tools/src/project.dart';
|
2019-07-29 14:24:02 +00:00
|
|
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
2017-05-21 22:15:44 +00:00
|
|
|
import 'package:flutter_tools/src/resident_runner.dart';
|
2019-10-15 20:05:47 +00:00
|
|
|
import 'package:flutter_tools/src/run_cold.dart';
|
2019-07-09 20:10:26 +00:00
|
|
|
import 'package:flutter_tools/src/run_hot.dart';
|
|
|
|
import 'package:flutter_tools/src/vmservice.dart';
|
2017-05-21 22:15:44 +00:00
|
|
|
import 'package:mockito/mockito.dart';
|
|
|
|
|
2019-07-13 18:51:44 +00:00
|
|
|
import '../src/common.dart';
|
2019-07-18 22:29:06 +00:00
|
|
|
import '../src/context.dart';
|
2019-07-13 18:51:44 +00:00
|
|
|
import '../src/testbed.dart';
|
2017-05-21 22:15:44 +00:00
|
|
|
|
2020-04-28 00:41:42 +00:00
|
|
|
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
|
|
|
|
id: '1',
|
|
|
|
pauseEvent: vm_service.Event(
|
|
|
|
kind: vm_service.EventKind.kResume,
|
|
|
|
timestamp: 0
|
|
|
|
),
|
|
|
|
breakpoints: <vm_service.Breakpoint>[],
|
|
|
|
exceptionPauseMode: null,
|
|
|
|
libraries: <vm_service.LibraryRef>[],
|
|
|
|
livePorts: 0,
|
|
|
|
name: 'test',
|
|
|
|
number: '1',
|
|
|
|
pauseOnExit: false,
|
|
|
|
runnable: true,
|
|
|
|
startTime: 0,
|
|
|
|
);
|
|
|
|
|
|
|
|
final vm_service.Isolate fakePausedIsolate = vm_service.Isolate(
|
|
|
|
id: '1',
|
|
|
|
pauseEvent: vm_service.Event(
|
|
|
|
kind: vm_service.EventKind.kPauseException,
|
|
|
|
timestamp: 0
|
|
|
|
),
|
|
|
|
breakpoints: <vm_service.Breakpoint>[],
|
|
|
|
exceptionPauseMode: null,
|
|
|
|
libraries: <vm_service.LibraryRef>[],
|
|
|
|
livePorts: 0,
|
|
|
|
name: 'test',
|
|
|
|
number: '1',
|
|
|
|
pauseOnExit: false,
|
|
|
|
runnable: true,
|
|
|
|
startTime: 0,
|
|
|
|
);
|
|
|
|
|
|
|
|
final FlutterView fakeFlutterView = FlutterView(
|
|
|
|
id: 'a',
|
|
|
|
uiIsolate: fakeUnpausedIsolate,
|
|
|
|
);
|
|
|
|
|
2020-05-05 19:09:51 +00:00
|
|
|
final FakeVmServiceRequest listViews = FakeVmServiceRequest(
|
|
|
|
method: kListViewsMethod,
|
|
|
|
jsonResponse: <String, Object>{
|
|
|
|
'views': <Object>[
|
|
|
|
fakeFlutterView.toJson(),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2019-07-09 20:10:26 +00:00
|
|
|
void main() {
|
2019-07-18 17:40:40 +00:00
|
|
|
final Uri testUri = Uri.parse('foo://bar');
|
|
|
|
Testbed testbed;
|
|
|
|
MockFlutterDevice mockFlutterDevice;
|
|
|
|
MockVMService mockVMService;
|
|
|
|
MockDevFS mockDevFS;
|
|
|
|
ResidentRunner residentRunner;
|
|
|
|
MockDevice mockDevice;
|
2020-04-20 22:15:54 +00:00
|
|
|
FakeVmServiceHost fakeVmServiceHost;
|
2019-07-18 17:40:40 +00:00
|
|
|
|
|
|
|
setUp(() {
|
|
|
|
testbed = Testbed(setup: () {
|
2020-04-20 21:02:49 +00:00
|
|
|
globals.fs.file('.packages').writeAsStringSync('\n');
|
2020-01-06 19:04:20 +00:00
|
|
|
globals.fs.file(globals.fs.path.join('build', 'app.dill'))
|
2019-09-12 19:45:53 +00:00
|
|
|
..createSync(recursive: true)
|
|
|
|
..writeAsStringSync('ABC');
|
2019-07-18 17:40:40 +00:00
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
mockFlutterDevice = MockFlutterDevice();
|
|
|
|
mockDevice = MockDevice();
|
|
|
|
mockVMService = MockVMService();
|
|
|
|
mockDevFS = MockDevFS();
|
2020-04-28 00:41:42 +00:00
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
// DevFS Mocks
|
|
|
|
when(mockDevFS.lastCompiled).thenReturn(DateTime(2000));
|
|
|
|
when(mockDevFS.sources).thenReturn(<Uri>[]);
|
2019-07-30 19:18:15 +00:00
|
|
|
when(mockDevFS.baseUri).thenReturn(Uri());
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevFS.destroy()).thenAnswer((Invocation invocation) async { });
|
2019-07-29 14:24:02 +00:00
|
|
|
when(mockDevFS.assetPathsToEvict).thenReturn(<String>{});
|
2019-07-18 17:40:40 +00:00
|
|
|
// FlutterDevice Mocks.
|
|
|
|
when(mockFlutterDevice.updateDevFS(
|
2020-04-20 21:02:49 +00:00
|
|
|
invalidatedFiles: anyNamed('invalidatedFiles'),
|
|
|
|
mainUri: anyNamed('mainUri'),
|
2019-07-18 17:40:40 +00:00
|
|
|
target: anyNamed('target'),
|
|
|
|
bundle: anyNamed('bundle'),
|
|
|
|
firstBuildTime: anyNamed('firstBuildTime'),
|
|
|
|
bundleFirstUpload: anyNamed('bundleFirstUpload'),
|
|
|
|
bundleDirty: anyNamed('bundleDirty'),
|
|
|
|
fullRestart: anyNamed('fullRestart'),
|
|
|
|
projectRootPath: anyNamed('projectRootPath'),
|
|
|
|
pathToReload: anyNamed('pathToReload'),
|
2019-07-31 23:19:22 +00:00
|
|
|
dillOutputPath: anyNamed('dillOutputPath'),
|
2020-04-20 21:02:49 +00:00
|
|
|
packageConfig: anyNamed('packageConfig'),
|
2019-07-18 17:40:40 +00:00
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return UpdateFSReport(
|
|
|
|
success: true,
|
|
|
|
syncedBytes: 0,
|
|
|
|
invalidatedSourcesCount: 0,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
when(mockFlutterDevice.devFS).thenReturn(mockDevFS);
|
|
|
|
when(mockFlutterDevice.device).thenReturn(mockDevice);
|
|
|
|
when(mockFlutterDevice.stopEchoingDeviceLog()).thenAnswer((Invocation invocation) async { });
|
2019-11-21 02:51:25 +00:00
|
|
|
when(mockFlutterDevice.observatoryUris).thenAnswer((_) => Stream<Uri>.value(testUri));
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockFlutterDevice.connect(
|
|
|
|
reloadSources: anyNamed('reloadSources'),
|
|
|
|
restart: anyNamed('restart'),
|
2019-09-24 06:06:09 +00:00
|
|
|
compileExpression: anyNamed('compileExpression'),
|
2020-05-27 17:10:41 +00:00
|
|
|
getSkSLMethod: anyNamed('getSkSLMethod'),
|
2019-07-18 17:40:40 +00:00
|
|
|
)).thenAnswer((Invocation invocation) async { });
|
|
|
|
when(mockFlutterDevice.setupDevFS(any, any, packagesFilePath: anyNamed('packagesFilePath')))
|
|
|
|
.thenAnswer((Invocation invocation) async {
|
|
|
|
return testUri;
|
2019-07-09 20:10:26 +00:00
|
|
|
});
|
2020-04-20 22:15:54 +00:00
|
|
|
when(mockFlutterDevice.vmService).thenAnswer((Invocation invocation) {
|
|
|
|
return fakeVmServiceHost.vmService;
|
|
|
|
});
|
2020-04-29 18:52:46 +00:00
|
|
|
when(mockFlutterDevice.reloadSources(any, pause: anyNamed('pause'))).thenAnswer((Invocation invocation) async {
|
|
|
|
return <Future<vm_service.ReloadReport>>[
|
|
|
|
Future<vm_service.ReloadReport>.value(vm_service.ReloadReport.parse(<String, dynamic>{
|
|
|
|
'type': 'ReloadReport',
|
|
|
|
'success': true,
|
|
|
|
'details': <String, dynamic>{
|
|
|
|
'loadedLibraryCount': 1,
|
|
|
|
'finalLibraryCount': 1,
|
|
|
|
'receivedLibraryCount': 1,
|
|
|
|
'receivedClassesCount': 1,
|
|
|
|
'receivedProceduresCount': 1,
|
|
|
|
},
|
|
|
|
})),
|
|
|
|
];
|
2019-07-18 17:40:40 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-04-28 00:41:42 +00:00
|
|
|
test('FlutterDevice can list views with a filter', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
]);
|
|
|
|
final MockDevice mockDevice = MockDevice();
|
|
|
|
final FlutterDevice flutterDevice = FlutterDevice(
|
|
|
|
mockDevice,
|
|
|
|
buildInfo: BuildInfo.debug,
|
|
|
|
viewFilter: 'b', // Does not match name of `fakeFlutterView`.
|
|
|
|
);
|
|
|
|
|
|
|
|
flutterDevice.vmService = fakeVmServiceHost.vmService;
|
|
|
|
}));
|
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
test('ResidentRunner can attach to device successfully', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
|
|
|
|
final Completer<void> onAppStart = Completer<void>.sync();
|
2019-12-10 18:26:14 +00:00
|
|
|
final Future<int> result = residentRunner.attach(
|
|
|
|
appStartedCompleter: onAppStart,
|
|
|
|
connectionInfoCompleter: onConnectionInfo,
|
|
|
|
);
|
|
|
|
final Future<DebugConnectionInfo> connectionInfo = onConnectionInfo.future;
|
|
|
|
|
|
|
|
expect(await result, 0);
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.initLogReader()).called(1);
|
|
|
|
|
|
|
|
expect(onConnectionInfo.isCompleted, true);
|
|
|
|
expect((await connectionInfo).baseUri, 'foo://bar');
|
|
|
|
expect(onAppStart.isCompleted, true);
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-12-10 18:26:14 +00:00
|
|
|
}));
|
|
|
|
|
2020-06-03 19:00:03 +00:00
|
|
|
test('ResidentRunner suppresses errors for the initial compilation', () => testbed.run(() async {
|
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart'))
|
|
|
|
.createSync(recursive: true);
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
|
|
|
final MockResidentCompiler residentCompiler = MockResidentCompiler();
|
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
|
|
|
);
|
|
|
|
when(mockFlutterDevice.generator).thenReturn(residentCompiler);
|
|
|
|
when(residentCompiler.recompile(
|
|
|
|
any,
|
|
|
|
any,
|
|
|
|
outputPath: anyNamed('outputPath'),
|
|
|
|
packageConfig: anyNamed('packageConfig'),
|
|
|
|
suppressErrors: true,
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return const CompilerOutput('foo', 0 ,<Uri>[]);
|
|
|
|
});
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(await residentRunner.run(), 0);
|
|
|
|
verify(residentCompiler.recompile(
|
|
|
|
any,
|
|
|
|
any,
|
|
|
|
outputPath: anyNamed('outputPath'),
|
|
|
|
packageConfig: anyNamed('packageConfig'),
|
|
|
|
suppressErrors: true,
|
|
|
|
)).called(1);
|
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner does not suppressErrors if running with an applicationBinary', () => testbed.run(() async {
|
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart'))
|
|
|
|
.createSync(recursive: true);
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
|
|
|
final MockResidentCompiler residentCompiler = MockResidentCompiler();
|
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
applicationBinary: globals.fs.file('app.apk'),
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
|
|
|
);
|
|
|
|
when(mockFlutterDevice.generator).thenReturn(residentCompiler);
|
|
|
|
when(residentCompiler.recompile(
|
|
|
|
any,
|
|
|
|
any,
|
|
|
|
outputPath: anyNamed('outputPath'),
|
|
|
|
packageConfig: anyNamed('packageConfig'),
|
|
|
|
suppressErrors: false,
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return const CompilerOutput('foo', 0, <Uri>[]);
|
|
|
|
});
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(await residentRunner.run(), 0);
|
|
|
|
verify(residentCompiler.recompile(
|
|
|
|
any,
|
|
|
|
any,
|
|
|
|
outputPath: anyNamed('outputPath'),
|
|
|
|
packageConfig: anyNamed('packageConfig'),
|
|
|
|
suppressErrors: false,
|
|
|
|
)).called(1);
|
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
|
|
|
}));
|
|
|
|
|
2019-12-10 18:26:14 +00:00
|
|
|
test('ResidentRunner can attach to device successfully with --fast-start', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getIsolate',
|
|
|
|
args: <String, Object>{
|
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
|
|
|
},
|
|
|
|
jsonResponse: fakeUnpausedIsolate.toJson(),
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getVM',
|
|
|
|
jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson(),
|
|
|
|
),
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
const FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'streamListen',
|
|
|
|
args: <String, Object>{
|
|
|
|
'streamId': 'Isolate',
|
|
|
|
}
|
|
|
|
),
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: kRunInViewMethod,
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'viewId': fakeFlutterView.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'mainScript': 'lib/main.dart.dill',
|
|
|
|
'assetDirectory': 'build/flutter_assets',
|
|
|
|
}
|
|
|
|
),
|
|
|
|
FakeVmServiceStreamResponse(
|
|
|
|
streamId: 'Isolate',
|
|
|
|
event: vm_service.Event(
|
|
|
|
timestamp: 0,
|
|
|
|
kind: vm_service.EventKind.kIsolateRunnable,
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]);
|
2019-12-10 18:26:14 +00:00
|
|
|
when(mockDevice.supportsHotRestart).thenReturn(true);
|
|
|
|
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
|
|
|
|
return 'Example';
|
|
|
|
});
|
|
|
|
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
|
|
|
|
return TargetPlatform.android_arm;
|
|
|
|
});
|
|
|
|
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
2020-04-20 22:15:54 +00:00
|
|
|
debuggingOptions: DebuggingOptions.enabled(
|
|
|
|
BuildInfo.debug,
|
|
|
|
fastStart: true,
|
|
|
|
startPaused: true,
|
|
|
|
),
|
2019-12-10 18:26:14 +00:00
|
|
|
);
|
|
|
|
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
|
|
|
|
final Completer<void> onAppStart = Completer<void>.sync();
|
2019-07-18 17:40:40 +00:00
|
|
|
final Future<int> result = residentRunner.attach(
|
|
|
|
appStartedCompleter: onAppStart,
|
|
|
|
connectionInfoCompleter: onConnectionInfo,
|
|
|
|
);
|
|
|
|
final Future<DebugConnectionInfo> connectionInfo = onConnectionInfo.future;
|
|
|
|
|
|
|
|
expect(await result, 0);
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.initLogReader()).called(1);
|
|
|
|
|
|
|
|
expect(onConnectionInfo.isCompleted, true);
|
|
|
|
expect((await connectionInfo).baseUri, 'foo://bar');
|
|
|
|
expect(onAppStart.isCompleted, true);
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner can handle an RPC exception from hot reload', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
|
|
|
|
return 'Example';
|
|
|
|
});
|
|
|
|
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
|
|
|
|
return TargetPlatform.android_arm;
|
|
|
|
});
|
|
|
|
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
|
|
|
|
final Completer<void> onAppStart = Completer<void>.sync();
|
|
|
|
unawaited(residentRunner.attach(
|
|
|
|
appStartedCompleter: onAppStart,
|
|
|
|
connectionInfoCompleter: onConnectionInfo,
|
|
|
|
));
|
|
|
|
await onAppStart.future;
|
|
|
|
when(mockFlutterDevice.updateDevFS(
|
2020-04-20 21:02:49 +00:00
|
|
|
mainUri: anyNamed('mainUri'),
|
2019-07-18 17:40:40 +00:00
|
|
|
target: anyNamed('target'),
|
|
|
|
bundle: anyNamed('bundle'),
|
|
|
|
firstBuildTime: anyNamed('firstBuildTime'),
|
|
|
|
bundleFirstUpload: anyNamed('bundleFirstUpload'),
|
|
|
|
bundleDirty: anyNamed('bundleDirty'),
|
|
|
|
fullRestart: anyNamed('fullRestart'),
|
|
|
|
projectRootPath: anyNamed('projectRootPath'),
|
|
|
|
pathToReload: anyNamed('pathToReload'),
|
|
|
|
invalidatedFiles: anyNamed('invalidatedFiles'),
|
2019-07-31 23:19:22 +00:00
|
|
|
dillOutputPath: anyNamed('dillOutputPath'),
|
2020-04-20 21:02:49 +00:00
|
|
|
packageConfig: anyNamed('packageConfig'),
|
2020-04-08 19:33:33 +00:00
|
|
|
)).thenThrow(vm_service.RPCError('something bad happened', 666, ''));
|
2019-07-18 17:40:40 +00:00
|
|
|
|
|
|
|
final OperationResult result = await residentRunner.restart(fullRestart: false);
|
|
|
|
expect(result.fatal, true);
|
|
|
|
expect(result.code, 1);
|
2020-03-06 20:14:29 +00:00
|
|
|
verify(globals.flutterUsage.sendEvent('hot', 'exception', parameters: <String, String>{
|
2019-07-29 14:24:02 +00:00
|
|
|
cdKey(CustomDimensions.hotEventTargetPlatform):
|
|
|
|
getNameForTargetPlatform(TargetPlatform.android_arm),
|
|
|
|
cdKey(CustomDimensions.hotEventSdkName): 'Example',
|
|
|
|
cdKey(CustomDimensions.hotEventEmulator): 'false',
|
|
|
|
cdKey(CustomDimensions.hotEventFullRestart): 'false',
|
2019-07-18 17:40:40 +00:00
|
|
|
})).called(1);
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
Usage: () => MockUsage(),
|
|
|
|
}));
|
|
|
|
|
2019-07-29 14:24:02 +00:00
|
|
|
test('ResidentRunner can send target platform to analytics from hot reload', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getIsolate',
|
|
|
|
args: <String, Object>{
|
|
|
|
'isolateId': '1',
|
|
|
|
},
|
|
|
|
jsonResponse: fakeUnpausedIsolate.toJson(),
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.reassemble',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
]);
|
2019-07-29 14:24:02 +00:00
|
|
|
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
|
|
|
|
return 'Example';
|
|
|
|
});
|
|
|
|
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
|
|
|
|
return TargetPlatform.android_arm;
|
|
|
|
});
|
|
|
|
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
|
|
|
|
final Completer<void> onAppStart = Completer<void>.sync();
|
|
|
|
unawaited(residentRunner.attach(
|
|
|
|
appStartedCompleter: onAppStart,
|
|
|
|
connectionInfoCompleter: onConnectionInfo,
|
|
|
|
));
|
|
|
|
|
|
|
|
final OperationResult result = await residentRunner.restart(fullRestart: false);
|
|
|
|
expect(result.fatal, false);
|
|
|
|
expect(result.code, 0);
|
2020-03-06 20:14:29 +00:00
|
|
|
expect(verify(globals.flutterUsage.sendEvent('hot', 'reload',
|
2019-07-29 14:24:02 +00:00
|
|
|
parameters: captureAnyNamed('parameters'))).captured[0],
|
|
|
|
containsPair(cdKey(CustomDimensions.hotEventTargetPlatform),
|
2019-09-24 06:06:09 +00:00
|
|
|
getNameForTargetPlatform(TargetPlatform.android_arm)),
|
2019-07-29 14:24:02 +00:00
|
|
|
);
|
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
Usage: () => MockUsage(),
|
|
|
|
}));
|
|
|
|
|
2019-07-30 19:18:15 +00:00
|
|
|
test('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getIsolate',
|
|
|
|
args: <String, Object>{
|
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
|
|
|
},
|
|
|
|
jsonResponse: fakeUnpausedIsolate.toJson(),
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getVM',
|
|
|
|
jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson(),
|
|
|
|
),
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
const FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'streamListen',
|
|
|
|
args: <String, Object>{
|
|
|
|
'streamId': 'Isolate',
|
|
|
|
},
|
|
|
|
),
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: kRunInViewMethod,
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'viewId': fakeFlutterView.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'mainScript': 'lib/main.dart.dill',
|
|
|
|
'assetDirectory': 'build/flutter_assets',
|
|
|
|
},
|
|
|
|
),
|
|
|
|
FakeVmServiceStreamResponse(
|
|
|
|
streamId: 'Isolate',
|
|
|
|
event: vm_service.Event(
|
|
|
|
timestamp: 0,
|
|
|
|
kind: vm_service.EventKind.kIsolateRunnable,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
]);
|
2019-07-30 19:18:15 +00:00
|
|
|
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
|
|
|
|
return 'Example';
|
|
|
|
});
|
|
|
|
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
|
|
|
|
return TargetPlatform.android_arm;
|
|
|
|
});
|
|
|
|
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
when(mockDevice.supportsHotRestart).thenReturn(true);
|
|
|
|
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
|
|
|
|
final Completer<void> onAppStart = Completer<void>.sync();
|
|
|
|
unawaited(residentRunner.attach(
|
|
|
|
appStartedCompleter: onAppStart,
|
|
|
|
connectionInfoCompleter: onConnectionInfo,
|
|
|
|
));
|
|
|
|
|
|
|
|
final OperationResult result = await residentRunner.restart(fullRestart: true);
|
|
|
|
expect(result.fatal, false);
|
|
|
|
expect(result.code, 0);
|
2020-03-06 20:14:29 +00:00
|
|
|
expect(verify(globals.flutterUsage.sendEvent('hot', 'restart',
|
2019-07-30 19:18:15 +00:00
|
|
|
parameters: captureAnyNamed('parameters'))).captured[0],
|
|
|
|
containsPair(cdKey(CustomDimensions.hotEventTargetPlatform),
|
2019-09-24 06:06:09 +00:00
|
|
|
getNameForTargetPlatform(TargetPlatform.android_arm)),
|
2019-07-30 19:18:15 +00:00
|
|
|
);
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-30 19:18:15 +00:00
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
Usage: () => MockUsage(),
|
|
|
|
}));
|
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
test('ResidentRunner Can handle an RPC exception from hot restart', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
|
|
|
|
return 'Example';
|
|
|
|
});
|
|
|
|
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
|
|
|
|
return TargetPlatform.android_arm;
|
|
|
|
});
|
|
|
|
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
when(mockDevice.supportsHotRestart).thenReturn(true);
|
|
|
|
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
|
|
|
|
final Completer<void> onAppStart = Completer<void>.sync();
|
|
|
|
unawaited(residentRunner.attach(
|
|
|
|
appStartedCompleter: onAppStart,
|
|
|
|
connectionInfoCompleter: onConnectionInfo,
|
|
|
|
));
|
|
|
|
await onAppStart.future;
|
|
|
|
when(mockFlutterDevice.updateDevFS(
|
2020-04-20 21:02:49 +00:00
|
|
|
mainUri: anyNamed('mainUri'),
|
2019-07-18 17:40:40 +00:00
|
|
|
target: anyNamed('target'),
|
|
|
|
bundle: anyNamed('bundle'),
|
|
|
|
firstBuildTime: anyNamed('firstBuildTime'),
|
|
|
|
bundleFirstUpload: anyNamed('bundleFirstUpload'),
|
|
|
|
bundleDirty: anyNamed('bundleDirty'),
|
|
|
|
fullRestart: anyNamed('fullRestart'),
|
|
|
|
projectRootPath: anyNamed('projectRootPath'),
|
|
|
|
pathToReload: anyNamed('pathToReload'),
|
|
|
|
invalidatedFiles: anyNamed('invalidatedFiles'),
|
2019-07-31 23:19:22 +00:00
|
|
|
dillOutputPath: anyNamed('dillOutputPath'),
|
2020-04-20 21:02:49 +00:00
|
|
|
packageConfig: anyNamed('packageConfig'),
|
2020-04-08 19:33:33 +00:00
|
|
|
)).thenThrow(vm_service.RPCError('something bad happened', 666, ''));
|
2019-07-18 17:40:40 +00:00
|
|
|
|
|
|
|
final OperationResult result = await residentRunner.restart(fullRestart: true);
|
|
|
|
expect(result.fatal, true);
|
|
|
|
expect(result.code, 1);
|
2020-03-06 20:14:29 +00:00
|
|
|
verify(globals.flutterUsage.sendEvent('hot', 'exception', parameters: <String, String>{
|
2019-07-29 14:24:02 +00:00
|
|
|
cdKey(CustomDimensions.hotEventTargetPlatform):
|
|
|
|
getNameForTargetPlatform(TargetPlatform.android_arm),
|
|
|
|
cdKey(CustomDimensions.hotEventSdkName): 'Example',
|
|
|
|
cdKey(CustomDimensions.hotEventEmulator): 'false',
|
|
|
|
cdKey(CustomDimensions.hotEventFullRestart): 'true',
|
2019-07-18 17:40:40 +00:00
|
|
|
})).called(1);
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
Usage: () => MockUsage(),
|
|
|
|
}));
|
|
|
|
|
2019-09-11 19:57:43 +00:00
|
|
|
test('ResidentRunner uses temp directory when there is no output dill path', () => testbed.run(() {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-10-07 23:43:04 +00:00
|
|
|
expect(residentRunner.artifactDirectory.path, contains('flutter_tool.'));
|
2019-09-11 19:57:43 +00:00
|
|
|
|
|
|
|
final ResidentRunner otherRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
2020-01-06 19:04:20 +00:00
|
|
|
dillOutputPath: globals.fs.path.join('foobar', 'app.dill'),
|
2019-09-11 19:57:43 +00:00
|
|
|
);
|
|
|
|
expect(otherRunner.artifactDirectory.path, contains('foobar'));
|
|
|
|
}));
|
|
|
|
|
2020-06-04 17:17:43 +00:00
|
|
|
test('ResidentRunner deletes artifact directory on preExit', () => testbed.run(() async {
|
2020-05-29 22:43:03 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2020-06-04 17:17:43 +00:00
|
|
|
residentRunner.artifactDirectory.childFile('app.dill').createSync();
|
2020-05-29 22:43:03 +00:00
|
|
|
await residentRunner.preExit();
|
|
|
|
|
2020-06-04 17:17:43 +00:00
|
|
|
expect(residentRunner.artifactDirectory, isNot(exists));
|
2020-05-29 22:43:03 +00:00
|
|
|
}));
|
|
|
|
|
2020-05-18 19:47:18 +00:00
|
|
|
test('ResidentRunner can run source generation', () => testbed.run(() async {
|
|
|
|
final FakeProcessManager processManager = globals.processManager as FakeProcessManager;
|
|
|
|
final Directory dependencies = globals.fs.directory(
|
|
|
|
globals.fs.path.join('build', '6ec2559087977927717927ede0a147f1'));
|
|
|
|
processManager.addCommand(FakeCommand(
|
|
|
|
command: <String>[
|
|
|
|
globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
|
|
|
|
globals.fs.path.join(Cache.flutterRoot, 'dev', 'tools', 'localization', 'bin', 'gen_l10n.dart'),
|
|
|
|
'--gen-inputs-and-outputs-list=${dependencies.absolute.path}',
|
|
|
|
],
|
|
|
|
onRun: () {
|
|
|
|
dependencies
|
|
|
|
.childFile('gen_l10n_inputs_and_outputs.json')
|
|
|
|
..createSync()
|
|
|
|
..writeAsStringSync('{"inputs":[],"outputs":[]}');
|
|
|
|
}
|
|
|
|
));
|
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'l10n', 'foo.arb'))
|
|
|
|
.createSync(recursive: true);
|
|
|
|
globals.fs.file('l10n.yaml').createSync();
|
|
|
|
|
|
|
|
await residentRunner.runSourceGenerators();
|
|
|
|
|
|
|
|
expect(testLogger.errorText, isEmpty);
|
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[]),
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner can run source generation - generation fails', () => testbed.run(() async {
|
|
|
|
final FakeProcessManager processManager = globals.processManager as FakeProcessManager;
|
|
|
|
final Directory dependencies = globals.fs.directory(
|
|
|
|
globals.fs.path.join('build', '6ec2559087977927717927ede0a147f1'));
|
|
|
|
processManager.addCommand(FakeCommand(
|
|
|
|
command: <String>[
|
|
|
|
globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
|
|
|
|
globals.fs.path.join(Cache.flutterRoot, 'dev', 'tools', 'localization', 'bin', 'gen_l10n.dart'),
|
|
|
|
'--gen-inputs-and-outputs-list=${dependencies.absolute.path}',
|
|
|
|
],
|
|
|
|
exitCode: 1,
|
|
|
|
stderr: 'stderr'
|
|
|
|
));
|
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'l10n', 'foo.arb'))
|
|
|
|
.createSync(recursive: true);
|
|
|
|
globals.fs.file('l10n.yaml').createSync();
|
|
|
|
|
|
|
|
await residentRunner.runSourceGenerators();
|
|
|
|
|
|
|
|
expect(testLogger.errorText, allOf(
|
|
|
|
contains('stderr'), // Message from gen_l10n.dart
|
|
|
|
contains('Exception') // Message from build_system
|
|
|
|
));
|
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[]),
|
|
|
|
}));
|
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
test('ResidentRunner printHelpDetails', () => testbed.run(() {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.supportsHotRestart).thenReturn(true);
|
|
|
|
when(mockDevice.supportsScreenshot).thenReturn(true);
|
|
|
|
|
|
|
|
residentRunner.printHelp(details: true);
|
|
|
|
|
2020-01-11 00:53:01 +00:00
|
|
|
final CommandHelp commandHelp = residentRunner.commandHelp;
|
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
// supports service protocol
|
|
|
|
expect(residentRunner.supportsServiceProtocol, true);
|
|
|
|
// isRunningDebug
|
|
|
|
expect(residentRunner.isRunningDebug, true);
|
2020-03-13 14:02:34 +00:00
|
|
|
// does not support CanvasKit
|
|
|
|
expect(residentRunner.supportsCanvasKit, false);
|
2020-04-07 19:17:39 +00:00
|
|
|
// does support SkSL
|
|
|
|
expect(residentRunner.supportsWriteSkSL, true);
|
2020-01-09 16:18:03 +00:00
|
|
|
// commands
|
|
|
|
expect(testLogger.statusText, equals(
|
|
|
|
<dynamic>[
|
|
|
|
'Flutter run key commands.',
|
2020-01-11 00:53:01 +00:00
|
|
|
commandHelp.r,
|
|
|
|
commandHelp.R,
|
|
|
|
commandHelp.h,
|
2020-02-06 23:53:04 +00:00
|
|
|
commandHelp.c,
|
2020-01-11 00:53:01 +00:00
|
|
|
commandHelp.q,
|
|
|
|
commandHelp.s,
|
|
|
|
commandHelp.w,
|
|
|
|
commandHelp.t,
|
|
|
|
commandHelp.L,
|
|
|
|
commandHelp.S,
|
|
|
|
commandHelp.U,
|
|
|
|
commandHelp.i,
|
|
|
|
commandHelp.p,
|
|
|
|
commandHelp.o,
|
|
|
|
commandHelp.z,
|
2020-05-18 19:47:18 +00:00
|
|
|
commandHelp.g,
|
2020-04-07 19:17:39 +00:00
|
|
|
commandHelp.M,
|
2020-04-05 02:51:01 +00:00
|
|
|
commandHelp.v,
|
2020-01-11 00:53:01 +00:00
|
|
|
commandHelp.P,
|
|
|
|
commandHelp.a,
|
2020-01-09 16:18:03 +00:00
|
|
|
'An Observatory debugger and profiler on null is available at: null',
|
|
|
|
''
|
|
|
|
].join('\n')
|
|
|
|
));
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
|
|
|
|
2020-04-07 19:17:39 +00:00
|
|
|
test('ResidentRunner does support CanvasKit', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2020-05-05 19:09:51 +00:00
|
|
|
|
2020-03-13 14:02:34 +00:00
|
|
|
expect(() => residentRunner.toggleCanvaskit(),
|
|
|
|
throwsA(isA<Exception>()));
|
|
|
|
}));
|
|
|
|
|
2020-04-07 19:17:39 +00:00
|
|
|
test('ResidentRunner handles writeSkSL returning no data', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: kGetSkSLsMethod,
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'viewId': fakeFlutterView.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
},
|
|
|
|
jsonResponse: <String, Object>{
|
|
|
|
'SkSLs': <String, Object>{}
|
|
|
|
}
|
2020-05-05 19:09:51 +00:00
|
|
|
),
|
2020-04-20 22:15:54 +00:00
|
|
|
]);
|
2020-04-07 19:17:39 +00:00
|
|
|
await residentRunner.writeSkSL();
|
|
|
|
|
|
|
|
expect(testLogger.statusText, contains('No data was receieved'));
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2020-04-07 19:17:39 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner can write SkSL data to a unique file with engine revision, platform, and device name', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: kGetSkSLsMethod,
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'viewId': fakeFlutterView.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
},
|
|
|
|
jsonResponse: <String, Object>{
|
|
|
|
'SkSLs': <String, Object>{
|
|
|
|
'A': 'B',
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
]);
|
2020-04-07 19:17:39 +00:00
|
|
|
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
|
|
|
|
return TargetPlatform.android_arm;
|
|
|
|
});
|
|
|
|
when(mockDevice.name).thenReturn('test device');
|
|
|
|
await residentRunner.writeSkSL();
|
|
|
|
|
2020-05-08 16:44:03 +00:00
|
|
|
expect(testLogger.statusText, contains('flutter_01.sksl.json'));
|
|
|
|
expect(globals.fs.file('flutter_01.sksl.json'), exists);
|
|
|
|
expect(json.decode(globals.fs.file('flutter_01.sksl.json').readAsStringSync()), <String, Object>{
|
2020-04-30 20:39:08 +00:00
|
|
|
'platform': 'android',
|
2020-04-07 19:17:39 +00:00
|
|
|
'name': 'test device',
|
|
|
|
'engineRevision': '42.2', // From FakeFlutterVersion
|
|
|
|
'data': <String, Object>{'A': 'B'}
|
|
|
|
});
|
2020-04-20 22:15:54 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2020-04-07 19:17:39 +00:00
|
|
|
}));
|
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
test('ResidentRunner can take screenshot on debug device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.debugAllowBanner',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'enabled': 'false',
|
|
|
|
},
|
|
|
|
),
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.debugAllowBanner',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'enabled': 'true',
|
|
|
|
},
|
|
|
|
)
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.supportsScreenshot).thenReturn(true);
|
|
|
|
when(mockDevice.takeScreenshot(any))
|
2019-09-24 19:03:37 +00:00
|
|
|
.thenAnswer((Invocation invocation) async {
|
2019-11-24 05:54:43 +00:00
|
|
|
final File file = invocation.positionalArguments.first as File;
|
2019-09-24 19:03:37 +00:00
|
|
|
file.writeAsBytesSync(List<int>.generate(1024, (int i) => i));
|
|
|
|
});
|
2017-05-21 22:15:44 +00:00
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
await residentRunner.screenshot(mockFlutterDevice);
|
2019-01-18 18:09:44 +00:00
|
|
|
|
2019-11-24 05:54:43 +00:00
|
|
|
expect(testLogger.statusText, contains('1kB'));
|
2020-04-20 22:15:54 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
2017-05-21 22:15:44 +00:00
|
|
|
|
2020-04-20 22:15:54 +00:00
|
|
|
test('ResidentRunner clears the screen when it should', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2020-02-06 23:53:04 +00:00
|
|
|
const String message = 'This should be cleared';
|
|
|
|
expect(testLogger.statusText, equals(''));
|
|
|
|
testLogger.printStatus(message);
|
|
|
|
expect(testLogger.statusText, equals(message + '\n')); // printStatus makes a newline
|
|
|
|
residentRunner.clearScreen();
|
|
|
|
expect(testLogger.statusText, equals(''));
|
|
|
|
}));
|
|
|
|
|
2020-04-20 22:15:54 +00:00
|
|
|
test('ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws RpcError', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.debugAllowBanner',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'enabled': 'false',
|
|
|
|
},
|
|
|
|
// Failed response,
|
|
|
|
errorCode: RPCErrorCodes.kInternalError,
|
|
|
|
)
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.supportsScreenshot).thenReturn(true);
|
2020-04-20 22:15:54 +00:00
|
|
|
await residentRunner.screenshot(mockFlutterDevice);
|
2019-07-18 17:40:40 +00:00
|
|
|
|
2020-04-20 22:15:54 +00:00
|
|
|
expect(testLogger.errorText, contains('Error'));
|
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner bails taking screenshot on debug device if debugAllowBanner during second request', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.debugAllowBanner',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'enabled': 'false',
|
|
|
|
},
|
|
|
|
),
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.debugAllowBanner',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'enabled': 'true',
|
|
|
|
},
|
|
|
|
// Failed response,
|
|
|
|
errorCode: RPCErrorCodes.kInternalError,
|
|
|
|
)
|
|
|
|
]);
|
|
|
|
when(mockDevice.supportsScreenshot).thenReturn(true);
|
2019-07-18 17:40:40 +00:00
|
|
|
await residentRunner.screenshot(mockFlutterDevice);
|
|
|
|
|
2019-11-24 05:54:43 +00:00
|
|
|
expect(testLogger.errorText, contains('Error'));
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner bails taking screenshot on debug device if takeScreenshot throws', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-05-05 19:09:51 +00:00
|
|
|
listViews,
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.debugAllowBanner',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'enabled': 'false',
|
|
|
|
},
|
|
|
|
),
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.debugAllowBanner',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
'enabled': 'true',
|
|
|
|
},
|
|
|
|
),
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.supportsScreenshot).thenReturn(true);
|
|
|
|
when(mockDevice.takeScreenshot(any)).thenThrow(Exception());
|
|
|
|
|
|
|
|
await residentRunner.screenshot(mockFlutterDevice);
|
|
|
|
|
2019-11-24 05:54:43 +00:00
|
|
|
expect(testLogger.errorText, contains('Error'));
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
|
|
|
|
2020-02-11 19:58:27 +00:00
|
|
|
test("ResidentRunner can't take screenshot on device without support", () => testbed.run(() {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.supportsScreenshot).thenReturn(false);
|
|
|
|
|
|
|
|
expect(() => residentRunner.screenshot(mockFlutterDevice),
|
2020-01-27 22:36:02 +00:00
|
|
|
throwsAssertionError);
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner does not toggle banner in non-debug mode', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
|
|
|
);
|
|
|
|
when(mockDevice.supportsScreenshot).thenReturn(true);
|
|
|
|
when(mockDevice.takeScreenshot(any))
|
2019-09-24 19:03:37 +00:00
|
|
|
.thenAnswer((Invocation invocation) async {
|
2019-11-24 05:54:43 +00:00
|
|
|
final File file = invocation.positionalArguments.first as File;
|
2019-09-24 19:03:37 +00:00
|
|
|
file.writeAsBytesSync(List<int>.generate(1024, (int i) => i));
|
|
|
|
});
|
2019-07-18 17:40:40 +00:00
|
|
|
|
|
|
|
await residentRunner.screenshot(mockFlutterDevice);
|
|
|
|
|
2019-11-24 05:54:43 +00:00
|
|
|
expect(testLogger.statusText, contains('1kB'));
|
2020-04-20 22:15:54 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
test('FlutterDevice will not exit a paused isolate', () => testbed.run(() async {
|
2020-04-28 00:41:42 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: '_flutter.listViews',
|
|
|
|
jsonResponse: <String, Object>{
|
|
|
|
'views': <Object>[
|
|
|
|
fakeFlutterView.toJson(),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getIsolate',
|
|
|
|
args: <String, Object>{
|
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
|
|
|
},
|
|
|
|
jsonResponse: fakePausedIsolate.toJson(),
|
|
|
|
),
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
final TestFlutterDevice flutterDevice = TestFlutterDevice(
|
|
|
|
mockDevice,
|
|
|
|
);
|
2020-04-20 22:15:54 +00:00
|
|
|
flutterDevice.vmService = fakeVmServiceHost.vmService;
|
2019-07-18 17:40:40 +00:00
|
|
|
when(mockDevice.supportsFlutterExit).thenReturn(true);
|
|
|
|
|
|
|
|
await flutterDevice.exitApps();
|
|
|
|
|
|
|
|
verify(mockDevice.stopApp(any)).called(1);
|
2020-04-20 22:15:54 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
|
|
|
|
2020-05-05 19:09:51 +00:00
|
|
|
test('FlutterDevice can exit from a release mode isolate with no VmService', () => testbed.run(() async {
|
|
|
|
final TestFlutterDevice flutterDevice = TestFlutterDevice(
|
|
|
|
mockDevice,
|
|
|
|
);
|
|
|
|
when(mockDevice.supportsFlutterExit).thenReturn(true);
|
|
|
|
|
|
|
|
await flutterDevice.exitApps();
|
|
|
|
|
|
|
|
verify(mockDevice.stopApp(any)).called(1);
|
|
|
|
}));
|
|
|
|
|
2020-04-29 22:08:34 +00:00
|
|
|
test('FlutterDevice will call stopApp if the exit request times out', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: '_flutter.listViews',
|
|
|
|
jsonResponse: <String, Object>{
|
|
|
|
'views': <Object>[
|
|
|
|
fakeFlutterView.toJson(),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getIsolate',
|
|
|
|
args: <String, Object>{
|
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
|
|
|
},
|
|
|
|
jsonResponse: fakeUnpausedIsolate.toJson(),
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'ext.flutter.exit',
|
|
|
|
args: <String, Object>{
|
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
|
|
|
},
|
|
|
|
// Intentionally do not close isolate.
|
|
|
|
close: false,
|
|
|
|
)
|
|
|
|
]);
|
|
|
|
final TestFlutterDevice flutterDevice = TestFlutterDevice(
|
|
|
|
mockDevice,
|
|
|
|
);
|
|
|
|
flutterDevice.vmService = fakeVmServiceHost.vmService;
|
|
|
|
when(mockDevice.supportsFlutterExit).thenReturn(true);
|
|
|
|
|
|
|
|
await flutterDevice.exitApps(
|
|
|
|
timeoutDelay: Duration.zero,
|
|
|
|
);
|
|
|
|
|
|
|
|
verify(mockDevice.stopApp(any)).called(1);
|
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
|
|
|
}));
|
|
|
|
|
2019-07-18 17:40:40 +00:00
|
|
|
test('FlutterDevice will exit an un-paused isolate', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
2020-04-28 00:41:42 +00:00
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: kListViewsMethod,
|
|
|
|
jsonResponse: <String, Object>{
|
|
|
|
'views': <Object>[
|
|
|
|
fakeFlutterView.toJson(),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
|
|
|
method: 'getIsolate',
|
|
|
|
args: <String, Object>{
|
|
|
|
'isolateId': fakeUnpausedIsolate.id
|
|
|
|
},
|
|
|
|
jsonResponse: fakeUnpausedIsolate.toJson(),
|
|
|
|
),
|
|
|
|
FakeVmServiceRequest(
|
2020-04-20 22:15:54 +00:00
|
|
|
method: 'ext.flutter.exit',
|
|
|
|
args: <String, Object>{
|
2020-04-28 00:41:42 +00:00
|
|
|
'isolateId': fakeUnpausedIsolate.id,
|
2020-04-20 22:15:54 +00:00
|
|
|
},
|
2020-04-28 00:41:42 +00:00
|
|
|
close: true,
|
2020-04-20 22:15:54 +00:00
|
|
|
)
|
|
|
|
]);
|
2019-07-18 17:40:40 +00:00
|
|
|
final TestFlutterDevice flutterDevice = TestFlutterDevice(
|
|
|
|
mockDevice,
|
|
|
|
);
|
2020-04-20 22:15:54 +00:00
|
|
|
flutterDevice.vmService = fakeVmServiceHost.vmService;
|
2019-07-18 17:40:40 +00:00
|
|
|
|
|
|
|
when(mockDevice.supportsFlutterExit).thenReturn(true);
|
|
|
|
|
2020-04-28 00:41:42 +00:00
|
|
|
final Future<void> exitFuture = flutterDevice.exitApps();
|
|
|
|
|
|
|
|
await expectLater(exitFuture, completes);
|
2020-04-20 22:15:54 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-07-18 17:40:40 +00:00
|
|
|
}));
|
2019-07-23 22:38:52 +00:00
|
|
|
|
|
|
|
test('ResidentRunner debugDumpApp calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugDumpApp();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.debugDumpApp()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugDumpRenderTree calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugDumpRenderTree();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.debugDumpRenderTree()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugDumpLayerTree calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugDumpLayerTree();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.debugDumpLayerTree()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugDumpSemanticsTreeInTraversalOrder calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugDumpSemanticsTreeInTraversalOrder();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.debugDumpSemanticsTreeInTraversalOrder()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugDumpSemanticsTreeInInverseHitTestOrder calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugDumpSemanticsTreeInInverseHitTestOrder();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.debugDumpSemanticsTreeInInverseHitTestOrder()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugToggleDebugPaintSizeEnabled calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugToggleDebugPaintSizeEnabled();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.toggleDebugPaintSizeEnabled()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugToggleDebugCheckElevationsEnabled calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugToggleDebugCheckElevationsEnabled();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.toggleDebugCheckElevationsEnabled()).called(1);
|
|
|
|
}));
|
|
|
|
|
2020-04-20 22:15:54 +00:00
|
|
|
test('ResidentRunner debugTogglePerformanceOverlayOverride calls flutter device', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugTogglePerformanceOverlayOverride();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.debugTogglePerformanceOverlayOverride()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugToggleWidgetInspector calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugToggleWidgetInspector();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.toggleWidgetInspector()).called(1);
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('ResidentRunner debugToggleProfileWidgetBuilds calls flutter device', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-07-23 22:38:52 +00:00
|
|
|
await residentRunner.debugToggleProfileWidgetBuilds();
|
|
|
|
|
|
|
|
verify(mockFlutterDevice.toggleProfileWidgetBuilds()).called(1);
|
|
|
|
}));
|
2019-10-15 20:05:47 +00:00
|
|
|
|
|
|
|
test('HotRunner writes vm service file when providing debugging option', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
2020-04-29 18:52:46 +00:00
|
|
|
setWsAddress(testUri, fakeVmServiceHost.vmService);
|
2020-01-06 19:04:20 +00:00
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
2019-10-15 20:05:47 +00:00
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, vmserviceOutFile: 'foo'),
|
|
|
|
);
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
await residentRunner.run();
|
|
|
|
|
2020-01-06 19:04:20 +00:00
|
|
|
expect(await globals.fs.file('foo').readAsString(), testUri.toString());
|
2019-10-15 20:05:47 +00:00
|
|
|
}));
|
|
|
|
|
2020-06-04 17:17:43 +00:00
|
|
|
test('HotRunner copies compiled app.dill to cache during startup', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
|
|
|
setWsAddress(testUri, fakeVmServiceHost.vmService);
|
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
|
|
|
);
|
|
|
|
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
await residentRunner.run();
|
|
|
|
|
|
|
|
expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill')).readAsString(), 'ABC');
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('HotRunner does not copy app.dill if a dillOutputPath is given', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
|
|
|
setWsAddress(testUri, fakeVmServiceHost.vmService);
|
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
dillOutputPath: 'test',
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
|
|
|
);
|
|
|
|
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
await residentRunner.run();
|
|
|
|
|
|
|
|
expect(globals.fs.file(globals.fs.path.join('build', 'cache.dill')), isNot(exists));
|
|
|
|
}));
|
|
|
|
|
|
|
|
test('HotRunner copies compiled app.dill to cache during startup with --track-widget-creation', () => testbed.run(() async {
|
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
|
|
|
setWsAddress(testUri, fakeVmServiceHost.vmService);
|
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(const BuildInfo(
|
|
|
|
BuildMode.debug,
|
|
|
|
'',
|
|
|
|
treeShakeIcons: false,
|
|
|
|
trackWidgetCreation: true,
|
|
|
|
)),
|
|
|
|
);
|
|
|
|
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
await residentRunner.run();
|
|
|
|
|
|
|
|
expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill.track.dill')).readAsString(), 'ABC');
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
2019-12-05 16:48:00 +00:00
|
|
|
test('HotRunner unforwards device ports', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
2019-12-05 16:48:00 +00:00
|
|
|
final MockDevicePortForwarder mockPortForwarder = MockDevicePortForwarder();
|
|
|
|
when(mockDevice.portForwarder).thenReturn(mockPortForwarder);
|
2020-01-06 19:04:20 +00:00
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
2019-12-05 16:48:00 +00:00
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
|
|
|
);
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
when(mockDevice.dispose()).thenAnswer((Invocation invocation) async {
|
|
|
|
await mockDevice.portForwarder.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
await residentRunner.run();
|
|
|
|
|
|
|
|
verify(mockPortForwarder.dispose()).called(1);
|
|
|
|
}));
|
|
|
|
|
2019-10-15 20:05:47 +00:00
|
|
|
test('HotRunner handles failure to write vmservice file', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
listViews,
|
|
|
|
]);
|
2020-01-06 19:04:20 +00:00
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
2019-10-15 20:05:47 +00:00
|
|
|
residentRunner = HotRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, vmserviceOutFile: 'foo'),
|
|
|
|
);
|
|
|
|
when(mockFlutterDevice.runHot(
|
|
|
|
hotRunner: anyNamed('hotRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
await residentRunner.run();
|
|
|
|
|
2019-11-24 05:54:43 +00:00
|
|
|
expect(testLogger.errorText, contains('Failed to write vmservice-out-file at foo'));
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-10-15 20:05:47 +00:00
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
FileSystem: () => ThrowingForwardingFileSystem(MemoryFileSystem()),
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
test('ColdRunner writes vm service file when providing debugging option', () => testbed.run(() async {
|
2020-05-05 19:09:51 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
|
|
|
listViews,
|
|
|
|
]);
|
2020-01-06 19:04:20 +00:00
|
|
|
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
2020-04-29 18:52:46 +00:00
|
|
|
setWsAddress(testUri, fakeVmServiceHost.vmService);
|
2019-10-15 20:05:47 +00:00
|
|
|
residentRunner = ColdRunner(
|
|
|
|
<FlutterDevice>[
|
|
|
|
mockFlutterDevice,
|
|
|
|
],
|
|
|
|
stayResident: false,
|
|
|
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'),
|
|
|
|
);
|
|
|
|
when(mockFlutterDevice.runCold(
|
|
|
|
coldRunner: anyNamed('coldRunner'),
|
|
|
|
route: anyNamed('route'),
|
|
|
|
)).thenAnswer((Invocation invocation) async {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
await residentRunner.run();
|
|
|
|
|
2020-01-06 19:04:20 +00:00
|
|
|
expect(await globals.fs.file('foo').readAsString(), testUri.toString());
|
2020-05-05 19:09:51 +00:00
|
|
|
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
2019-10-15 20:05:47 +00:00
|
|
|
}));
|
2019-10-23 03:35:05 +00:00
|
|
|
|
|
|
|
test('FlutterDevice uses dartdevc configuration when targeting web', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-10-23 03:35:05 +00:00
|
|
|
final MockDevice mockDevice = MockDevice();
|
|
|
|
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
|
|
|
|
return TargetPlatform.web_javascript;
|
|
|
|
});
|
|
|
|
|
|
|
|
final DefaultResidentCompiler residentCompiler = (await FlutterDevice.create(
|
|
|
|
mockDevice,
|
2020-03-06 22:53:36 +00:00
|
|
|
buildInfo: BuildInfo.debug,
|
2019-10-23 03:35:05 +00:00
|
|
|
flutterProject: FlutterProject.current(),
|
|
|
|
target: null,
|
2019-11-24 05:54:43 +00:00
|
|
|
)).generator as DefaultResidentCompiler;
|
2019-10-23 03:35:05 +00:00
|
|
|
|
2020-05-29 22:43:03 +00:00
|
|
|
expect(residentCompiler.initializeFromDill,
|
|
|
|
globals.fs.path.join(getBuildDirectory(), 'cache.dill'));
|
2020-02-28 19:26:02 +00:00
|
|
|
expect(residentCompiler.librariesSpec,
|
|
|
|
globals.fs.file(globals.artifacts.getArtifactPath(Artifact.flutterWebLibrariesJson))
|
|
|
|
.uri.toString());
|
2019-10-23 03:35:05 +00:00
|
|
|
expect(residentCompiler.targetModel, TargetModel.dartdevc);
|
|
|
|
expect(residentCompiler.sdkRoot,
|
2020-01-06 19:04:20 +00:00
|
|
|
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: BuildMode.debug) + '/');
|
2019-11-22 18:08:38 +00:00
|
|
|
expect(
|
|
|
|
residentCompiler.platformDill,
|
2020-01-06 19:04:20 +00:00
|
|
|
globals.fs.file(globals.artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: BuildMode.debug))
|
2019-11-22 18:08:38 +00:00
|
|
|
.absolute.uri.toString(),
|
|
|
|
);
|
2019-10-23 03:35:05 +00:00
|
|
|
}));
|
2019-11-01 21:37:17 +00:00
|
|
|
|
|
|
|
test('connect sets up log reader', () => testbed.run(() async {
|
2020-04-20 22:15:54 +00:00
|
|
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
2019-11-01 21:37:17 +00:00
|
|
|
final MockDevice mockDevice = MockDevice();
|
|
|
|
final MockDeviceLogReader mockLogReader = MockDeviceLogReader();
|
|
|
|
when(mockDevice.getLogReader(app: anyNamed('app'))).thenReturn(mockLogReader);
|
|
|
|
|
|
|
|
final TestFlutterDevice flutterDevice = TestFlutterDevice(
|
|
|
|
mockDevice,
|
2019-11-21 02:51:25 +00:00
|
|
|
observatoryUris: Stream<Uri>.value(testUri),
|
2019-11-01 21:37:17 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
await flutterDevice.connect();
|
2019-11-27 21:11:04 +00:00
|
|
|
verify(mockLogReader.connectedVMService = mockVMService);
|
2019-11-01 21:37:17 +00:00
|
|
|
}, overrides: <Type, Generator>{
|
2019-11-26 22:49:56 +00:00
|
|
|
VMServiceConnector: () => (Uri httpUri, {
|
|
|
|
ReloadSources reloadSources,
|
|
|
|
Restart restart,
|
|
|
|
CompileExpression compileExpression,
|
2019-12-10 05:31:34 +00:00
|
|
|
ReloadMethod reloadMethod,
|
2020-05-27 17:10:41 +00:00
|
|
|
GetSkSLMethod getSkSLMethod,
|
2019-11-26 22:49:56 +00:00
|
|
|
io.CompressionOptions compression,
|
|
|
|
Device device,
|
|
|
|
}) async => mockVMService,
|
2019-11-01 21:37:17 +00:00
|
|
|
}));
|
2019-12-12 23:20:52 +00:00
|
|
|
|
|
|
|
test('nextPlatform moves through expected platforms', () {
|
|
|
|
expect(nextPlatform('android', TestFeatureFlags()), 'iOS');
|
|
|
|
expect(nextPlatform('iOS', TestFeatureFlags()), 'fuchsia');
|
|
|
|
expect(nextPlatform('fuchsia', TestFeatureFlags()), 'android');
|
|
|
|
expect(nextPlatform('fuchsia', TestFeatureFlags(isMacOSEnabled: true)), 'macOS');
|
2020-01-27 22:36:02 +00:00
|
|
|
expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsAssertionError);
|
2019-12-12 23:20:52 +00:00
|
|
|
});
|
2017-05-21 22:15:44 +00:00
|
|
|
}
|
|
|
|
|
2019-07-13 23:02:09 +00:00
|
|
|
class MockFlutterDevice extends Mock implements FlutterDevice {}
|
2020-04-29 18:52:46 +00:00
|
|
|
class MockVMService extends Mock implements vm_service.VmService {}
|
2019-07-09 20:10:26 +00:00
|
|
|
class MockDevFS extends Mock implements DevFS {}
|
2019-07-13 23:02:09 +00:00
|
|
|
class MockDevice extends Mock implements Device {}
|
2019-11-01 21:37:17 +00:00
|
|
|
class MockDeviceLogReader extends Mock implements DeviceLogReader {}
|
2019-12-05 16:48:00 +00:00
|
|
|
class MockDevicePortForwarder extends Mock implements DevicePortForwarder {}
|
2019-07-13 23:02:09 +00:00
|
|
|
class MockUsage extends Mock implements Usage {}
|
2019-10-23 03:35:05 +00:00
|
|
|
class MockProcessManager extends Mock implements ProcessManager {}
|
2020-06-03 19:00:03 +00:00
|
|
|
class MockResidentCompiler extends Mock implements ResidentCompiler {}
|
2020-04-28 00:41:42 +00:00
|
|
|
|
2019-07-15 22:44:58 +00:00
|
|
|
class TestFlutterDevice extends FlutterDevice {
|
2020-05-05 19:09:51 +00:00
|
|
|
TestFlutterDevice(Device device, { Stream<Uri> observatoryUris })
|
2020-03-06 22:53:36 +00:00
|
|
|
: super(device, buildInfo: BuildInfo.debug) {
|
2019-11-01 21:37:17 +00:00
|
|
|
_observatoryUris = observatoryUris;
|
|
|
|
}
|
2019-07-15 22:44:58 +00:00
|
|
|
|
2019-11-01 21:37:17 +00:00
|
|
|
@override
|
2019-11-21 02:51:25 +00:00
|
|
|
Stream<Uri> get observatoryUris => _observatoryUris;
|
|
|
|
Stream<Uri> _observatoryUris;
|
2019-07-15 22:44:58 +00:00
|
|
|
}
|
|
|
|
|
2019-10-15 20:05:47 +00:00
|
|
|
class ThrowingForwardingFileSystem extends ForwardingFileSystem {
|
|
|
|
ThrowingForwardingFileSystem(FileSystem delegate) : super(delegate);
|
|
|
|
|
|
|
|
@override
|
|
|
|
File file(dynamic path) {
|
|
|
|
if (path == 'foo') {
|
|
|
|
throw const FileSystemException();
|
|
|
|
}
|
|
|
|
return delegate.file(path);
|
|
|
|
}
|
|
|
|
}
|