mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
This reverts commit 388dcd2478
.
This commit is contained in:
parent
ffbbf93c6b
commit
912c3ab171
@ -156,6 +156,8 @@ Future<void> main(List<String> args) async {
|
||||
processManager: globals.processManager,
|
||||
pubExecutable: globals.artifacts.getArtifactPath(Artifact.pubExecutable),
|
||||
logger: globals.logger,
|
||||
platform: globals.platform,
|
||||
persistentToolState: globals.persistentToolState,
|
||||
),
|
||||
Logger: () {
|
||||
final LoggerFactory loggerFactory = LoggerFactory(
|
||||
|
@ -101,6 +101,7 @@ class AttachCommand extends FlutterCommand {
|
||||
);
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
addDdsOptions(verboseHelp: verboseHelp);
|
||||
addDevToolsOptions();
|
||||
usesDeviceTimeoutOption();
|
||||
hotRunnerFactory ??= HotRunnerFactory();
|
||||
}
|
||||
@ -405,7 +406,11 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
||||
);
|
||||
flutterDevice.observatoryUris = observatoryUris;
|
||||
final List<FlutterDevice> flutterDevices = <FlutterDevice>[flutterDevice];
|
||||
final DebuggingOptions debuggingOptions = DebuggingOptions.enabled(buildInfo, disableDds: boolArg('disable-dds'));
|
||||
final DebuggingOptions debuggingOptions = DebuggingOptions.enabled(
|
||||
buildInfo,
|
||||
disableDds: boolArg('disable-dds'),
|
||||
devToolsServerAddress: devToolsServerAddress,
|
||||
);
|
||||
|
||||
return buildInfo.isDebug
|
||||
? hotRunnerFactory.build(
|
||||
|
@ -871,8 +871,7 @@ class DevToolsDomain extends Domain {
|
||||
|
||||
Future<Map<String, dynamic>> serve([ Map<String, dynamic> args ]) async {
|
||||
_devtoolsLauncher ??= DevtoolsLauncher.instance;
|
||||
final bool openInBrowser = args != null && (args['openInBrowser'] == 'true');
|
||||
final DevToolsServerAddress server = await _devtoolsLauncher.serve(openInBrowser: openInBrowser);
|
||||
final DevToolsServerAddress server = await _devtoolsLauncher.serve();
|
||||
return<String, dynamic>{
|
||||
'host': server?.host,
|
||||
'port': server?.port,
|
||||
|
@ -134,6 +134,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
usesDeviceUserOption();
|
||||
usesDeviceTimeoutOption();
|
||||
addDdsOptions(verboseHelp: verboseHelp);
|
||||
addDevToolsOptions();
|
||||
addAndroidSpecificBuildOptions(hide: !verboseHelp);
|
||||
}
|
||||
|
||||
@ -195,6 +196,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
hostVmServicePort: hostVmservicePort,
|
||||
disablePortPublication: disablePortPublication,
|
||||
ddsPort: ddsPort,
|
||||
devToolsServerAddress: devToolsServerAddress,
|
||||
verboseSystemLogs: boolArg('verbose-system-logs'),
|
||||
hostname: featureFlags.isWebEnabled ? stringArg('web-hostname') : '',
|
||||
port: featureFlags.isWebEnabled ? stringArg('web-port') : '',
|
||||
|
@ -184,6 +184,8 @@ Future<T> runInContext<T>(
|
||||
processManager: globals.processManager,
|
||||
pubExecutable: globals.artifacts.getArtifactPath(Artifact.pubExecutable),
|
||||
logger: globals.logger,
|
||||
platform: globals.platform,
|
||||
persistentToolState: globals.persistentToolState,
|
||||
),
|
||||
Doctor: () => Doctor(logger: globals.logger),
|
||||
DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
|
||||
|
@ -852,6 +852,7 @@ class DebuggingOptions {
|
||||
this.disablePortPublication = false,
|
||||
this.deviceVmServicePort,
|
||||
this.ddsPort,
|
||||
this.devToolsServerAddress,
|
||||
this.hostname,
|
||||
this.port,
|
||||
this.webEnableExposeUrl,
|
||||
@ -895,6 +896,7 @@ class DebuggingOptions {
|
||||
disablePortPublication = false,
|
||||
deviceVmServicePort = null,
|
||||
ddsPort = null,
|
||||
devToolsServerAddress = null,
|
||||
vmserviceOutFile = null,
|
||||
fastStart = false,
|
||||
webEnableExpressionEvaluation = false,
|
||||
@ -924,6 +926,7 @@ class DebuggingOptions {
|
||||
final int deviceVmServicePort;
|
||||
final bool disablePortPublication;
|
||||
final int ddsPort;
|
||||
final Uri devToolsServerAddress;
|
||||
final String port;
|
||||
final String hostname;
|
||||
final bool webEnableExposeUrl;
|
||||
|
@ -4,13 +4,15 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:browser_launcher/browser_launcher.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:process/process.dart';
|
||||
|
||||
import 'base/io.dart' as io;
|
||||
import 'base/logger.dart';
|
||||
import 'base/platform.dart';
|
||||
import 'convert.dart';
|
||||
import 'persistent_tool_state.dart';
|
||||
import 'resident_runner.dart';
|
||||
|
||||
/// An implementation of the devtools launcher that uses the server package.
|
||||
@ -19,59 +21,68 @@ import 'resident_runner.dart';
|
||||
/// a devtools dep in google3.
|
||||
class DevtoolsServerLauncher extends DevtoolsLauncher {
|
||||
DevtoolsServerLauncher({
|
||||
@required Platform platform,
|
||||
@required ProcessManager processManager,
|
||||
@required String pubExecutable,
|
||||
@required Logger logger,
|
||||
@required PersistentToolState persistentToolState,
|
||||
}) : _processManager = processManager,
|
||||
_pubExecutable = pubExecutable,
|
||||
_logger = logger;
|
||||
_logger = logger,
|
||||
_platform = platform,
|
||||
_persistentToolState = persistentToolState;
|
||||
|
||||
final ProcessManager _processManager;
|
||||
final String _pubExecutable;
|
||||
final Logger _logger;
|
||||
final Platform _platform;
|
||||
final PersistentToolState _persistentToolState;
|
||||
|
||||
io.Process _devToolsProcess;
|
||||
Uri _devToolsUri;
|
||||
|
||||
static final RegExp _serveDevToolsPattern =
|
||||
RegExp(r'Serving DevTools at ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)');
|
||||
|
||||
@override
|
||||
Future<void> launch(Uri vmServiceUri, {bool openInBrowser = false}) async {
|
||||
if (_devToolsProcess != null && _devToolsUri != null) {
|
||||
// DevTools is already running.
|
||||
if (openInBrowser) {
|
||||
await Chrome.start(<String>[_devToolsUri.toString()]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final Status status = _logger.startProgress(
|
||||
'Activating Dart DevTools...',
|
||||
);
|
||||
Future<void> launch(Uri vmServiceUri) async {
|
||||
// Place this entire method in a try/catch that swallows exceptions because
|
||||
// we do not want to block Flutter run/attach operations on a DevTools
|
||||
// failure.
|
||||
try {
|
||||
// TODO(kenz): https://github.com/dart-lang/pub/issues/2791 - calling `pub
|
||||
// global activate` adds ~ 4.5 seconds of latency.
|
||||
final io.ProcessResult _devToolsActivateProcess = await _processManager.run(<String>[
|
||||
_pubExecutable,
|
||||
'global',
|
||||
'activate',
|
||||
'devtools'
|
||||
]);
|
||||
if (_devToolsActivateProcess.exitCode != 0) {
|
||||
status.cancel();
|
||||
_logger.printError('Error running `pub global activate '
|
||||
'devtools`:\n${_devToolsActivateProcess.stderr}');
|
||||
return;
|
||||
bool offline = false;
|
||||
try {
|
||||
const String pubHostedUrlKey = 'PUB_HOSTED_URL';
|
||||
if (_platform.environment.containsKey(pubHostedUrlKey)) {
|
||||
await http.head(_platform.environment[pubHostedUrlKey]);
|
||||
} else {
|
||||
await http.head('https://pub.dev');
|
||||
}
|
||||
} on Exception {
|
||||
offline = true;
|
||||
}
|
||||
|
||||
if (offline) {
|
||||
// TODO(kenz): we should launch an already activated version of DevTools
|
||||
// here, if available, once DevTools has offline support. DevTools does
|
||||
// not work without internet currently due to the failed request of a
|
||||
// couple scripts. See https://github.com/flutter/devtools/issues/2420.
|
||||
return;
|
||||
} else {
|
||||
final bool didActivateDevTools = await _activateDevTools();
|
||||
final bool devToolsActive = await _checkForActiveDevTools();
|
||||
if (!didActivateDevTools && !devToolsActive) {
|
||||
// At this point, we failed to activate the DevTools package and the
|
||||
// package is not already active.
|
||||
return;
|
||||
}
|
||||
}
|
||||
status.stop();
|
||||
|
||||
_devToolsProcess = await _processManager.start(<String>[
|
||||
_pubExecutable,
|
||||
'global',
|
||||
'run',
|
||||
'devtools',
|
||||
if (!openInBrowser) '--no-launch-browser',
|
||||
'--no-launch-browser',
|
||||
if (vmServiceUri != null) '--vm-uri=$vmServiceUri',
|
||||
]);
|
||||
final Completer<Uri> completer = Completer<Uri>();
|
||||
@ -91,30 +102,83 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
|
||||
}
|
||||
completer.complete(Uri.parse(uri));
|
||||
}
|
||||
_logger.printStatus(line);
|
||||
});
|
||||
_devToolsProcess.stderr
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.listen(_logger.printError);
|
||||
_devToolsUri = await completer.future;
|
||||
devToolsUri = await completer.future
|
||||
.timeout(const Duration(seconds: 10));
|
||||
} on Exception catch (e, st) {
|
||||
status.cancel();
|
||||
_logger.printError('Failed to launch DevTools: $e', stackTrace: st);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DevToolsServerAddress> serve({bool openInBrowser = false}) async {
|
||||
await launch(null, openInBrowser: openInBrowser);
|
||||
if (_devToolsUri == null) {
|
||||
return null;
|
||||
Future<bool> _checkForActiveDevTools() async {
|
||||
// We are offline, and cannot activate DevTools, so check if the DevTools
|
||||
// package is already active.
|
||||
final io.ProcessResult _pubGlobalListProcess = await _processManager.run(<String>[
|
||||
_pubExecutable,
|
||||
'global',
|
||||
'list',
|
||||
]);
|
||||
|
||||
if (_pubGlobalListProcess.stdout.toString().contains('devtools ')) {
|
||||
return true;
|
||||
}
|
||||
return DevToolsServerAddress(_devToolsUri.host, _devToolsUri.port);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Helper method to activate the DevTools pub package.
|
||||
///
|
||||
/// Returns a bool indicating whether or not the package was successfully
|
||||
/// activated from pub.
|
||||
Future<bool> _activateDevTools() async {
|
||||
final DateTime now = DateTime.now();
|
||||
// Only attempt to activate DevTools twice a day.
|
||||
final bool shouldActivate =
|
||||
_persistentToolState.lastDevToolsActivationTime == null ||
|
||||
now.difference(_persistentToolState.lastDevToolsActivationTime).inHours >= 12;
|
||||
if (!shouldActivate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Status status = _logger.startProgress(
|
||||
'Activating Dart DevTools...',
|
||||
);
|
||||
try {
|
||||
final io.ProcessResult _devToolsActivateProcess = await _processManager
|
||||
.run(<String>[
|
||||
_pubExecutable,
|
||||
'global',
|
||||
'activate',
|
||||
'devtools'
|
||||
]);
|
||||
if (_devToolsActivateProcess.exitCode != 0) {
|
||||
status.cancel();
|
||||
_logger.printError('Error running `pub global activate '
|
||||
'devtools`:\n${_devToolsActivateProcess.stderr}');
|
||||
return false;
|
||||
}
|
||||
status.stop();
|
||||
_persistentToolState.lastDevToolsActivationTime = DateTime.now();
|
||||
return true;
|
||||
} on Exception catch (e, _) {
|
||||
status.stop();
|
||||
_logger.printError('Error running `pub global activate devtools`: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DevToolsServerAddress> serve() async {
|
||||
await launch(null);
|
||||
return activeDevToolsServer;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
devToolsUri = null;
|
||||
if (_devToolsProcess != null) {
|
||||
_devToolsProcess.kill();
|
||||
await _devToolsProcess.exitCode;
|
||||
|
@ -52,6 +52,9 @@ abstract class PersistentToolState {
|
||||
|
||||
/// Whether this client was already determined to be or not be a bot.
|
||||
bool isRunningOnBot;
|
||||
|
||||
/// The last time the the DevTools package was activated from pub.
|
||||
DateTime lastDevToolsActivationTime;
|
||||
}
|
||||
|
||||
class _DefaultPersistentToolState implements PersistentToolState {
|
||||
@ -85,6 +88,7 @@ class _DefaultPersistentToolState implements PersistentToolState {
|
||||
Channel.stable: 'last-active-stable-version'
|
||||
};
|
||||
static const String _kBotKey = 'is-bot';
|
||||
static const String _kLastDevToolsActivationTimeKey = 'last-devtools-activation-time';
|
||||
static const String _kLicenseHash = 'license-hash';
|
||||
|
||||
final Config _config;
|
||||
@ -131,4 +135,14 @@ class _DefaultPersistentToolState implements PersistentToolState {
|
||||
|
||||
@override
|
||||
set isRunningOnBot(bool value) => _config.setValue(_kBotKey, value);
|
||||
|
||||
@override
|
||||
DateTime get lastDevToolsActivationTime {
|
||||
final String value = _config.getValue(_kLastDevToolsActivationTimeKey) as String;
|
||||
return value != null ? DateTime.parse(value) : null;
|
||||
}
|
||||
|
||||
@override
|
||||
set lastDevToolsActivationTime(DateTime time) =>
|
||||
_config.setValue(_kLastDevToolsActivationTimeKey, time.toString());
|
||||
}
|
||||
|
@ -774,7 +774,7 @@ abstract class ResidentRunner {
|
||||
final CommandHelp commandHelp;
|
||||
final bool machine;
|
||||
|
||||
DevtoolsLauncher _devtoolsLauncher;
|
||||
DevtoolsLauncher _devToolsLauncher;
|
||||
|
||||
bool _exited = false;
|
||||
Completer<int> _finished = Completer<int>();
|
||||
@ -926,7 +926,7 @@ abstract class ResidentRunner {
|
||||
}
|
||||
|
||||
@protected
|
||||
void writeVmserviceFile() {
|
||||
void writeVmServiceFile() {
|
||||
if (debuggingOptions.vmserviceOutFile != null) {
|
||||
try {
|
||||
final String address = flutterDevices.first.vmService.wsAddress.toString();
|
||||
@ -941,7 +941,7 @@ abstract class ResidentRunner {
|
||||
|
||||
Future<void> exit() async {
|
||||
_exited = true;
|
||||
await shutdownDevtools();
|
||||
await shutdownDevTools();
|
||||
await stopEchoingDeviceLog();
|
||||
await preExit();
|
||||
await exitApp();
|
||||
@ -949,7 +949,7 @@ abstract class ResidentRunner {
|
||||
}
|
||||
|
||||
Future<void> detach() async {
|
||||
await shutdownDevtools();
|
||||
await shutdownDevTools();
|
||||
await stopEchoingDeviceLog();
|
||||
await preExit();
|
||||
await shutdownDartDevelopmentService();
|
||||
@ -1250,22 +1250,29 @@ abstract class ResidentRunner {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> launchDevTools({bool openInBrowser = false}) async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return false;
|
||||
}
|
||||
assert(supportsServiceProtocol);
|
||||
_devtoolsLauncher ??= DevtoolsLauncher.instance;
|
||||
unawaited(_devtoolsLauncher.launch(
|
||||
flutterDevices.first.vmService.httpAddress,
|
||||
openInBrowser: openInBrowser,
|
||||
));
|
||||
return true;
|
||||
DevToolsServerAddress activeDevToolsServer() {
|
||||
_devToolsLauncher ??= DevtoolsLauncher.instance;
|
||||
return _devToolsLauncher.activeDevToolsServer;
|
||||
}
|
||||
|
||||
Future<void> shutdownDevtools() async {
|
||||
await _devtoolsLauncher?.close();
|
||||
_devtoolsLauncher = null;
|
||||
Future<void> serveDevToolsGracefully({
|
||||
Uri devToolsServerAddress
|
||||
}) async {
|
||||
if (!supportsServiceProtocol) {
|
||||
return;
|
||||
}
|
||||
|
||||
_devToolsLauncher ??= DevtoolsLauncher.instance;
|
||||
if (devToolsServerAddress != null) {
|
||||
_devToolsLauncher.devToolsUri = devToolsServerAddress;
|
||||
} else {
|
||||
await _devToolsLauncher.serve();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> shutdownDevTools() async {
|
||||
await _devToolsLauncher?.close();
|
||||
_devToolsLauncher = null;
|
||||
}
|
||||
|
||||
Future<void> _serviceProtocolDone(dynamic object) async {
|
||||
@ -1551,8 +1558,6 @@ class TerminalHandler {
|
||||
return residentRunner.debugDumpRenderTree();
|
||||
case 'U':
|
||||
return residentRunner.debugDumpSemanticsTreeInInverseHitTestOrder();
|
||||
case 'v':
|
||||
return residentRunner.launchDevTools(openInBrowser: true);
|
||||
case 'w':
|
||||
case 'W':
|
||||
return residentRunner.debugDumpApp();
|
||||
@ -1645,16 +1650,25 @@ String nextPlatform(String currentPlatform, FeatureFlags featureFlags) {
|
||||
|
||||
/// A launcher for the devtools debugger and analysis tool.
|
||||
abstract class DevtoolsLauncher {
|
||||
Uri devToolsUri;
|
||||
|
||||
/// Launch a Dart DevTools process, optionally targeting a specific VM Service
|
||||
/// URI if [vmServiceUri] is non-null.
|
||||
Future<void> launch(Uri vmServiceUri, {bool openInBrowser = false});
|
||||
Future<void> launch(Uri vmServiceUri);
|
||||
|
||||
/// Serve Dart DevTools and return the host and port they are available on.
|
||||
Future<DevToolsServerAddress> serve({bool openInBrowser = false});
|
||||
Future<DevToolsServerAddress> serve();
|
||||
|
||||
Future<void> close();
|
||||
|
||||
static DevtoolsLauncher get instance => context.get<DevtoolsLauncher>();
|
||||
|
||||
DevToolsServerAddress get activeDevToolsServer {
|
||||
if (devToolsUri == null) {
|
||||
return null;
|
||||
}
|
||||
return DevToolsServerAddress(devToolsUri.host, devToolsUri.port);
|
||||
}
|
||||
}
|
||||
|
||||
class DevToolsServerAddress {
|
||||
@ -1662,4 +1676,11 @@ class DevToolsServerAddress {
|
||||
|
||||
final String host;
|
||||
final int port;
|
||||
|
||||
Uri get uri {
|
||||
if (host == null || port == null) {
|
||||
return null;
|
||||
}
|
||||
return Uri(scheme: 'http', host: host, port: port);
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,12 @@ class ColdRunner extends ResidentRunner {
|
||||
// Connect to observatory.
|
||||
if (debuggingOptions.debuggingEnabled) {
|
||||
try {
|
||||
await connectToServiceProtocol();
|
||||
await Future.wait(<Future<void>>[
|
||||
connectToServiceProtocol(),
|
||||
serveDevToolsGracefully(
|
||||
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
|
||||
),
|
||||
]);
|
||||
} on String catch (message) {
|
||||
globals.printError(message);
|
||||
appFailedToStart();
|
||||
@ -115,7 +120,7 @@ class ColdRunner extends ResidentRunner {
|
||||
|
||||
appStartedCompleter?.complete();
|
||||
|
||||
writeVmserviceFile();
|
||||
writeVmServiceFile();
|
||||
|
||||
if (stayResident && !traceStartup) {
|
||||
return waitForAppToFinish();
|
||||
@ -132,10 +137,15 @@ class ColdRunner extends ResidentRunner {
|
||||
}) async {
|
||||
_didAttach = true;
|
||||
try {
|
||||
await connectToServiceProtocol(
|
||||
getSkSLMethod: writeSkSL,
|
||||
allowExistingDdsInstance: allowExistingDdsInstance,
|
||||
);
|
||||
await Future.wait(<Future<void>>[
|
||||
connectToServiceProtocol(
|
||||
getSkSLMethod: writeSkSL,
|
||||
allowExistingDdsInstance: allowExistingDdsInstance,
|
||||
),
|
||||
serveDevToolsGracefully(
|
||||
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
|
||||
),
|
||||
]);
|
||||
} on Exception catch (error) {
|
||||
globals.printError('Error connecting to the service protocol: $error');
|
||||
return 2;
|
||||
@ -195,6 +205,19 @@ class ColdRunner extends ResidentRunner {
|
||||
'An Observatory debugger and profiler on $dname is available at: '
|
||||
'${device.vmService.httpAddress}',
|
||||
);
|
||||
|
||||
final DevToolsServerAddress devToolsServerAddress = activeDevToolsServer();
|
||||
if (devToolsServerAddress != null) {
|
||||
final Uri uri = devToolsServerAddress.uri?.replace(
|
||||
queryParameters: <String, dynamic>{'uri': '${device.vmService.httpAddress}'},
|
||||
);
|
||||
if (uri != null) {
|
||||
globals.printStatus(
|
||||
'\nFlutter DevTools, a Flutter debugger and profiler, on '
|
||||
'${device.device.name} is available at: $uri',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,13 +174,18 @@ class HotRunner extends ResidentRunner {
|
||||
}) async {
|
||||
_didAttach = true;
|
||||
try {
|
||||
await connectToServiceProtocol(
|
||||
reloadSources: _reloadSourcesService,
|
||||
restart: _restartService,
|
||||
compileExpression: _compileExpressionService,
|
||||
getSkSLMethod: writeSkSL,
|
||||
allowExistingDdsInstance: allowExistingDdsInstance,
|
||||
);
|
||||
await Future.wait(<Future<void>>[
|
||||
connectToServiceProtocol(
|
||||
reloadSources: _reloadSourcesService,
|
||||
restart: _restartService,
|
||||
compileExpression: _compileExpressionService,
|
||||
getSkSLMethod: writeSkSL,
|
||||
allowExistingDdsInstance: allowExistingDdsInstance,
|
||||
),
|
||||
serveDevToolsGracefully(
|
||||
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
|
||||
),
|
||||
]);
|
||||
// Catches all exceptions, non-Exception objects are rethrown.
|
||||
} catch (error) { // ignore: avoid_catches_without_on_clauses
|
||||
if (error is! Exception && error is! String) {
|
||||
@ -280,7 +285,7 @@ class HotRunner extends ResidentRunner {
|
||||
benchmarkOutput.writeAsStringSync(toPrettyJson(benchmarkData));
|
||||
return 0;
|
||||
}
|
||||
writeVmserviceFile();
|
||||
writeVmServiceFile();
|
||||
|
||||
int result = 0;
|
||||
if (stayResident) {
|
||||
@ -1087,6 +1092,19 @@ class HotRunner extends ResidentRunner {
|
||||
'An Observatory debugger and profiler on ${device.device.name} is available at: '
|
||||
'${device.vmService.httpAddress}',
|
||||
);
|
||||
|
||||
final DevToolsServerAddress devToolsServerAddress = activeDevToolsServer();
|
||||
if (devToolsServerAddress != null) {
|
||||
final Uri uri = devToolsServerAddress.uri?.replace(
|
||||
queryParameters: <String, dynamic>{'uri': '${device.vmService.httpAddress}'},
|
||||
);
|
||||
if (uri != null) {
|
||||
globals.printStatus(
|
||||
'\nFlutter DevTools, a Flutter debugger and profiler, on '
|
||||
'${device.device.name} is available at: $uri',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
globals.printStatus('');
|
||||
if (debuggingOptions.buildInfo.nullSafetyMode == NullSafetyMode.sound) {
|
||||
|
@ -128,6 +128,9 @@ abstract class FlutterCommand extends Command<void> {
|
||||
/// The option name for a custom observatory port.
|
||||
static const String observatoryPortOption = 'observatory-port';
|
||||
|
||||
/// The option name for a custom DevTools server address.
|
||||
static const String kDevToolsServerAddress = 'devtools-server-address';
|
||||
|
||||
/// The flag name for whether or not to use ipv6.
|
||||
static const String ipv6Flag = 'ipv6';
|
||||
|
||||
@ -322,6 +325,13 @@ abstract class FlutterCommand extends Command<void> {
|
||||
_usesPortOption = true;
|
||||
}
|
||||
|
||||
void addDevToolsOptions() {
|
||||
argParser.addOption(kDevToolsServerAddress,
|
||||
help: 'When this value is provided, the Flutter tool will not spin up a '
|
||||
'new DevTools server instance, but instead will use the one provided '
|
||||
'at this address.');
|
||||
}
|
||||
|
||||
void addDdsOptions({@required bool verboseHelp}) {
|
||||
argParser.addOption('dds-port',
|
||||
help: 'When this value is provided, the Dart Development Service (DDS) will be '
|
||||
@ -365,6 +375,16 @@ abstract class FlutterCommand extends Command<void> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Uri get devToolsServerAddress {
|
||||
if (argResults.wasParsed(kDevToolsServerAddress)) {
|
||||
final Uri uri = Uri.tryParse(stringArg(kDevToolsServerAddress));
|
||||
if (uri != null && uri.host.isNotEmpty && uri.port != 0) {
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Gets the vmservice port provided to in the 'observatory-port' or
|
||||
/// 'host-vmservice-port option.
|
||||
///
|
||||
|
@ -4,20 +4,41 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/devtools_launcher.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:flutter_tools/src/persistent_tool_state.dart';
|
||||
import 'package:flutter_tools/src/resident_runner.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
|
||||
void main() {
|
||||
BufferLogger logger;
|
||||
FakePlatform platform;
|
||||
PersistentToolState persistentToolState;
|
||||
|
||||
setUp(() {
|
||||
logger = BufferLogger.test();
|
||||
platform = FakePlatform(environment: <String, String>{});
|
||||
|
||||
final Directory tempDir = globals.fs.systemTempDirectory.createTempSync('devtools_launcher_test');
|
||||
persistentToolState = PersistentToolState.test(
|
||||
directory: tempDir,
|
||||
logger: logger,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher launches DevTools through pub and saves the URI', () async {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
pubExecutable: 'pub',
|
||||
logger: BufferLogger.test(),
|
||||
logger: logger,
|
||||
platform: platform,
|
||||
persistentToolState: persistentToolState,
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
@ -28,6 +49,14 @@ void main() {
|
||||
],
|
||||
stdout: 'Activated DevTools 0.9.5',
|
||||
),
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'pub',
|
||||
'global',
|
||||
'list',
|
||||
],
|
||||
stdout: 'devtools 0.9.6',
|
||||
),
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'pub',
|
||||
@ -51,7 +80,9 @@ void main() {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
pubExecutable: 'pub',
|
||||
logger: BufferLogger.test(),
|
||||
logger: logger,
|
||||
platform: platform,
|
||||
persistentToolState: persistentToolState,
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
@ -62,12 +93,21 @@ void main() {
|
||||
],
|
||||
stdout: 'Activated DevTools 0.9.5',
|
||||
),
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'pub',
|
||||
'global',
|
||||
'list',
|
||||
],
|
||||
stdout: 'devtools 0.9.6',
|
||||
),
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'pub',
|
||||
'global',
|
||||
'run',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
],
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100\n',
|
||||
completer: completer,
|
||||
@ -75,16 +115,49 @@ void main() {
|
||||
]),
|
||||
);
|
||||
|
||||
final DevToolsServerAddress address = await launcher.serve(openInBrowser: true);
|
||||
final DevToolsServerAddress address = await launcher.serve();
|
||||
expect(address.host, '127.0.0.1');
|
||||
expect(address.port, 9100);
|
||||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher prints error if exception is thrown during activate', () async {
|
||||
final BufferLogger logger = BufferLogger.test();
|
||||
testWithoutContext('DevtoolsLauncher does not activate DevTools if it was recently activated', () async {
|
||||
persistentToolState.lastDevToolsActivationTime = DateTime.now();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
pubExecutable: 'pub',
|
||||
logger: logger,
|
||||
platform: platform,
|
||||
persistentToolState: persistentToolState,
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'pub',
|
||||
'global',
|
||||
'list',
|
||||
],
|
||||
stdout: 'devtools 0.9.6',
|
||||
),
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'pub',
|
||||
'global',
|
||||
'run',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
],
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100\n',
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
await launcher.serve();
|
||||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher prints error if exception is thrown during activate', () async {
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
pubExecutable: 'pub',
|
||||
logger: logger,
|
||||
platform: platform,
|
||||
persistentToolState: persistentToolState,
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
@ -96,6 +169,14 @@ void main() {
|
||||
stderr: 'Error - could not activate devtools',
|
||||
exitCode: 1,
|
||||
),
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'pub',
|
||||
'global',
|
||||
'list',
|
||||
],
|
||||
stdout: 'devtools 0.9.6',
|
||||
),
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'pub',
|
||||
@ -118,10 +199,11 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher prints error if exception is thrown during launch', () async {
|
||||
final BufferLogger logger = BufferLogger.test();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
pubExecutable: 'pub',
|
||||
logger: logger,
|
||||
platform: platform,
|
||||
persistentToolState: persistentToolState,
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
@ -132,6 +214,14 @@ void main() {
|
||||
],
|
||||
stdout: 'Activated DevTools 0.9.5',
|
||||
),
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'pub',
|
||||
'global',
|
||||
'list',
|
||||
],
|
||||
stdout: 'devtools 0.9.6',
|
||||
),
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'pub',
|
||||
|
@ -57,4 +57,23 @@ void main() {
|
||||
expect(state2.lastActiveVersion(Channel.beta), 'ghi');
|
||||
expect(state2.lastActiveVersion(Channel.stable), 'jkl');
|
||||
});
|
||||
|
||||
testWithoutContext('lastDevToolsActivationTime can be cached and stored', () {
|
||||
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
|
||||
final Directory directory = fileSystem.directory('state_dir')..createSync();
|
||||
final PersistentToolState state1 = PersistentToolState.test(
|
||||
directory: directory,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
|
||||
final DateTime time = DateTime.now();
|
||||
state1.lastDevToolsActivationTime = time;
|
||||
|
||||
final PersistentToolState state2 = PersistentToolState.test(
|
||||
directory: directory,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
|
||||
expect(state2.lastDevToolsActivationTime, equals(time));
|
||||
});
|
||||
}
|
||||
|
@ -229,7 +229,9 @@ void main() {
|
||||
expect((await connectionInfo).baseUri, 'foo://bar');
|
||||
expect(onAppStart.isCompleted, true);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner suppresses errors for the initial compilation', () => testbed.run(() async {
|
||||
globals.fs.file(globals.fs.path.join('lib', 'main.dart'))
|
||||
@ -274,7 +276,9 @@ void main() {
|
||||
suppressErrors: true,
|
||||
)).called(1);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/60613
|
||||
testUsingContext('ResidentRunner calls appFailedToStart if initial compilation fails', () => testbed.run(() async {
|
||||
@ -406,7 +410,9 @@ void main() {
|
||||
suppressErrors: false,
|
||||
)).called(1);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner can attach to device successfully with --fast-start', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -486,7 +492,9 @@ void main() {
|
||||
expect((await connectionInfo).baseUri, 'foo://bar');
|
||||
expect(onAppStart.isCompleted, true);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner can handle an RPC exception from hot reload', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -539,7 +547,9 @@ void main() {
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
Usage: () => MockUsage(),
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner fails its operation if the device initialization is not complete', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -624,7 +634,9 @@ void main() {
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
Usage: () => MockUsage(),
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner reports hot reload event with null safety analytics', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -688,6 +700,7 @@ void main() {
|
||||
})).called(1);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
Usage: () => MockUsage(),
|
||||
}));
|
||||
|
||||
@ -756,7 +769,9 @@ void main() {
|
||||
|
||||
expect(result.code, 0);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner reports error with missing entrypoint file', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -840,7 +855,9 @@ void main() {
|
||||
expect(testLogger.errorText, contains('The entrypoint file (i.e. the file with main())'));
|
||||
expect(result.fatal, false);
|
||||
expect(result.code, 0);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner resets compilation time on reload reject', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -928,7 +945,9 @@ void main() {
|
||||
expect(result.message, contains('Reload rejected: Failed to hot reload')); // contains error message from reload report.
|
||||
expect(result.code, 1);
|
||||
verify(mockDevFS.resetLastCompiled()).called(1); // compilation time is reset.
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner can send target platform to analytics from hot reload', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -1000,7 +1019,9 @@ void main() {
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
Usage: () => MockUsage(),
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner can perform fast reassemble', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -1114,7 +1135,9 @@ void main() {
|
||||
ProjectFileInvalidator: () => FakeProjectFileInvalidator(),
|
||||
Usage: () => MockUsage(),
|
||||
FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true),
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -1184,7 +1207,9 @@ void main() {
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
Usage: () => MockUsage(),
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner can remove breakpoints from paused isolate during hot restart', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -1260,7 +1285,9 @@ void main() {
|
||||
|
||||
expect(result.isOk, true);
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner will alternative the name of the dill file uploaded for a hot restart', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -1392,7 +1419,9 @@ void main() {
|
||||
await residentRunner.restart(fullRestart: true);
|
||||
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner Can handle an RPC exception from hot restart', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -1445,7 +1474,9 @@ void main() {
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
Usage: () => MockUsage(),
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner uses temp directory when there is no output dill path', () => testbed.run(() {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
@ -1650,13 +1681,88 @@ void main() {
|
||||
)
|
||||
}));
|
||||
|
||||
testUsingContext('ResidentRunner invokes DevtoolsLauncher when launching and shutting down Devtools', () => testbed.run(() async {
|
||||
when(mockFlutterDevice.vmService).thenReturn(fakeVmServiceHost.vmService);
|
||||
setHttpAddress(testUri, fakeVmServiceHost.vmService);
|
||||
await residentRunner.launchDevTools();
|
||||
verify(mockDevtoolsLauncher.launch(testUri)).called(1);
|
||||
testUsingContext('ResidentRunner invokes DevToolsLauncher when attaching and shutting down DevTools', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
listViews,
|
||||
listViews,
|
||||
setAssetBundlePath,
|
||||
]);
|
||||
final Future<int> result = residentRunner.attach();
|
||||
expect(await result, 0);
|
||||
|
||||
await residentRunner.shutdownDevtools();
|
||||
// Verify DevTools was served.
|
||||
verify(mockDevtoolsLauncher.serve()).called(1);
|
||||
|
||||
// Shutdown
|
||||
await residentRunner.shutdownDevTools();
|
||||
verify(mockDevtoolsLauncher.close()).called(1);
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner invokes DevtoolsLauncher when attaching and shutting down - cold mode', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
listViews,
|
||||
listViews,
|
||||
setAssetBundlePath,
|
||||
]);
|
||||
residentRunner = ColdRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'),
|
||||
target: 'main.dart',
|
||||
);
|
||||
when(mockFlutterDevice.runCold(
|
||||
coldRunner: anyNamed('coldRunner'),
|
||||
route: anyNamed('route'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return 0;
|
||||
});
|
||||
|
||||
final Future<int> result = residentRunner.attach();
|
||||
expect(await result, 0);
|
||||
|
||||
// Verify DevTools was served.
|
||||
verify(mockDevtoolsLauncher.serve()).called(1);
|
||||
|
||||
// Shutdown
|
||||
await residentRunner.shutdownDevTools();
|
||||
verify(mockDevtoolsLauncher.close()).called(1);
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('ResidentRunner invokes DevtoolsLauncher when running and shutting down - cold mode', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
listViews,
|
||||
listViews,
|
||||
setAssetBundlePath,
|
||||
]);
|
||||
residentRunner = ColdRunner(
|
||||
<FlutterDevice>[
|
||||
mockFlutterDevice,
|
||||
],
|
||||
stayResident: false,
|
||||
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'),
|
||||
target: 'main.dart',
|
||||
);
|
||||
when(mockFlutterDevice.runCold(
|
||||
coldRunner: anyNamed('coldRunner'),
|
||||
route: anyNamed('route'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return 0;
|
||||
});
|
||||
|
||||
final Future<int> result = residentRunner.run();
|
||||
expect(await result, 0);
|
||||
|
||||
// Verify DevTools was served.
|
||||
verify(mockDevtoolsLauncher.serve()).called(1);
|
||||
|
||||
// Shutdown
|
||||
await residentRunner.shutdownDevTools();
|
||||
verify(mockDevtoolsLauncher.close()).called(1);
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
@ -2299,7 +2405,9 @@ void main() {
|
||||
await residentRunner.run();
|
||||
|
||||
expect(await globals.fs.file('foo').readAsString(), testUri.toString());
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('HotRunner copies compiled app.dill to cache during startup', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -2327,7 +2435,9 @@ void main() {
|
||||
await residentRunner.run();
|
||||
|
||||
expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill')).readAsString(), 'ABC');
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('HotRunner copies compiled app.dill to cache during startup with dart defines', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -2363,7 +2473,9 @@ void main() {
|
||||
|
||||
expect(await globals.fs.file(globals.fs.path.join(
|
||||
'build', '187ef4436122d1cc2f40dc2b92f0eba0.cache.dill')).readAsString(), 'ABC');
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('HotRunner copies compiled app.dill to cache during startup with null safety', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -2399,7 +2511,9 @@ void main() {
|
||||
|
||||
expect(await globals.fs.file(globals.fs.path.join(
|
||||
'build', '3416d3007730479552122f01c01e326d.cache.dill')).readAsString(), 'ABC');
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('HotRunner does not copy app.dill if a dillOutputPath is given', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -2428,7 +2542,9 @@ void main() {
|
||||
await residentRunner.run();
|
||||
|
||||
expect(globals.fs.file(globals.fs.path.join('build', 'cache.dill')), isNot(exists));
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('HotRunner copies compiled app.dill to cache during startup with --track-widget-creation', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -2461,7 +2577,9 @@ void main() {
|
||||
await residentRunner.run();
|
||||
|
||||
expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill.track.dill')).readAsString(), 'ABC');
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('HotRunner unforwards device ports', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -2494,7 +2612,9 @@ void main() {
|
||||
await residentRunner.run();
|
||||
|
||||
verify(mockPortForwarder.dispose()).called(1);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('HotRunner handles failure to write vmservice file', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
|
||||
@ -2523,7 +2643,9 @@ void main() {
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => ThrowingForwardingFileSystem(MemoryFileSystem.test()),
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
|
||||
testUsingContext('ColdRunner writes vm service file when providing debugging option', () => testbed.run(() async {
|
||||
@ -2550,7 +2672,9 @@ void main() {
|
||||
|
||||
expect(await globals.fs.file('foo').readAsString(), testUri.toString());
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
}));
|
||||
}), overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => mockDevtoolsLauncher,
|
||||
});
|
||||
|
||||
testUsingContext('FlutterDevice uses dartdevc configuration when targeting web', () async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
|
@ -290,6 +290,48 @@ void main() {
|
||||
expect(FlutterCommandResult.warning().exitStatus, ExitStatus.warning);
|
||||
});
|
||||
|
||||
testUsingContext('devToolsServerAddress returns parsed uri', () async {
|
||||
final DummyFlutterCommand command = DummyFlutterCommand()..addDevToolsOptions();
|
||||
await createTestCommandRunner(command).run(<String>[
|
||||
'dummy',
|
||||
'--${FlutterCommand.kDevToolsServerAddress}',
|
||||
'http://127.0.0.1:9105',
|
||||
]);
|
||||
expect(command.devToolsServerAddress.toString(), equals('http://127.0.0.1:9105'));
|
||||
});
|
||||
|
||||
testUsingContext('devToolsServerAddress returns null for bad input', () async {
|
||||
final DummyFlutterCommand command = DummyFlutterCommand()..addDevToolsOptions();
|
||||
final CommandRunner<void> runner = createTestCommandRunner(command);
|
||||
await runner.run(<String>[
|
||||
'dummy',
|
||||
'--${FlutterCommand.kDevToolsServerAddress}',
|
||||
'hello-world',
|
||||
]);
|
||||
expect(command.devToolsServerAddress, isNull);
|
||||
|
||||
await runner.run(<String>[
|
||||
'dummy',
|
||||
'--${FlutterCommand.kDevToolsServerAddress}',
|
||||
'',
|
||||
]);
|
||||
expect(command.devToolsServerAddress, isNull);
|
||||
|
||||
await runner.run(<String>[
|
||||
'dummy',
|
||||
'--${FlutterCommand.kDevToolsServerAddress}',
|
||||
'9101',
|
||||
]);
|
||||
expect(command.devToolsServerAddress, isNull);
|
||||
|
||||
await runner.run(<String>[
|
||||
'dummy',
|
||||
'--${FlutterCommand.kDevToolsServerAddress}',
|
||||
'127.0.0.1:9101',
|
||||
]);
|
||||
expect(command.devToolsServerAddress, isNull);
|
||||
});
|
||||
|
||||
group('signals tests', () {
|
||||
MockIoProcessSignal mockSignal;
|
||||
ProcessSignal signalUnderTest;
|
||||
|
@ -285,13 +285,6 @@ void main() {
|
||||
verify(mockResidentRunner.debugDumpSemanticsTreeInInverseHitTestOrder()).called(1);
|
||||
});
|
||||
|
||||
testWithoutContext('v - launchDevTools', () async {
|
||||
when(mockResidentRunner.supportsServiceProtocol).thenReturn(true);
|
||||
await terminalHandler.processTerminalInput('v');
|
||||
|
||||
verify(mockResidentRunner.launchDevTools(openInBrowser: true)).called(1);
|
||||
});
|
||||
|
||||
testWithoutContext('w,W - debugDumpApp with service protocol', () async {
|
||||
await terminalHandler.processTerminalInput('w');
|
||||
await terminalHandler.processTerminalInput('W');
|
||||
|
Loading…
Reference in New Issue
Block a user