mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Refactor core resident runner logic (#80462)
This commit is contained in:
parent
aa9f6a2a05
commit
9904a7f472
@ -41,18 +41,7 @@ class FileSystemUtils {
|
||||
/// Appends a number to a filename in order to make it unique under a
|
||||
/// directory.
|
||||
File getUniqueFile(Directory dir, String baseName, String ext) {
|
||||
final FileSystem fs = dir.fileSystem;
|
||||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
final String name = '${baseName}_${i.toString().padLeft(2, '0')}.$ext';
|
||||
final File file = fs.file(_fileSystem.path.join(dir.path, name));
|
||||
if (!file.existsSync()) {
|
||||
file.createSync(recursive: true);
|
||||
return file;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return _getUniqueFile(dir, baseName, ext);
|
||||
}
|
||||
|
||||
/// Appends a number to a directory name in order to make it unique under a
|
||||
@ -157,6 +146,27 @@ void copyDirectory(
|
||||
}
|
||||
}
|
||||
|
||||
File _getUniqueFile(Directory dir, String baseName, String ext) {
|
||||
final FileSystem fs = dir.fileSystem;
|
||||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
final String name = '${baseName}_${i.toString().padLeft(2, '0')}.$ext';
|
||||
final File file = fs.file(dir.fileSystem.path.join(dir.path, name));
|
||||
if (!file.existsSync()) {
|
||||
file.createSync(recursive: true);
|
||||
return file;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends a number to a filename in order to make it unique under a
|
||||
/// directory.
|
||||
File getUniqueFile(Directory dir, String baseName, String ext) {
|
||||
return _getUniqueFile(dir, baseName, ext);
|
||||
}
|
||||
|
||||
/// This class extends [local_fs.LocalFileSystem] in order to clean up
|
||||
/// directories and files that the tool creates under the system temporary
|
||||
/// directory when the tool exits either normally or when killed by a signal.
|
||||
|
||||
@ -29,6 +29,7 @@ import '../resident_runner.dart';
|
||||
import '../run_cold.dart';
|
||||
import '../run_hot.dart';
|
||||
import '../runner/flutter_command.dart';
|
||||
import '../vmservice.dart';
|
||||
import '../web/web_runner.dart';
|
||||
|
||||
const String protocolVersion = '0.6.0';
|
||||
@ -687,9 +688,16 @@ class AppDomain extends Domain {
|
||||
if (app == null) {
|
||||
throw "app '$appId' not found";
|
||||
}
|
||||
|
||||
final Map<String, dynamic> result = await app.runner
|
||||
.invokeFlutterExtensionRpcRawOnFirstIsolate(methodName, params: params);
|
||||
final FlutterDevice device = app.runner.flutterDevices.first;
|
||||
final List<FlutterView> views = await device.vmService.getFlutterViews();
|
||||
final Map<String, dynamic> result = await device
|
||||
.vmService
|
||||
.invokeFlutterExtensionRpcRaw(
|
||||
methodName,
|
||||
args: params,
|
||||
isolateId: views
|
||||
.first.uiIsolate.id
|
||||
);
|
||||
if (result == null) {
|
||||
throw 'method not available: $methodName';
|
||||
}
|
||||
|
||||
@ -76,7 +76,6 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
|
||||
systemClock: systemClock,
|
||||
fileSystem: fileSystem,
|
||||
logger: logger,
|
||||
featureFlags: featureFlags,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -99,14 +98,12 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
@required SystemClock systemClock,
|
||||
@required Usage usage,
|
||||
@required UrlTunneller urlTunneller,
|
||||
@required FeatureFlags featureFlags,
|
||||
ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler,
|
||||
}) : _fileSystem = fileSystem,
|
||||
_logger = logger,
|
||||
_systemClock = systemClock,
|
||||
_usage = usage,
|
||||
_urlTunneller = urlTunneller,
|
||||
_featureFlags = featureFlags,
|
||||
super(
|
||||
<FlutterDevice>[device],
|
||||
target: target ?? fileSystem.path.join('lib', 'main.dart'),
|
||||
@ -122,7 +119,6 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
final SystemClock _systemClock;
|
||||
final Usage _usage;
|
||||
final UrlTunneller _urlTunneller;
|
||||
final FeatureFlags _featureFlags;
|
||||
|
||||
FlutterDevice get device => flutterDevices.first;
|
||||
final FlutterProject flutterProject;
|
||||
@ -167,20 +163,7 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
FlutterVmService _instance;
|
||||
|
||||
@override
|
||||
bool get canHotRestart {
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> invokeFlutterExtensionRpcRawOnFirstIsolate(
|
||||
String method, {
|
||||
FlutterDevice device,
|
||||
Map<String, dynamic> params,
|
||||
}) async {
|
||||
final vmservice.Response response =
|
||||
await _vmService.service.callServiceExtension(method, args: params);
|
||||
return response.toJson();
|
||||
}
|
||||
bool get supportsRestart => true;
|
||||
|
||||
@override
|
||||
Future<void> cleanupAfterSignal() async {
|
||||
@ -313,7 +296,7 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
?.flutterPlatformOverride(
|
||||
isolateId: null,
|
||||
);
|
||||
final String platform = nextPlatform(currentPlatform, _featureFlags);
|
||||
final String platform = nextPlatform(currentPlatform);
|
||||
await _vmService
|
||||
?.flutterPlatformOverride(
|
||||
platform: platform,
|
||||
|
||||
@ -192,11 +192,11 @@ class FlutterDevice {
|
||||
);
|
||||
}
|
||||
|
||||
final TargetPlatform targetPlatform;
|
||||
final Device device;
|
||||
final ResidentCompiler generator;
|
||||
final BuildInfo buildInfo;
|
||||
final String userIdentifier;
|
||||
final TargetPlatform targetPlatform;
|
||||
|
||||
DevFSWriter devFSWriter;
|
||||
Stream<Uri> observatoryUris;
|
||||
@ -401,138 +401,16 @@ class FlutterDevice {
|
||||
return devFS.create();
|
||||
}
|
||||
|
||||
Future<void> debugDumpApp() async {
|
||||
Future<List<vm_service.IsolateRef>> _getCurrentIsolates() async {
|
||||
if (targetPlatform == TargetPlatform.web_javascript) {
|
||||
final vm_service.VM vm = await vmService.service.getVM();
|
||||
return vm.isolates;
|
||||
}
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
final String data = await vmService.flutterDebugDumpApp(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
globals.printStatus(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> debugDumpRenderTree() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
final String data = await vmService.flutterDebugDumpRenderTree(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
globals.printStatus(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> debugDumpLayerTree() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
final String data = await vmService.flutterDebugDumpLayerTree(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
globals.printStatus(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> debugDumpSemanticsTreeInTraversalOrder() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
final String data = await vmService.flutterDebugDumpSemanticsTreeInTraversalOrder(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
globals.printStatus(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> debugDumpSemanticsTreeInInverseHitTestOrder() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
final String data = await vmService.flutterDebugDumpSemanticsTreeInInverseHitTestOrder(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
globals.printStatus(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> toggleDebugPaintSizeEnabled() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
await vmService.flutterToggleDebugPaintSizeEnabled(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> toggleDebugCheckElevationsEnabled() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
await vmService.flutterToggleDebugCheckElevationsEnabled(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> debugTogglePerformanceOverlayOverride() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
await vmService.flutterTogglePerformanceOverlayOverride(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> toggleWidgetInspector() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
await vmService.flutterToggleWidgetInspector(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> toggleInvertOversizedImages() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
await vmService.flutterToggleInvertOversizedImages(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> toggleProfileWidgetBuilds() async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
for (final FlutterView view in views) {
|
||||
await vmService.flutterToggleProfileWidgetBuilds(
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Brightness> toggleBrightness({ Brightness current }) async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
Brightness next;
|
||||
if (current == Brightness.light) {
|
||||
next = Brightness.dark;
|
||||
} else if (current == Brightness.dark) {
|
||||
next = Brightness.light;
|
||||
}
|
||||
|
||||
for (final FlutterView view in views) {
|
||||
next = await vmService.flutterBrightnessOverride(
|
||||
isolateId: view.uiIsolate.id,
|
||||
brightness: next,
|
||||
);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
Future<String> togglePlatform({ String from }) async {
|
||||
final List<FlutterView> views = await vmService.getFlutterViews();
|
||||
final String to = nextPlatform(from, featureFlags);
|
||||
for (final FlutterView view in views) {
|
||||
await vmService.flutterPlatformOverride(
|
||||
platform: to,
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
return to;
|
||||
return <vm_service.IsolateRef>[
|
||||
for (FlutterView view in views)
|
||||
view.uiIsolate,
|
||||
];
|
||||
}
|
||||
|
||||
Future<void> startEchoingDeviceLog() async {
|
||||
@ -629,7 +507,6 @@ class FlutterDevice {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Future<int> runCold({
|
||||
ColdRunner coldRunner,
|
||||
String route,
|
||||
@ -755,8 +632,389 @@ class FlutterDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/// A subset of the [ResidentRunner] for delegating to attached flutter devices.
|
||||
abstract class ResidentHandlers {
|
||||
List<FlutterDevice> get flutterDevices;
|
||||
|
||||
/// Whether the resident runner has hot reload and restart enabled.
|
||||
bool get hotMode;
|
||||
|
||||
/// Whether the resident runner is connect to the device's VM Service.
|
||||
bool get supportsServiceProtocol;
|
||||
|
||||
/// The application is running in debug mode.
|
||||
bool get isRunningDebug;
|
||||
|
||||
/// The application is running in profile mode.
|
||||
bool get isRunningProfile;
|
||||
|
||||
/// The application is running in release mode.
|
||||
bool get isRunningRelease;
|
||||
|
||||
/// The resident runner should stay resident after establishing a connection with the
|
||||
/// application.
|
||||
bool get stayResident;
|
||||
|
||||
/// Whether all of the connected devices support hot restart.
|
||||
///
|
||||
/// To prevent scenarios where only a subset of devices are hot restarted,
|
||||
/// the runner requires that all attached devices can support hot restart
|
||||
/// before enabling it.
|
||||
bool get supportsRestart;
|
||||
|
||||
/// Whether all of the connected devices support gathering SkSL.
|
||||
bool get supportsWriteSkSL;
|
||||
|
||||
/// Whether all of the connected devices support hot reload.
|
||||
bool get canHotReload;
|
||||
|
||||
@protected
|
||||
Logger get logger;
|
||||
|
||||
@protected
|
||||
FileSystem get fileSystem;
|
||||
|
||||
/// Called to print help to the terminal.
|
||||
void printHelp({ @required bool details });
|
||||
|
||||
/// Perfor a hot reload or hot restart of all attached applications.
|
||||
///
|
||||
/// If [fullRestart] is true, a hot restart is performed. Otherwise a hot reload
|
||||
/// is run instead. On web devices, this only performs a hot restart regardless of
|
||||
/// the value of [fullRestart].
|
||||
Future<OperationResult> restart({ bool fullRestart = false, bool pause = false, String reason }) {
|
||||
final String mode = isRunningProfile ? 'profile' :isRunningRelease ? 'release' : 'this';
|
||||
throw '${fullRestart ? 'Restart' : 'Reload'} is not supported in $mode mode';
|
||||
}
|
||||
|
||||
/// Dump the application's current widget tree to the terminal.
|
||||
Future<bool> debugDumpApp() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
final String data = await device.vmService.flutterDebugDumpApp(
|
||||
isolateId: view.id,
|
||||
);
|
||||
logger.printStatus(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Dump the application's current render tree to the terminal.
|
||||
Future<bool> debugDumpRenderTree() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
final String data = await device.vmService.flutterDebugDumpRenderTree(
|
||||
isolateId: view.id,
|
||||
);
|
||||
logger.printStatus(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Dump the application's current layer tree to the terminal.
|
||||
Future<bool> debugDumpLayerTree() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
final String data = await device.vmService.flutterDebugDumpLayerTree(
|
||||
isolateId: view.id,
|
||||
);
|
||||
logger.printStatus(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Dump the application's current semantics tree to the terminal.
|
||||
///
|
||||
/// If semantics are not enabled, nothing is returned.
|
||||
Future<bool> debugDumpSemanticsTreeInTraversalOrder() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
final String data = await device.vmService.flutterDebugDumpSemanticsTreeInTraversalOrder(
|
||||
isolateId: view.id,
|
||||
);
|
||||
logger.printStatus(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Dump the application's current semantics tree to the terminal.
|
||||
///
|
||||
/// If semantics are not enabled, nothing is returned.
|
||||
Future<bool> debugDumpSemanticsTreeInInverseHitTestOrder() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
final String data = await device.vmService.flutterDebugDumpSemanticsTreeInInverseHitTestOrder(
|
||||
isolateId: view.id,
|
||||
);
|
||||
logger.printStatus(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Toggle the "paint size" debugging feature.
|
||||
Future<bool> debugToggleDebugPaintSizeEnabled() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterToggleDebugPaintSizeEnabled(
|
||||
isolateId: view.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Toggle the "elevation check" debugging feature.
|
||||
Future<bool> debugToggleDebugCheckElevationsEnabled() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterToggleDebugCheckElevationsEnabled(
|
||||
isolateId: view.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Toggle the performance overlay.
|
||||
///
|
||||
/// This is not supported in web mode.
|
||||
Future<bool> debugTogglePerformanceOverlayOverride() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
if (device.targetPlatform == TargetPlatform.web_javascript) {
|
||||
continue;
|
||||
}
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterTogglePerformanceOverlayOverride(
|
||||
isolateId: view.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Toggle the widget inspector.
|
||||
Future<bool> debugToggleWidgetInspector() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterToggleWidgetInspector(
|
||||
isolateId: view.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Toggle the "invert images" debugging feature.
|
||||
Future<bool> debugToggleInvertOversizedImages() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterToggleInvertOversizedImages(
|
||||
isolateId: view.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Toggle the "profile widget builds" debugging feature.
|
||||
Future<bool> debugToggleProfileWidgetBuilds() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterToggleProfileWidgetBuilds(
|
||||
isolateId: view.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Toggle the operating system brightness (light or dart).
|
||||
Future<bool> debugToggleBrightness() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
final List<vm_service.IsolateRef> views = await flutterDevices.first._getCurrentIsolates();
|
||||
final Brightness current = await flutterDevices.first.vmService.flutterBrightnessOverride(
|
||||
isolateId: views.first.id,
|
||||
);
|
||||
Brightness next;
|
||||
if (current == Brightness.light) {
|
||||
next = Brightness.dark;
|
||||
} else {
|
||||
next = Brightness.light;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterBrightnessOverride(
|
||||
isolateId: view.id,
|
||||
brightness: next,
|
||||
);
|
||||
}
|
||||
logger.printStatus('Changed brightness to $next.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Rotate the application through different `defaultTargetPlatform` values.
|
||||
Future<bool> debugTogglePlatform() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
final List<vm_service.IsolateRef> views = await flutterDevices.first._getCurrentIsolates();
|
||||
final String from = await flutterDevices
|
||||
.first.vmService.flutterPlatformOverride(
|
||||
isolateId: views.first.id,
|
||||
);
|
||||
final String to = nextPlatform(from);
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
for (final vm_service.IsolateRef view in await device._getCurrentIsolates()) {
|
||||
await device.vmService.flutterPlatformOverride(
|
||||
platform: to,
|
||||
isolateId: view.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
logger.printStatus('Switched operating system to $to');
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Write the SkSL shaders to a zip file in build directory.
|
||||
///
|
||||
/// Returns the name of the file, or `null` on failures.
|
||||
Future<String> writeSkSL() async {
|
||||
if (!supportsWriteSkSL) {
|
||||
throw Exception('writeSkSL is not supported by this runner.');
|
||||
}
|
||||
final List<FlutterView> views = await flutterDevices
|
||||
.first
|
||||
.vmService.getFlutterViews();
|
||||
final Map<String, Object> data = await flutterDevices.first.vmService.getSkSLs(
|
||||
viewId: views.first.id,
|
||||
);
|
||||
final Device device = flutterDevices.first.device;
|
||||
return sharedSkSlWriter(device, data);
|
||||
}
|
||||
|
||||
/// Take a screenshot on the provided [device].
|
||||
///
|
||||
/// If the device has a connected vmservice, this method will attempt to hide
|
||||
/// and restore the debug banner before taking the screenshot.
|
||||
///
|
||||
/// Throws an [AssertionError] if [Device.supportsScreenshot] is not true.
|
||||
Future<void> screenshot(FlutterDevice device) async {
|
||||
assert(device.device.supportsScreenshot);
|
||||
|
||||
final Status status = logger.startProgress(
|
||||
'Taking screenshot for ${device.device.name}...',
|
||||
);
|
||||
final File outputFile = getUniqueFile(
|
||||
fileSystem.currentDirectory,
|
||||
'flutter',
|
||||
'png',
|
||||
);
|
||||
List<FlutterView> views = <FlutterView>[];
|
||||
Future<bool> setDebugBanner(bool value) async {
|
||||
try {
|
||||
for (final FlutterView view in views) {
|
||||
await device.vmService.flutterDebugAllowBanner(
|
||||
value,
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
} on Exception catch (error) {
|
||||
status.cancel();
|
||||
logger.printError('Error communicating with Flutter on the device: $error');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (supportsServiceProtocol && isRunningDebug) {
|
||||
// Ensure that the vmService access is guarded by supportsServiceProtocol, it
|
||||
// will be null in release mode.
|
||||
views = await device.vmService.getFlutterViews();
|
||||
if (!await setDebugBanner(false)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
await device.device.takeScreenshot(outputFile);
|
||||
} finally {
|
||||
if (supportsServiceProtocol && isRunningDebug) {
|
||||
await setDebugBanner(true);
|
||||
}
|
||||
}
|
||||
final int sizeKB = outputFile.lengthSync() ~/ 1024;
|
||||
status.stop();
|
||||
logger.printStatus(
|
||||
'Screenshot written to ${fileSystem.path.relative(outputFile.path)} (${sizeKB}kB).',
|
||||
);
|
||||
} on Exception catch (error) {
|
||||
status.cancel();
|
||||
logger.printError('Error taking screenshot: $error');
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove sigusr signal handlers.
|
||||
Future<void> cleanupAfterSignal();
|
||||
|
||||
/// Tear down the runner and leave the application running.
|
||||
///
|
||||
/// This is not supported on web devices where the runner is running
|
||||
/// the application server as well.
|
||||
Future<void> detach();
|
||||
|
||||
/// Tear down the runner and exit the application.
|
||||
Future<void> exit();
|
||||
|
||||
/// Run any source generators, such as localizations.
|
||||
///
|
||||
/// These are automatically run during hot restart, but can be
|
||||
/// triggered manually to see the updated generated code.
|
||||
Future<void> runSourceGenerators();
|
||||
}
|
||||
|
||||
// Shared code between different resident application runners.
|
||||
abstract class ResidentRunner {
|
||||
abstract class ResidentRunner extends ResidentHandlers {
|
||||
ResidentRunner(
|
||||
this.flutterDevices, {
|
||||
@required this.target,
|
||||
@ -788,12 +1046,19 @@ abstract class ResidentRunner {
|
||||
_residentDevtoolsHandler = devtoolsHandler(DevtoolsLauncher.instance, this, globals.logger);
|
||||
}
|
||||
|
||||
@protected
|
||||
@visibleForTesting
|
||||
@override
|
||||
Logger get logger => globals.logger;
|
||||
|
||||
@override
|
||||
FileSystem get fileSystem => globals.fs;
|
||||
|
||||
@override
|
||||
final List<FlutterDevice> flutterDevices;
|
||||
|
||||
final String target;
|
||||
final DebuggingOptions debuggingOptions;
|
||||
|
||||
@override
|
||||
final bool stayResident;
|
||||
final bool ipv6;
|
||||
final String _dillOutputPath;
|
||||
@ -812,6 +1077,10 @@ abstract class ResidentRunner {
|
||||
|
||||
bool _exited = false;
|
||||
Completer<int> _finished = Completer<int>();
|
||||
BuildResult _lastBuild;
|
||||
Environment _environment;
|
||||
|
||||
@override
|
||||
bool hotMode;
|
||||
|
||||
/// Returns true if every device is streaming observatory URIs.
|
||||
@ -833,11 +1102,22 @@ abstract class ResidentRunner {
|
||||
}
|
||||
|
||||
bool get debuggingEnabled => debuggingOptions.debuggingEnabled;
|
||||
|
||||
@override
|
||||
bool get isRunningDebug => debuggingOptions.buildInfo.isDebug;
|
||||
|
||||
@override
|
||||
bool get isRunningProfile => debuggingOptions.buildInfo.isProfile;
|
||||
|
||||
@override
|
||||
bool get isRunningRelease => debuggingOptions.buildInfo.isRelease;
|
||||
|
||||
@override
|
||||
bool get supportsServiceProtocol => isRunningDebug || isRunningProfile;
|
||||
|
||||
@override
|
||||
bool get supportsWriteSkSL => supportsServiceProtocol;
|
||||
|
||||
bool get trackWidgetCreation => debuggingOptions.buildInfo.trackWidgetCreation;
|
||||
|
||||
// Returns the Uri of the first connected device for mobile,
|
||||
@ -850,38 +1130,14 @@ abstract class ResidentRunner {
|
||||
/// Returns [true] if the resident runner exited after invoking [exit()].
|
||||
bool get exited => _exited;
|
||||
|
||||
/// Whether this runner can hot restart.
|
||||
///
|
||||
/// To prevent scenarios where only a subset of devices are hot restarted,
|
||||
/// the runner requires that all attached devices can support hot restart
|
||||
/// before enabling it.
|
||||
bool get canHotRestart {
|
||||
return flutterDevices.every((FlutterDevice device) {
|
||||
@override
|
||||
bool get supportsRestart {
|
||||
return isRunningDebug && flutterDevices.every((FlutterDevice device) {
|
||||
return device.device.supportsHotRestart;
|
||||
});
|
||||
}
|
||||
|
||||
/// Invoke an RPC extension method on the first attached ui isolate of the first device.
|
||||
// TODO(jonahwilliams): Update/Remove this method when refactoring the resident
|
||||
// runner to support a single flutter device.
|
||||
Future<Map<String, dynamic>> invokeFlutterExtensionRpcRawOnFirstIsolate(
|
||||
String method, {
|
||||
FlutterDevice device,
|
||||
Map<String, dynamic> params,
|
||||
}) async {
|
||||
device ??= flutterDevices.first;
|
||||
final List<FlutterView> views = await device.vmService.getFlutterViews();
|
||||
return device
|
||||
.vmService
|
||||
.invokeFlutterExtensionRpcRaw(
|
||||
method,
|
||||
args: params,
|
||||
isolateId: views
|
||||
.first.uiIsolate.id
|
||||
);
|
||||
}
|
||||
|
||||
/// Whether this runner can hot reload.
|
||||
@override
|
||||
bool get canHotReload => hotMode;
|
||||
|
||||
/// Start the app and keep the process running during its lifetime.
|
||||
@ -902,17 +1158,7 @@ abstract class ResidentRunner {
|
||||
bool enableDevTools = false,
|
||||
});
|
||||
|
||||
bool get supportsRestart => false;
|
||||
|
||||
Future<OperationResult> restart({ bool fullRestart = false, bool pause = false, String reason }) {
|
||||
final String mode = isRunningProfile ? 'profile' :
|
||||
isRunningRelease ? 'release' : 'this';
|
||||
throw '${fullRestart ? 'Restart' : 'Reload'} is not supported in $mode mode';
|
||||
}
|
||||
|
||||
|
||||
BuildResult _lastBuild;
|
||||
Environment _environment;
|
||||
@override
|
||||
Future<void> runSourceGenerators() async {
|
||||
_environment ??= Environment(
|
||||
artifacts: globals.artifacts,
|
||||
@ -944,23 +1190,6 @@ abstract class ResidentRunner {
|
||||
globals.logger.printTrace('complete');
|
||||
}
|
||||
|
||||
/// Write the SkSL shaders to a zip file in build directory.
|
||||
///
|
||||
/// Returns the name of the file, or `null` on failures.
|
||||
Future<String> writeSkSL() async {
|
||||
if (!supportsWriteSkSL) {
|
||||
throw Exception('writeSkSL is not supported by this runner.');
|
||||
}
|
||||
final List<FlutterView> views = await flutterDevices
|
||||
.first
|
||||
.vmService.getFlutterViews();
|
||||
final Map<String, Object> data = await flutterDevices.first.vmService.getSkSLs(
|
||||
viewId: views.first.id,
|
||||
);
|
||||
final Device device = flutterDevices.first.device;
|
||||
return sharedSkSlWriter(device, data);
|
||||
}
|
||||
|
||||
@protected
|
||||
void writeVmServiceFile() {
|
||||
if (debuggingOptions.vmserviceOutFile != null) {
|
||||
@ -975,6 +1204,7 @@ abstract class ResidentRunner {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> exit() async {
|
||||
_exited = true;
|
||||
await residentDevtoolsHandler.shutdown();
|
||||
@ -984,6 +1214,7 @@ abstract class ResidentRunner {
|
||||
await shutdownDartDevelopmentService();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> detach() async {
|
||||
await residentDevtoolsHandler.shutdown();
|
||||
await stopEchoingDeviceLog();
|
||||
@ -992,212 +1223,6 @@ abstract class ResidentRunner {
|
||||
appFinished();
|
||||
}
|
||||
|
||||
Future<bool> debugDumpApp() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.debugDumpApp();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugDumpRenderTree() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.debugDumpRenderTree();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugDumpLayerTree() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.debugDumpLayerTree();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugDumpSemanticsTreeInTraversalOrder() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.debugDumpSemanticsTreeInTraversalOrder();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugDumpSemanticsTreeInInverseHitTestOrder() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.debugDumpSemanticsTreeInInverseHitTestOrder();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugToggleDebugPaintSizeEnabled() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.toggleDebugPaintSizeEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugToggleDebugCheckElevationsEnabled() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.toggleDebugCheckElevationsEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugTogglePerformanceOverlayOverride() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.debugTogglePerformanceOverlayOverride();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugToggleWidgetInspector() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.toggleWidgetInspector();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugToggleInvertOversizedImages() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.toggleInvertOversizedImages();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugToggleProfileWidgetBuilds() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
await device.toggleProfileWidgetBuilds();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> debugToggleBrightness() async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
final Brightness brightness = await flutterDevices.first.toggleBrightness();
|
||||
Brightness next;
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
next = await device.toggleBrightness(
|
||||
current: brightness,
|
||||
);
|
||||
globals.logger.printStatus('Changed brightness to $next.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Take a screenshot on the provided [device].
|
||||
///
|
||||
/// If the device has a connected vmservice, this method will attempt to hide
|
||||
/// and restore the debug banner before taking the screenshot.
|
||||
///
|
||||
/// Throws an [AssertionError] if [Device.supportsScreenshot] is not true.
|
||||
Future<void> screenshot(FlutterDevice device) async {
|
||||
assert(device.device.supportsScreenshot);
|
||||
|
||||
final Status status = globals.logger.startProgress(
|
||||
'Taking screenshot for ${device.device.name}...',
|
||||
);
|
||||
final File outputFile = globals.fsUtils.getUniqueFile(
|
||||
globals.fs.currentDirectory,
|
||||
'flutter',
|
||||
'png',
|
||||
);
|
||||
List<FlutterView> views = <FlutterView>[];
|
||||
Future<bool> setDebugBanner(bool value) async {
|
||||
try {
|
||||
for (final FlutterView view in views) {
|
||||
await device.vmService.flutterDebugAllowBanner(
|
||||
value,
|
||||
isolateId: view.uiIsolate.id,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
} on Exception catch (error) {
|
||||
status.cancel();
|
||||
globals.printError('Error communicating with Flutter on the device: $error');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (supportsServiceProtocol && isRunningDebug) {
|
||||
// Ensure that the vmService access is guarded by supportsServiceProtocol, it
|
||||
// will be null in release mode.
|
||||
views = await device.vmService.getFlutterViews();
|
||||
if (!await setDebugBanner(false)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
await device.device.takeScreenshot(outputFile);
|
||||
} finally {
|
||||
if (supportsServiceProtocol && isRunningDebug) {
|
||||
await setDebugBanner(true);
|
||||
}
|
||||
}
|
||||
final int sizeKB = outputFile.lengthSync() ~/ 1024;
|
||||
status.stop();
|
||||
globals.printStatus(
|
||||
'Screenshot written to ${globals.fs.path.relative(outputFile.path)} (${sizeKB}kB).',
|
||||
);
|
||||
} on Exception catch (error) {
|
||||
status.cancel();
|
||||
globals.printError('Error taking screenshot: $error');
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> debugTogglePlatform() async {
|
||||
if (!supportsServiceProtocol || !isRunningDebug) {
|
||||
return false;
|
||||
}
|
||||
final List<FlutterView> views = await flutterDevices
|
||||
.first
|
||||
.vmService.getFlutterViews();
|
||||
final String isolateId = views.first.uiIsolate.id;
|
||||
final String from = await flutterDevices
|
||||
.first.vmService.flutterPlatformOverride(
|
||||
isolateId: isolateId,
|
||||
);
|
||||
String to;
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
to = await device.togglePlatform(from: from);
|
||||
}
|
||||
globals.printStatus('Switched operating system to $to');
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> stopEchoingDeviceLog() async {
|
||||
await Future.wait<void>(
|
||||
flutterDevices.map<Future<void>>((FlutterDevice device) => device.stopEchoingDeviceLog())
|
||||
@ -1379,9 +1404,6 @@ abstract class ResidentRunner {
|
||||
_reportedDebuggers = true;
|
||||
}
|
||||
|
||||
/// Called to print help to the terminal.
|
||||
void printHelp({ @required bool details });
|
||||
|
||||
void printHelpDetails() {
|
||||
if (flutterDevices.any((FlutterDevice d) => d.device.supportsScreenshot)) {
|
||||
commandHelp.s.print();
|
||||
@ -1413,14 +1435,11 @@ abstract class ResidentRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/// Called when a signal has requested we exit.
|
||||
@override
|
||||
Future<void> cleanupAfterSignal();
|
||||
|
||||
/// Called right before we exit.
|
||||
Future<void> cleanupAtFinish();
|
||||
|
||||
// Clears the screen.
|
||||
void clearScreen() => globals.logger.clear();
|
||||
}
|
||||
|
||||
class OperationResult {
|
||||
@ -1479,7 +1498,7 @@ class TerminalHandler {
|
||||
final bool _reportReady;
|
||||
final String _pidFile;
|
||||
|
||||
final ResidentRunner residentRunner;
|
||||
final ResidentHandlers residentRunner;
|
||||
bool _processingUserRequest = false;
|
||||
StreamSubscription<void> subscription;
|
||||
File _actualPidFile;
|
||||
@ -1487,6 +1506,10 @@ class TerminalHandler {
|
||||
@visibleForTesting
|
||||
String lastReceivedCommand;
|
||||
|
||||
/// This is only a buffer logger in unit tests
|
||||
@visibleForTesting
|
||||
BufferLogger get logger => _logger as BufferLogger;
|
||||
|
||||
void setupTerminal() {
|
||||
if (!_logger.quiet) {
|
||||
_logger.printStatus('');
|
||||
@ -1544,7 +1567,7 @@ class TerminalHandler {
|
||||
case 'b':
|
||||
return residentRunner.debugToggleBrightness();
|
||||
case 'c':
|
||||
residentRunner.clearScreen();
|
||||
_logger.clear();
|
||||
return true;
|
||||
case 'd':
|
||||
case 'D':
|
||||
@ -1597,7 +1620,7 @@ class TerminalHandler {
|
||||
return true;
|
||||
case 'R':
|
||||
// If hot restart is not supported for all devices, ignore the command.
|
||||
if (!residentRunner.canHotRestart || !residentRunner.hotMode) {
|
||||
if (!residentRunner.supportsRestart || !residentRunner.hotMode) {
|
||||
return false;
|
||||
}
|
||||
final OperationResult result = await residentRunner.restart(fullRestart: true);
|
||||
@ -1694,17 +1717,14 @@ class DebugConnectionInfo {
|
||||
///
|
||||
/// These values must match what is available in
|
||||
/// `packages/flutter/lib/src/foundation/binding.dart`.
|
||||
String nextPlatform(String currentPlatform, FeatureFlags featureFlags) {
|
||||
String nextPlatform(String currentPlatform) {
|
||||
switch (currentPlatform) {
|
||||
case 'android':
|
||||
return 'iOS';
|
||||
case 'iOS':
|
||||
return 'fuchsia';
|
||||
case 'fuchsia':
|
||||
if (featureFlags.isMacOSEnabled) {
|
||||
return 'macOS';
|
||||
}
|
||||
return 'android';
|
||||
return 'macOS';
|
||||
case 'macOS':
|
||||
return 'android';
|
||||
default:
|
||||
|
||||
@ -10,6 +10,7 @@ import 'package:meta/meta.dart';
|
||||
|
||||
import 'base/common.dart';
|
||||
import 'base/file_system.dart';
|
||||
import 'base/logger.dart';
|
||||
import 'build_info.dart';
|
||||
import 'device.dart';
|
||||
import 'globals_null_migrated.dart' as globals;
|
||||
@ -51,7 +52,10 @@ class ColdRunner extends ResidentRunner {
|
||||
bool get canHotReload => false;
|
||||
|
||||
@override
|
||||
bool get canHotRestart => false;
|
||||
Logger get logger => globals.logger;
|
||||
|
||||
@override
|
||||
FileSystem get fileSystem => globals.fs;
|
||||
|
||||
@override
|
||||
Future<int> run({
|
||||
|
||||
@ -598,9 +598,6 @@ class HotRunner extends ResidentRunner {
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get supportsRestart => true;
|
||||
|
||||
@override
|
||||
Future<OperationResult> restart({
|
||||
bool fullRestart = false,
|
||||
@ -670,7 +667,7 @@ class HotRunner extends ResidentRunner {
|
||||
String reason,
|
||||
bool silent,
|
||||
}) async {
|
||||
if (!canHotRestart) {
|
||||
if (!supportsRestart) {
|
||||
return OperationResult(1, 'hotRestart not supported');
|
||||
}
|
||||
Status status;
|
||||
@ -1089,7 +1086,7 @@ class HotRunner extends ResidentRunner {
|
||||
void printHelp({ @required bool details }) {
|
||||
globals.printStatus('Flutter run key commands.');
|
||||
commandHelp.r.print();
|
||||
if (canHotRestart) {
|
||||
if (supportsRestart) {
|
||||
commandHelp.R.print();
|
||||
}
|
||||
commandHelp.h.print(); // TODO(ianh): print different message if "details" is false
|
||||
|
||||
@ -1684,16 +1684,6 @@ void main() {
|
||||
expect(testLogger.statusText, contains('1kB'));
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner clears the screen when it should', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
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(''));
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws RpcError', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
listViews,
|
||||
@ -1906,361 +1896,6 @@ void main() {
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpApp calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugDumpApp(), true);
|
||||
verify(mockFlutterDevice.debugDumpApp()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpApp does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugDumpApp(), false);
|
||||
verifyNever(mockFlutterDevice.debugDumpApp());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpRenderTree calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugDumpRenderTree(), true);
|
||||
verify(mockFlutterDevice.debugDumpRenderTree()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpRenderTree does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugDumpRenderTree(), false);
|
||||
verifyNever(mockFlutterDevice.debugDumpRenderTree());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpLayerTree calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugDumpLayerTree(), true);
|
||||
verify(mockFlutterDevice.debugDumpLayerTree()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpLayerTree does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugDumpLayerTree(), false);
|
||||
verifyNever(mockFlutterDevice.debugDumpLayerTree());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpLayerTree does not call flutter device if not running in debug mode', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugDumpLayerTree(), false);
|
||||
verifyNever(mockFlutterDevice.debugDumpLayerTree());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpSemanticsTreeInTraversalOrder calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugDumpSemanticsTreeInTraversalOrder(), true);
|
||||
verify(mockFlutterDevice.debugDumpSemanticsTreeInTraversalOrder()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpSemanticsTreeInTraversalOrder does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugDumpSemanticsTreeInTraversalOrder(), false);
|
||||
verifyNever(mockFlutterDevice.debugDumpSemanticsTreeInTraversalOrder());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpSemanticsTreeInInverseHitTestOrder calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugDumpSemanticsTreeInInverseHitTestOrder(), true);
|
||||
verify(mockFlutterDevice.debugDumpSemanticsTreeInInverseHitTestOrder()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugDumpSemanticsTreeInInverseHitTestOrder does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugDumpSemanticsTreeInInverseHitTestOrder(), false);
|
||||
verifyNever(mockFlutterDevice.debugDumpSemanticsTreeInInverseHitTestOrder());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleDebugPaintSizeEnabled calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugToggleDebugPaintSizeEnabled(), true);
|
||||
verify(mockFlutterDevice.toggleDebugPaintSizeEnabled()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleDebugPaintSizeEnabled does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugToggleDebugPaintSizeEnabled(), false);
|
||||
verifyNever(mockFlutterDevice.toggleDebugPaintSizeEnabled());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleBrightness calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugToggleBrightness(), true);
|
||||
verify(mockFlutterDevice.toggleBrightness()).called(2);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleBrightness does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugToggleBrightness(), false);
|
||||
verifyNever(mockFlutterDevice.toggleBrightness());
|
||||
}));
|
||||
|
||||
testUsingContext('FlutterDevice.toggleBrightness invokes correct VM service request', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
listViews,
|
||||
const FakeVmServiceRequest(
|
||||
method: 'ext.flutter.brightnessOverride',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
},
|
||||
jsonResponse: <String, Object>{
|
||||
'value': 'Brightness.dark'
|
||||
},
|
||||
),
|
||||
]);
|
||||
final FlutterDevice flutterDevice = FlutterDevice(
|
||||
mockDevice,
|
||||
buildInfo: BuildInfo.debug,
|
||||
);
|
||||
flutterDevice.vmService = fakeVmServiceHost.vmService;
|
||||
|
||||
expect(await flutterDevice.toggleBrightness(), Brightness.dark);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleInvertOversizedImages calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugToggleInvertOversizedImages(), true);
|
||||
verify(mockFlutterDevice.toggleInvertOversizedImages()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleInvertOversizedImages does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugToggleInvertOversizedImages(), false);
|
||||
verifyNever(mockFlutterDevice.toggleInvertOversizedImages());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleInvertOversizedImages does not call flutter device if in profile mode', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugToggleInvertOversizedImages(), false);
|
||||
verifyNever(mockFlutterDevice.toggleInvertOversizedImages());
|
||||
}));
|
||||
|
||||
testUsingContext('FlutterDevice.toggleInvertOversizedImages invokes correct VM service request', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
listViews,
|
||||
const FakeVmServiceRequest(
|
||||
method: 'ext.flutter.invertOversizedImages',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
},
|
||||
jsonResponse: <String, Object>{
|
||||
'value': 'false'
|
||||
},
|
||||
),
|
||||
]);
|
||||
final FlutterDevice flutterDevice = FlutterDevice(
|
||||
mockDevice,
|
||||
buildInfo: BuildInfo.debug,
|
||||
);
|
||||
flutterDevice.vmService = fakeVmServiceHost.vmService;
|
||||
|
||||
await flutterDevice.toggleInvertOversizedImages();
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleDebugCheckElevationsEnabled calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugToggleDebugCheckElevationsEnabled(), true);
|
||||
verify(mockFlutterDevice.toggleDebugCheckElevationsEnabled()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleDebugCheckElevationsEnabled does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugToggleDebugCheckElevationsEnabled(), false);
|
||||
verifyNever(mockFlutterDevice.toggleDebugCheckElevationsEnabled());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugTogglePerformanceOverlayOverride calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugTogglePerformanceOverlayOverride(), true);
|
||||
verify(mockFlutterDevice.debugTogglePerformanceOverlayOverride()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugTogglePerformanceOverlayOverride does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugTogglePerformanceOverlayOverride(), false);
|
||||
verifyNever(mockFlutterDevice.debugTogglePerformanceOverlayOverride());
|
||||
}));
|
||||
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleWidgetInspector calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
||||
expect(await residentRunner.debugToggleWidgetInspector(), true);
|
||||
verify(mockFlutterDevice.toggleWidgetInspector()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleWidgetInspector does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugToggleWidgetInspector(), false);
|
||||
verifyNever(mockFlutterDevice.toggleWidgetInspector());
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleProfileWidgetBuilds calls flutter device', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
await residentRunner.debugToggleProfileWidgetBuilds();
|
||||
|
||||
verify(mockFlutterDevice.toggleProfileWidgetBuilds()).called(1);
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner debugToggleProfileWidgetBuilds does not call flutter device if service protocol is unsupported', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
);
|
||||
|
||||
expect(await residentRunner.debugToggleProfileWidgetBuilds(), false);
|
||||
verifyNever(mockFlutterDevice.toggleProfileWidgetBuilds());
|
||||
}));
|
||||
|
||||
testUsingContext('HotRunner writes vm service file when providing debugging option', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
listViews,
|
||||
@ -2811,11 +2446,11 @@ void main() {
|
||||
}));
|
||||
|
||||
testUsingContext('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');
|
||||
expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsAssertionError);
|
||||
expect(nextPlatform('android'), 'iOS');
|
||||
expect(nextPlatform('iOS'), 'fuchsia');
|
||||
expect(nextPlatform('fuchsia'), 'macOS');
|
||||
expect(nextPlatform('macOS'), 'android');
|
||||
expect(() => nextPlatform('unknown'), throwsAssertionError);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -55,7 +55,6 @@ void main() {
|
||||
ipv6: true,
|
||||
stayResident: true,
|
||||
urlTunneller: null,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
systemClock: globals.systemClock,
|
||||
|
||||
@ -195,7 +195,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
@ -229,7 +228,7 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
@ -253,7 +252,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
@ -268,7 +266,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
@ -373,7 +370,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: logger,
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
@ -398,7 +394,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
@ -517,7 +512,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations.toList());
|
||||
@ -1439,7 +1433,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: logger,
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
@ -1487,7 +1480,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
logger: logger,
|
||||
usage: globals.flutterUsage,
|
||||
featureFlags: TestFeatureFlags(),
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
@ -1606,7 +1598,6 @@ ResidentRunner setUpResidentRunner(FlutterDevice flutterDevice, {
|
||||
systemClock: systemClock ?? SystemClock.fixed(DateTime.now()),
|
||||
fileSystem: globals.fs,
|
||||
logger: logger ?? BufferLogger.test(),
|
||||
featureFlags: TestFeatureFlags(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -240,7 +240,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('R - hotRestart supported and succeeds', () async {
|
||||
when(mockResidentRunner.canHotRestart).thenReturn(true);
|
||||
when(mockResidentRunner.supportsRestart).thenReturn(true);
|
||||
when(mockResidentRunner.hotMode).thenReturn(true);
|
||||
when(mockResidentRunner.restart(fullRestart: true))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
@ -252,7 +252,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('R - hotRestart supported and fails', () async {
|
||||
when(mockResidentRunner.canHotRestart).thenReturn(true);
|
||||
when(mockResidentRunner.supportsRestart).thenReturn(true);
|
||||
when(mockResidentRunner.hotMode).thenReturn(true);
|
||||
when(mockResidentRunner.restart(fullRestart: true))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
@ -266,7 +266,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('R - hotRestart supported and fails fatally', () async {
|
||||
when(mockResidentRunner.canHotRestart).thenReturn(true);
|
||||
when(mockResidentRunner.supportsRestart).thenReturn(true);
|
||||
when(mockResidentRunner.hotMode).thenReturn(true);
|
||||
when(mockResidentRunner.restart(fullRestart: true))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
@ -276,12 +276,23 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('R - hot restart unsupported', () async {
|
||||
when(mockResidentRunner.canHotRestart).thenReturn(false);
|
||||
when(mockResidentRunner.supportsRestart).thenReturn(false);
|
||||
await terminalHandler.processTerminalInput('R');
|
||||
|
||||
verifyNever(mockResidentRunner.restart(fullRestart: true));
|
||||
});
|
||||
|
||||
testWithoutContext('ResidentRunner clears the screen when it should', () async {
|
||||
const String message = 'This should be cleared';
|
||||
|
||||
expect(testLogger.statusText, equals(''));
|
||||
testLogger.printStatus(message);
|
||||
expect(testLogger.statusText, equals(message + '\n')); // printStatus makes a newline
|
||||
|
||||
await terminalHandler.processTerminalInput('c');
|
||||
expect(testLogger.statusText, equals(''));
|
||||
});
|
||||
|
||||
testWithoutContext('S - debugDumpSemanticsTreeInTraversalOrder with service protocol', () async {
|
||||
await terminalHandler.processTerminalInput('S');
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user