From 388dcd2478d511f5c5dececb94c654d3086c1944 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 13 Jan 2021 13:57:09 -0800 Subject: [PATCH] Revert "[flutter_tools] Serve DevTools at app start (#73366)" (#73896) This reverts commit 1cb0a24a466fb1d1cf8ad95b15c9857ab9817293. --- packages/flutter_tools/lib/executable.dart | 2 - .../lib/src/commands/attach.dart | 7 +- .../lib/src/commands/daemon.dart | 3 +- .../flutter_tools/lib/src/commands/run.dart | 2 - .../flutter_tools/lib/src/context_runner.dart | 2 - packages/flutter_tools/lib/src/device.dart | 3 - .../lib/src/devtools_launcher.dart | 138 ++++--------- .../lib/src/persistent_tool_state.dart | 14 -- .../lib/src/resident_runner.dart | 61 ++---- packages/flutter_tools/lib/src/run_cold.dart | 35 +--- packages/flutter_tools/lib/src/run_hot.dart | 34 +--- .../lib/src/runner/flutter_command.dart | 20 -- .../general.shard/devtools_launcher_test.dart | 100 +--------- .../persistent_tool_state_test.dart | 19 -- .../general.shard/resident_runner_test.dart | 184 +++--------------- .../runner/flutter_command_test.dart | 42 ---- .../general.shard/terminal_handler_test.dart | 7 + 17 files changed, 116 insertions(+), 557 deletions(-) diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 660c494662d..26e74d855e3 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -156,8 +156,6 @@ Future main(List 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( diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart index ddc877b4a80..d10a7000e21 100644 --- a/packages/flutter_tools/lib/src/commands/attach.dart +++ b/packages/flutter_tools/lib/src/commands/attach.dart @@ -101,7 +101,6 @@ class AttachCommand extends FlutterCommand { ); usesTrackWidgetCreation(verboseHelp: verboseHelp); addDdsOptions(verboseHelp: verboseHelp); - addDevToolsOptions(); usesDeviceTimeoutOption(); hotRunnerFactory ??= HotRunnerFactory(); } @@ -406,11 +405,7 @@ known, it can be explicitly provided to attach via the command-line, e.g. ); flutterDevice.observatoryUris = observatoryUris; final List flutterDevices = [flutterDevice]; - final DebuggingOptions debuggingOptions = DebuggingOptions.enabled( - buildInfo, - disableDds: boolArg('disable-dds'), - devToolsServerAddress: devToolsServerAddress, - ); + final DebuggingOptions debuggingOptions = DebuggingOptions.enabled(buildInfo, disableDds: boolArg('disable-dds')); return buildInfo.isDebug ? hotRunnerFactory.build( diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 16c457b2aee..a72e7763a41 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart @@ -871,7 +871,8 @@ class DevToolsDomain extends Domain { Future> serve([ Map args ]) async { _devtoolsLauncher ??= DevtoolsLauncher.instance; - final DevToolsServerAddress server = await _devtoolsLauncher.serve(); + final bool openInBrowser = args != null && (args['openInBrowser'] == 'true'); + final DevToolsServerAddress server = await _devtoolsLauncher.serve(openInBrowser: openInBrowser); return{ 'host': server?.host, 'port': server?.port, diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index e9cf68b40e4..7b2af9f3dcc 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -134,7 +134,6 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment usesDeviceUserOption(); usesDeviceTimeoutOption(); addDdsOptions(verboseHelp: verboseHelp); - addDevToolsOptions(); addAndroidSpecificBuildOptions(hide: !verboseHelp); } @@ -196,7 +195,6 @@ 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') : '', diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart index baad4222df0..02ca1a7f7fa 100644 --- a/packages/flutter_tools/lib/src/context_runner.dart +++ b/packages/flutter_tools/lib/src/context_runner.dart @@ -184,8 +184,6 @@ Future runInContext( 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, diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index cbbf9e5fee9..53c8861f5a8 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -852,7 +852,6 @@ class DebuggingOptions { this.disablePortPublication = false, this.deviceVmServicePort, this.ddsPort, - this.devToolsServerAddress, this.hostname, this.port, this.webEnableExposeUrl, @@ -896,7 +895,6 @@ class DebuggingOptions { disablePortPublication = false, deviceVmServicePort = null, ddsPort = null, - devToolsServerAddress = null, vmserviceOutFile = null, fastStart = false, webEnableExpressionEvaluation = false, @@ -926,7 +924,6 @@ class DebuggingOptions { final int deviceVmServicePort; final bool disablePortPublication; final int ddsPort; - final Uri devToolsServerAddress; final String port; final String hostname; final bool webEnableExposeUrl; diff --git a/packages/flutter_tools/lib/src/devtools_launcher.dart b/packages/flutter_tools/lib/src/devtools_launcher.dart index c4480181433..c553a997df5 100644 --- a/packages/flutter_tools/lib/src/devtools_launcher.dart +++ b/packages/flutter_tools/lib/src/devtools_launcher.dart @@ -4,15 +4,13 @@ import 'dart:async'; -import 'package:http/http.dart' as http; +import 'package:browser_launcher/browser_launcher.dart'; 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. @@ -21,68 +19,59 @@ 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, - _platform = platform, - _persistentToolState = persistentToolState; + _logger = logger; 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 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 { - 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; + Future launch(Uri vmServiceUri, {bool openInBrowser = false}) async { + if (_devToolsProcess != null && _devToolsUri != null) { + // DevTools is already running. + if (openInBrowser) { + await Chrome.start([_devToolsUri.toString()]); } + return; + } - 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. + final Status status = _logger.startProgress( + 'Activating Dart DevTools...', + ); + 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([ + _pubExecutable, + 'global', + 'activate', + 'devtools' + ]); + if (_devToolsActivateProcess.exitCode != 0) { + status.cancel(); + _logger.printError('Error running `pub global activate ' + 'devtools`:\n${_devToolsActivateProcess.stderr}'); 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([ _pubExecutable, 'global', 'run', 'devtools', - '--no-launch-browser', + if (!openInBrowser) '--no-launch-browser', if (vmServiceUri != null) '--vm-uri=$vmServiceUri', ]); final Completer completer = Completer(); @@ -102,83 +91,30 @@ 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 - .timeout(const Duration(seconds: 10)); + _devToolsUri = await completer.future; } on Exception catch (e, st) { + status.cancel(); _logger.printError('Failed to launch DevTools: $e', stackTrace: st); } } - Future _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([ - _pubExecutable, - 'global', - 'list', - ]); - - if (_pubGlobalListProcess.stdout.toString().contains('devtools ')) { - return true; - } - 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 _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([ - _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 serve() async { - await launch(null); - return activeDevToolsServer; + Future serve({bool openInBrowser = false}) async { + await launch(null, openInBrowser: openInBrowser); + if (_devToolsUri == null) { + return null; + } + return DevToolsServerAddress(_devToolsUri.host, _devToolsUri.port); } @override Future close() async { - devToolsUri = null; if (_devToolsProcess != null) { _devToolsProcess.kill(); await _devToolsProcess.exitCode; diff --git a/packages/flutter_tools/lib/src/persistent_tool_state.dart b/packages/flutter_tools/lib/src/persistent_tool_state.dart index f0bfbf39481..2fc16994e7a 100644 --- a/packages/flutter_tools/lib/src/persistent_tool_state.dart +++ b/packages/flutter_tools/lib/src/persistent_tool_state.dart @@ -52,9 +52,6 @@ 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 { @@ -88,7 +85,6 @@ 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; @@ -135,14 +131,4 @@ 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()); } diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 59243f68b20..c99b7d4c366 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -774,7 +774,7 @@ abstract class ResidentRunner { final CommandHelp commandHelp; final bool machine; - DevtoolsLauncher _devToolsLauncher; + DevtoolsLauncher _devtoolsLauncher; bool _exited = false; Completer _finished = Completer(); @@ -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 exit() async { _exited = true; - await shutdownDevTools(); + await shutdownDevtools(); await stopEchoingDeviceLog(); await preExit(); await exitApp(); @@ -949,7 +949,7 @@ abstract class ResidentRunner { } Future detach() async { - await shutdownDevTools(); + await shutdownDevtools(); await stopEchoingDeviceLog(); await preExit(); await shutdownDartDevelopmentService(); @@ -1250,29 +1250,22 @@ abstract class ResidentRunner { } } - DevToolsServerAddress activeDevToolsServer() { - _devToolsLauncher ??= DevtoolsLauncher.instance; - return _devToolsLauncher.activeDevToolsServer; - } - - Future serveDevToolsGracefully({ - Uri devToolsServerAddress - }) async { + Future launchDevTools({bool openInBrowser = false}) async { if (!supportsServiceProtocol) { - return; - } - - _devToolsLauncher ??= DevtoolsLauncher.instance; - if (devToolsServerAddress != null) { - _devToolsLauncher.devToolsUri = devToolsServerAddress; - } else { - await _devToolsLauncher.serve(); + return false; } + assert(supportsServiceProtocol); + _devtoolsLauncher ??= DevtoolsLauncher.instance; + unawaited(_devtoolsLauncher.launch( + flutterDevices.first.vmService.httpAddress, + openInBrowser: openInBrowser, + )); + return true; } - Future shutdownDevTools() async { - await _devToolsLauncher?.close(); - _devToolsLauncher = null; + Future shutdownDevtools() async { + await _devtoolsLauncher?.close(); + _devtoolsLauncher = null; } Future _serviceProtocolDone(dynamic object) async { @@ -1558,6 +1551,8 @@ class TerminalHandler { return residentRunner.debugDumpRenderTree(); case 'U': return residentRunner.debugDumpSemanticsTreeInInverseHitTestOrder(); + case 'v': + return residentRunner.launchDevTools(openInBrowser: true); case 'w': case 'W': return residentRunner.debugDumpApp(); @@ -1650,25 +1645,16 @@ 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 launch(Uri vmServiceUri); + Future launch(Uri vmServiceUri, {bool openInBrowser = false}); /// Serve Dart DevTools and return the host and port they are available on. - Future serve(); + Future serve({bool openInBrowser = false}); Future close(); static DevtoolsLauncher get instance => context.get(); - - DevToolsServerAddress get activeDevToolsServer { - if (devToolsUri == null) { - return null; - } - return DevToolsServerAddress(devToolsUri.host, devToolsUri.port); - } } class DevToolsServerAddress { @@ -1676,11 +1662,4 @@ 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); - } } diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart index 8410f8ede2b..6ce44a13c56 100644 --- a/packages/flutter_tools/lib/src/run_cold.dart +++ b/packages/flutter_tools/lib/src/run_cold.dart @@ -72,12 +72,7 @@ class ColdRunner extends ResidentRunner { // Connect to observatory. if (debuggingOptions.debuggingEnabled) { try { - await Future.wait(>[ - connectToServiceProtocol(), - serveDevToolsGracefully( - devToolsServerAddress: debuggingOptions.devToolsServerAddress, - ), - ]); + await connectToServiceProtocol(); } on String catch (message) { globals.printError(message); appFailedToStart(); @@ -120,7 +115,7 @@ class ColdRunner extends ResidentRunner { appStartedCompleter?.complete(); - writeVmServiceFile(); + writeVmserviceFile(); if (stayResident && !traceStartup) { return waitForAppToFinish(); @@ -137,15 +132,10 @@ class ColdRunner extends ResidentRunner { }) async { _didAttach = true; try { - await Future.wait(>[ - connectToServiceProtocol( - getSkSLMethod: writeSkSL, - allowExistingDdsInstance: allowExistingDdsInstance, - ), - serveDevToolsGracefully( - devToolsServerAddress: debuggingOptions.devToolsServerAddress, - ), - ]); + await connectToServiceProtocol( + getSkSLMethod: writeSkSL, + allowExistingDdsInstance: allowExistingDdsInstance, + ); } on Exception catch (error) { globals.printError('Error connecting to the service protocol: $error'); return 2; @@ -205,19 +195,6 @@ 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: {'uri': '${device.vmService.httpAddress}'}, - ); - if (uri != null) { - globals.printStatus( - '\nFlutter DevTools, a Flutter debugger and profiler, on ' - '${device.device.name} is available at: $uri', - ); - } - } } } } diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index c8ec0de38fe..443a7c2c31a 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -174,18 +174,13 @@ class HotRunner extends ResidentRunner { }) async { _didAttach = true; try { - await Future.wait(>[ - connectToServiceProtocol( - reloadSources: _reloadSourcesService, - restart: _restartService, - compileExpression: _compileExpressionService, - getSkSLMethod: writeSkSL, - allowExistingDdsInstance: allowExistingDdsInstance, - ), - serveDevToolsGracefully( - devToolsServerAddress: debuggingOptions.devToolsServerAddress, - ), - ]); + await connectToServiceProtocol( + reloadSources: _reloadSourcesService, + restart: _restartService, + compileExpression: _compileExpressionService, + getSkSLMethod: writeSkSL, + allowExistingDdsInstance: allowExistingDdsInstance, + ); // Catches all exceptions, non-Exception objects are rethrown. } catch (error) { // ignore: avoid_catches_without_on_clauses if (error is! Exception && error is! String) { @@ -285,7 +280,7 @@ class HotRunner extends ResidentRunner { benchmarkOutput.writeAsStringSync(toPrettyJson(benchmarkData)); return 0; } - writeVmServiceFile(); + writeVmserviceFile(); int result = 0; if (stayResident) { @@ -1092,19 +1087,6 @@ 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: {'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) { diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index b9adae8710c..bf4247ae405 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -128,9 +128,6 @@ abstract class FlutterCommand extends Command { /// 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'; @@ -325,13 +322,6 @@ abstract class FlutterCommand extends Command { _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 ' @@ -375,16 +365,6 @@ abstract class FlutterCommand extends Command { 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. /// diff --git a/packages/flutter_tools/test/general.shard/devtools_launcher_test.dart b/packages/flutter_tools/test/general.shard/devtools_launcher_test.dart index 43ccb8a48c8..c7cf5704976 100644 --- a/packages/flutter_tools/test/general.shard/devtools_launcher_test.dart +++ b/packages/flutter_tools/test/general.shard/devtools_launcher_test.dart @@ -4,41 +4,20 @@ 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: {}); - - 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 completer = Completer(); final DevtoolsLauncher launcher = DevtoolsServerLauncher( pubExecutable: 'pub', - logger: logger, - platform: platform, - persistentToolState: persistentToolState, + logger: BufferLogger.test(), processManager: FakeProcessManager.list([ const FakeCommand( command: [ @@ -49,14 +28,6 @@ void main() { ], stdout: 'Activated DevTools 0.9.5', ), - const FakeCommand( - command: [ - 'pub', - 'global', - 'list', - ], - stdout: 'devtools 0.9.6', - ), FakeCommand( command: const [ 'pub', @@ -80,9 +51,7 @@ void main() { final Completer completer = Completer(); final DevtoolsLauncher launcher = DevtoolsServerLauncher( pubExecutable: 'pub', - logger: logger, - platform: platform, - persistentToolState: persistentToolState, + logger: BufferLogger.test(), processManager: FakeProcessManager.list([ const FakeCommand( command: [ @@ -93,21 +62,12 @@ void main() { ], stdout: 'Activated DevTools 0.9.5', ), - const FakeCommand( - command: [ - 'pub', - 'global', - 'list', - ], - stdout: 'devtools 0.9.6', - ), FakeCommand( command: const [ 'pub', 'global', 'run', 'devtools', - '--no-launch-browser', ], stdout: 'Serving DevTools at http://127.0.0.1:9100\n', completer: completer, @@ -115,49 +75,16 @@ void main() { ]), ); - final DevToolsServerAddress address = await launcher.serve(); + final DevToolsServerAddress address = await launcher.serve(openInBrowser: true); expect(address.host, '127.0.0.1'); expect(address.port, 9100); }); - 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([ - const FakeCommand( - command: [ - 'pub', - 'global', - 'list', - ], - stdout: 'devtools 0.9.6', - ), - const FakeCommand( - command: [ - '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 BufferLogger logger = BufferLogger.test(); final DevtoolsLauncher launcher = DevtoolsServerLauncher( pubExecutable: 'pub', logger: logger, - platform: platform, - persistentToolState: persistentToolState, processManager: FakeProcessManager.list([ const FakeCommand( command: [ @@ -169,14 +96,6 @@ void main() { stderr: 'Error - could not activate devtools', exitCode: 1, ), - const FakeCommand( - command: [ - 'pub', - 'global', - 'list', - ], - stdout: 'devtools 0.9.6', - ), FakeCommand( command: const [ 'pub', @@ -199,11 +118,10 @@ 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([ const FakeCommand( command: [ @@ -214,14 +132,6 @@ void main() { ], stdout: 'Activated DevTools 0.9.5', ), - const FakeCommand( - command: [ - 'pub', - 'global', - 'list', - ], - stdout: 'devtools 0.9.6', - ), FakeCommand( command: const [ 'pub', diff --git a/packages/flutter_tools/test/general.shard/persistent_tool_state_test.dart b/packages/flutter_tools/test/general.shard/persistent_tool_state_test.dart index 94b32d36b0a..2823c515a75 100644 --- a/packages/flutter_tools/test/general.shard/persistent_tool_state_test.dart +++ b/packages/flutter_tools/test/general.shard/persistent_tool_state_test.dart @@ -57,23 +57,4 @@ 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)); - }); } diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart index 91d4c585b65..bc1ac3574b6 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart @@ -229,9 +229,7 @@ void main() { expect((await connectionInfo).baseUri, 'foo://bar'); expect(onAppStart.isCompleted, true); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner suppresses errors for the initial compilation', () => testbed.run(() async { globals.fs.file(globals.fs.path.join('lib', 'main.dart')) @@ -276,9 +274,7 @@ void main() { suppressErrors: true, )).called(1); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); // Regression test for https://github.com/flutter/flutter/issues/60613 testUsingContext('ResidentRunner calls appFailedToStart if initial compilation fails', () => testbed.run(() async { @@ -410,9 +406,7 @@ void main() { suppressErrors: false, )).called(1); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner can attach to device successfully with --fast-start', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -492,9 +486,7 @@ void main() { expect((await connectionInfo).baseUri, 'foo://bar'); expect(onAppStart.isCompleted, true); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner can handle an RPC exception from hot reload', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -547,9 +539,7 @@ void main() { expect(fakeVmServiceHost.hasRemainingExpectations, false); }, overrides: { Usage: () => MockUsage(), - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner fails its operation if the device initialization is not complete', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -634,9 +624,7 @@ void main() { expect(fakeVmServiceHost.hasRemainingExpectations, false); }, overrides: { Usage: () => MockUsage(), - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner reports hot reload event with null safety analytics', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -700,7 +688,6 @@ void main() { })).called(1); expect(fakeVmServiceHost.hasRemainingExpectations, false); }, overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, Usage: () => MockUsage(), })); @@ -769,9 +756,7 @@ void main() { expect(result.code, 0); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner reports error with missing entrypoint file', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -855,9 +840,7 @@ void main() { expect(testLogger.errorText, contains('The entrypoint file (i.e. the file with main())')); expect(result.fatal, false); expect(result.code, 0); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner resets compilation time on reload reject', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -945,9 +928,7 @@ 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: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner can send target platform to analytics from hot reload', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -1019,9 +1000,7 @@ void main() { ); }, overrides: { Usage: () => MockUsage(), - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner can perform fast reassemble', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -1135,9 +1114,7 @@ void main() { ProjectFileInvalidator: () => FakeProjectFileInvalidator(), Usage: () => MockUsage(), FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true), - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -1207,9 +1184,7 @@ void main() { expect(fakeVmServiceHost.hasRemainingExpectations, false); }, overrides: { Usage: () => MockUsage(), - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner can remove breakpoints from paused isolate during hot restart', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -1285,9 +1260,7 @@ void main() { expect(result.isOk, true); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner will alternative the name of the dill file uploaded for a hot restart', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -1419,9 +1392,7 @@ void main() { await residentRunner.restart(fullRestart: true); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner Can handle an RPC exception from hot restart', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -1474,9 +1445,7 @@ void main() { expect(fakeVmServiceHost.hasRemainingExpectations, false); }, overrides: { Usage: () => MockUsage(), - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ResidentRunner uses temp directory when there is no output dill path', () => testbed.run(() { fakeVmServiceHost = FakeVmServiceHost(requests: []); @@ -1681,88 +1650,13 @@ void main() { ) })); - testUsingContext('ResidentRunner invokes DevToolsLauncher when attaching and shutting down DevTools', () => testbed.run(() async { - fakeVmServiceHost = FakeVmServiceHost(requests: [ - listViews, - listViews, - setAssetBundlePath, - ]); - final Future result = residentRunner.attach(); - expect(await result, 0); + 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); - // Verify DevTools was served. - verify(mockDevtoolsLauncher.serve()).called(1); - - // Shutdown - await residentRunner.shutdownDevTools(); - verify(mockDevtoolsLauncher.close()).called(1); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); - - testUsingContext('ResidentRunner invokes DevtoolsLauncher when attaching and shutting down - cold mode', () => testbed.run(() async { - fakeVmServiceHost = FakeVmServiceHost(requests: [ - listViews, - listViews, - setAssetBundlePath, - ]); - residentRunner = ColdRunner( - [ - 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 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: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); - - testUsingContext('ResidentRunner invokes DevtoolsLauncher when running and shutting down - cold mode', () => testbed.run(() async { - fakeVmServiceHost = FakeVmServiceHost(requests: [ - listViews, - listViews, - setAssetBundlePath, - ]); - residentRunner = ColdRunner( - [ - 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 result = residentRunner.run(); - expect(await result, 0); - - // Verify DevTools was served. - verify(mockDevtoolsLauncher.serve()).called(1); - - // Shutdown - await residentRunner.shutdownDevTools(); + await residentRunner.shutdownDevtools(); verify(mockDevtoolsLauncher.close()).called(1); }), overrides: { DevtoolsLauncher: () => mockDevtoolsLauncher, @@ -2405,9 +2299,7 @@ void main() { await residentRunner.run(); expect(await globals.fs.file('foo').readAsString(), testUri.toString()); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('HotRunner copies compiled app.dill to cache during startup', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -2435,9 +2327,7 @@ void main() { await residentRunner.run(); expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill')).readAsString(), 'ABC'); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('HotRunner copies compiled app.dill to cache during startup with dart defines', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -2473,9 +2363,7 @@ void main() { expect(await globals.fs.file(globals.fs.path.join( 'build', '187ef4436122d1cc2f40dc2b92f0eba0.cache.dill')).readAsString(), 'ABC'); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('HotRunner copies compiled app.dill to cache during startup with null safety', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -2511,9 +2399,7 @@ void main() { expect(await globals.fs.file(globals.fs.path.join( 'build', '3416d3007730479552122f01c01e326d.cache.dill')).readAsString(), 'ABC'); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('HotRunner does not copy app.dill if a dillOutputPath is given', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -2542,9 +2428,7 @@ void main() { await residentRunner.run(); expect(globals.fs.file(globals.fs.path.join('build', 'cache.dill')), isNot(exists)); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('HotRunner copies compiled app.dill to cache during startup with --track-widget-creation', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -2577,9 +2461,7 @@ void main() { await residentRunner.run(); expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill.track.dill')).readAsString(), 'ABC'); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('HotRunner unforwards device ports', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -2612,9 +2494,7 @@ void main() { await residentRunner.run(); verify(mockPortForwarder.dispose()).called(1); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('HotRunner handles failure to write vmservice file', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ @@ -2643,9 +2523,7 @@ void main() { expect(fakeVmServiceHost.hasRemainingExpectations, false); }, overrides: { FileSystem: () => ThrowingForwardingFileSystem(MemoryFileSystem.test()), - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('ColdRunner writes vm service file when providing debugging option', () => testbed.run(() async { @@ -2672,9 +2550,7 @@ void main() { expect(await globals.fs.file('foo').readAsString(), testUri.toString()); expect(fakeVmServiceHost.hasRemainingExpectations, false); - }), overrides: { - DevtoolsLauncher: () => mockDevtoolsLauncher, - }); + })); testUsingContext('FlutterDevice uses dartdevc configuration when targeting web', () async { fakeVmServiceHost = FakeVmServiceHost(requests: []); diff --git a/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart b/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart index 9033b580f6d..e5f46f70e43 100644 --- a/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart +++ b/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart @@ -290,48 +290,6 @@ void main() { expect(FlutterCommandResult.warning().exitStatus, ExitStatus.warning); }); - testUsingContext('devToolsServerAddress returns parsed uri', () async { - final DummyFlutterCommand command = DummyFlutterCommand()..addDevToolsOptions(); - await createTestCommandRunner(command).run([ - '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 runner = createTestCommandRunner(command); - await runner.run([ - 'dummy', - '--${FlutterCommand.kDevToolsServerAddress}', - 'hello-world', - ]); - expect(command.devToolsServerAddress, isNull); - - await runner.run([ - 'dummy', - '--${FlutterCommand.kDevToolsServerAddress}', - '', - ]); - expect(command.devToolsServerAddress, isNull); - - await runner.run([ - 'dummy', - '--${FlutterCommand.kDevToolsServerAddress}', - '9101', - ]); - expect(command.devToolsServerAddress, isNull); - - await runner.run([ - 'dummy', - '--${FlutterCommand.kDevToolsServerAddress}', - '127.0.0.1:9101', - ]); - expect(command.devToolsServerAddress, isNull); - }); - group('signals tests', () { MockIoProcessSignal mockSignal; ProcessSignal signalUnderTest; diff --git a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart index 5c0eea2ae90..7ec82d1011a 100644 --- a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart +++ b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart @@ -285,6 +285,13 @@ 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');