diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index 40a291ae0b33..51ae79a34820 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart @@ -59,7 +59,7 @@ class AndroidDevice extends Device { this.productID, required this.modelID, this.deviceCodeName, - required super.logger, + required Logger logger, required ProcessManager processManager, required Platform platform, required AndroidSdk androidSdk, diff --git a/packages/flutter_tools/lib/src/base/dds.dart b/packages/flutter_tools/lib/src/base/dds.dart index f1be2faf10bf..eba8d3875c99 100644 --- a/packages/flutter_tools/lib/src/base/dds.dart +++ b/packages/flutter_tools/lib/src/base/dds.dart @@ -4,333 +4,112 @@ import 'dart:async'; +import 'package:dds/dds.dart' as dds; import 'package:meta/meta.dart'; -import '../artifacts.dart'; -import '../convert.dart'; -import '../device.dart'; -import '../globals.dart' as globals; +import 'common.dart'; +import 'context.dart'; import 'io.dart' as io; import 'logger.dart'; -/// A representation of the current DDS state including: -/// -/// - The process the external DDS instance is running in -/// - The service URI DDS is being served on -/// - The URI DevTools is being served on, if applicable -/// - The URI DTD is being served on, if applicable -typedef DartDevelopmentServiceInstance = ({ - io.Process? process, - Uri? serviceUri, - Uri? devToolsUri, - Uri? dtdUri, -}); - -/// The default DDSLauncherCallback used to spawn DDS. -Future defaultStartDartDevelopmentService( - Uri remoteVmServiceUri, { - required bool enableAuthCodes, - required bool ipv6, - required bool enableDevTools, - required List cachedUserTags, - Uri? serviceUri, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, -}) async { - final String exe = globals.artifacts!.getArtifactPath( - Artifact.engineDartBinary, - ); - final io.Process process = await io.Process.start( - exe, - [ - 'development-service', - '--vm-service-uri=$remoteVmServiceUri', - if (serviceUri != null) ...[ - '--bind-address=${serviceUri.host}', - '--bind-port=${serviceUri.port}', - ], - if (!enableAuthCodes) '--disable-service-auth-codes', - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // if (enableDevTools) '--serve-devtools', - if (google3WorkspaceRoot != null) - '--google3-workspace-root=$google3WorkspaceRoot', - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // if (devToolsServerAddress != null) - // '--devtools-server-address=$devToolsServerAddress', - for (final String tag in cachedUserTags) '--cached-user-tags=$tag', - ], - ); - final Completer completer = - Completer(); - late StreamSubscription stderrSub; - stderrSub = process.stderr - .transform(utf8.decoder) - .transform(json.decoder) - .listen((Object? result) { - if (result - case { - 'state': 'started', - 'ddsUri': final String ddsUriStr, - }) { - final Uri ddsUri = Uri.parse(ddsUriStr); - final String? devToolsUriStr = result['devToolsUri'] as String?; - final Uri? devToolsUri = - devToolsUriStr == null ? null : Uri.parse(devToolsUriStr); - final String? dtdUriStr = - (result['dtd'] as Map?)?['uri'] as String?; - final Uri? dtdUri = dtdUriStr == null ? null : Uri.parse(dtdUriStr); - - completer.complete(( - process: process, - serviceUri: ddsUri, - devToolsUri: devToolsUri, - dtdUri: dtdUri, - )); - } else if (result - case { - 'state': 'error', - 'error': final String error, - }) { - final Map? exceptionDetails = - result['ddsExceptionDetails'] as Map?; - completer.completeError( - exceptionDetails != null - ? DartDevelopmentServiceException.fromJson(exceptionDetails) - : StateError(error), - ); - } else { - throw StateError('Unexpected result from DDS: $result'); - } - stderrSub.cancel(); - }); - return completer.future; -} - -typedef DDSLauncherCallback = Future Function( - Uri remoteVmServiceUri, { - required bool enableAuthCodes, - required bool ipv6, - required bool enableDevTools, - required List cachedUserTags, - Uri? serviceUri, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, -}); - // TODO(fujino): This should be direct injected, rather than mutable global state. -/// Used by tests to override the DDS spawn behavior for mocking purposes. @visibleForTesting -DDSLauncherCallback ddsLauncherCallback = defaultStartDartDevelopmentService; - -/// Thrown by DDS during initialization failures, unexpected connection issues, -/// and when attempting to spawn DDS when an existing DDS instance exists. -class DartDevelopmentServiceException implements Exception { - factory DartDevelopmentServiceException.fromJson(Map json) { - if (json - case { - 'error_code': final int errorCode, - 'message': final String message, - 'uri': final String? uri - }) { - return switch (errorCode) { - existingDdsInstanceError => - DartDevelopmentServiceException.existingDdsInstance( - message, - ddsUri: Uri.parse(uri!), - ), - failedToStartError => DartDevelopmentServiceException.failedToStart(), - connectionError => - DartDevelopmentServiceException.connectionIssue(message), - _ => throw StateError( - 'Invalid DartDevelopmentServiceException error_code: $errorCode', - ), - }; - } - throw StateError('Invalid DartDevelopmentServiceException JSON: $json'); - } - - /// Thrown when `DartDeveloperService.startDartDevelopmentService` is called - /// and the target VM service already has a Dart Developer Service instance - /// connected. - factory DartDevelopmentServiceException.existingDdsInstance( - String message, { - Uri? ddsUri, - }) { - return ExistingDartDevelopmentServiceException._( - message, - ddsUri: ddsUri, - ); - } - - /// Thrown when the connection to the remote VM service terminates unexpectedly - /// during Dart Development Service startup. - factory DartDevelopmentServiceException.failedToStart() { - return DartDevelopmentServiceException._( - failedToStartError, - 'Failed to start Dart Development Service', - ); - } - - /// Thrown when a connection error has occurred after startup. - factory DartDevelopmentServiceException.connectionIssue(String message) { - return DartDevelopmentServiceException._(connectionError, message); - } - - DartDevelopmentServiceException._(this.errorCode, this.message); - - /// Set when `DartDeveloperService.startDartDevelopmentService` is called and - /// the target VM service already has a Dart Developer Service instance - /// connected. - static const int existingDdsInstanceError = 1; - - /// Set when the connection to the remote VM service terminates unexpectedly - /// during Dart Development Service startup. - static const int failedToStartError = 2; - - /// Set when a connection error has occurred after startup. - static const int connectionError = 3; - - @override - String toString() => 'DartDevelopmentServiceException: $message'; - - final int errorCode; - final String message; -} - -/// Thrown when attempting to start a new DDS instance when one already exists. -class ExistingDartDevelopmentServiceException - extends DartDevelopmentServiceException { - ExistingDartDevelopmentServiceException._( - String message, { - this.ddsUri, - }) : super._( - DartDevelopmentServiceException.existingDdsInstanceError, - message, - ); - - /// The URI of the existing DDS instance, if available. - /// - /// This URI is the base HTTP URI such as `http://127.0.0.1:1234/AbcDefg=/`, - /// not the WebSocket URI (which can be obtained by mapping the scheme to - /// `ws` (or `wss`) and appending `ws` to the path segments). - final Uri? ddsUri; -} +Future Function( + Uri remoteVmServiceUri, { + bool enableAuthCodes, + bool ipv6, + Uri? serviceUri, + List cachedUserTags, + dds.UriConverter? uriConverter, +}) ddsLauncherCallback = dds.DartDevelopmentService.startDartDevelopmentService; /// Helper class to launch a [dds.DartDevelopmentService]. Allows for us to /// mock out this functionality for testing purposes. -class DartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin { - DartDevelopmentService({required Logger logger}) : _logger = logger; - - DartDevelopmentServiceInstance? _ddsInstance; +class DartDevelopmentService { + dds.DartDevelopmentService? _ddsInstance; - Uri? get uri => _ddsInstance?.serviceUri ?? _existingDdsUri; + Uri? get uri => _ddsInstance?.uri ?? _existingDdsUri; Uri? _existingDdsUri; Future get done => _completer.future; final Completer _completer = Completer(); - final Logger _logger; - - @override Future startDartDevelopmentService( Uri vmServiceUri, { - int? ddsPort, - bool? disableServiceAuthCodes, + required Logger logger, + int? hostPort, bool? ipv6, - bool enableDevTools = true, + bool? disableServiceAuthCodes, bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async { - assert(_ddsInstance == null); final Uri ddsUri = Uri( scheme: 'http', - host: ((ipv6 ?? false) - ? io.InternetAddress.loopbackIPv6 - : io.InternetAddress.loopbackIPv4) - .host, - port: ddsPort ?? 0, + host: ((ipv6 ?? false) ? io.InternetAddress.loopbackIPv6 : io.InternetAddress.loopbackIPv4).host, + port: hostPort ?? 0, ); - _logger.printTrace( + logger.printTrace( 'Launching a Dart Developer Service (DDS) instance at $ddsUri, ' 'connecting to VM service at $vmServiceUri.', ); - void completeFuture() { - if (!_completer.isCompleted) { - _completer.complete(); - } - } - try { _ddsInstance = await ddsLauncherCallback( - vmServiceUri, - serviceUri: ddsUri, - enableAuthCodes: disableServiceAuthCodes != true, - ipv6: ipv6 ?? false, - enableDevTools: enableDevTools, - // Enables caching of CPU samples collected during application startup. - cachedUserTags: cacheStartupProfile - ? const ['AppStartUp'] - : const [], - google3WorkspaceRoot: google3WorkspaceRoot, - devToolsServerAddress: devToolsServerAddress, - ); - final io.Process? process = _ddsInstance?.process; - - // Complete the future if the DDS process is null, which happens in - // testing. - if (process != null) { - unawaited(process.exitCode.whenComplete(completeFuture)); - } - } on DartDevelopmentServiceException catch (e) { - _logger.printTrace('Warning: Failed to start DDS: ${e.message}'); - if (e is ExistingDartDevelopmentServiceException) { - _existingDdsUri = e.ddsUri; - } else { - _logger.printError( + vmServiceUri, + serviceUri: ddsUri, + enableAuthCodes: disableServiceAuthCodes != true, + ipv6: ipv6 ?? false, + // Enables caching of CPU samples collected during application startup. + cachedUserTags: cacheStartupProfile ? const ['AppStartUp'] : const [], + uriConverter: context.get(), + ); + unawaited(_ddsInstance?.done.whenComplete(() { + if (!_completer.isCompleted) { + _completer.complete(); + } + })); + logger.printTrace('DDS is listening at ${_ddsInstance?.uri}.'); + } on dds.DartDevelopmentServiceException catch (e) { + logger.printTrace('Warning: Failed to start DDS: ${e.message}'); + if (e.errorCode == dds.DartDevelopmentServiceException.existingDdsInstanceError) { + try { + // First try to use the new field to avoid parsing from the message. + _existingDdsUri = e is dds.ExistingDartDevelopmentServiceException ? e.ddsUri : null; + + // Otherwise, fall back to parsing from the exception (old DDS). + // This is not completely reliable which is why the new field above + // was added. + if (_existingDdsUri == null) { + String parsedUrl = e.message.split(' ').firstWhere((String e) => e.startsWith('http')); + // Trim trailing full stops from the message. + // https://github.com/flutter/flutter/issues/118609. + if (parsedUrl.endsWith('.')) { + parsedUrl = parsedUrl.substring(0, parsedUrl.length - 1); + } + _existingDdsUri ??= Uri.parse(parsedUrl); + } + } on StateError { + if (e.message.contains('Existing VM service clients prevent DDS from taking control.')) { + throwToolExit('${e.message}. Please rebuild your application with a newer version of Flutter.'); + } + logger.printError( 'DDS has failed to start and there is not an existing DDS instance ' 'available to connect to. Please file an issue at https://github.com/flutter/flutter/issues ' - 'with the following error message:\n\n ${e.message}.'); - // DDS was unable to start for an unknown reason. Raise a StateError - // so it can be reported by the crash reporter. - throw StateError(e.message); + 'with the following error message:\n\n ${e.message}.' + ); + // DDS was unable to start for an unknown reason. Raise a StateError + // so it can be reported by the crash reporter. + throw StateError(e.message); + } + } + if (!_completer.isCompleted) { + _completer.complete(); } - completeFuture(); rethrow; } } - void shutdown() => _ddsInstance?.process?.kill(); -} - -/// Contains common functionality that can be used with any implementation of -/// [DartDevelopmentService]. -mixin DartDevelopmentServiceLocalOperationsMixin { - Future startDartDevelopmentService( - Uri vmServiceUri, { - int? ddsPort, - bool? disableServiceAuthCodes, - bool? ipv6, - bool enableDevTools = true, - bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, - }); + Future shutdown() async => _ddsInstance?.shutdown(); - /// A convenience method used to create a [DartDevelopmentService] instance - /// from a [DebuggingOptions] instance. - Future startDartDevelopmentServiceFromDebuggingOptions( - Uri vmServiceUri, { - required DebuggingOptions debuggingOptions, - }) => - startDartDevelopmentService( - vmServiceUri, - ddsPort: debuggingOptions.ddsPort, - disableServiceAuthCodes: debuggingOptions.disableServiceAuthCodes, - ipv6: debuggingOptions.ipv6, - enableDevTools: debuggingOptions.enableDevTools, - cacheStartupProfile: debuggingOptions.cacheStartupProfile, - google3WorkspaceRoot: debuggingOptions.google3WorkspaceRoot, - devToolsServerAddress: debuggingOptions.devToolsServerAddress, - ); + void setExternalDevToolsUri(Uri uri) { + _ddsInstance?.setExternalDevToolsUri(uri); + } } diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart index 1fac03a7fd37..404b116c9d58 100644 --- a/packages/flutter_tools/lib/src/commands/attach.dart +++ b/packages/flutter_tools/lib/src/commands/attach.dart @@ -361,6 +361,7 @@ known, it can be explicitly provided to attach via the command-line, e.g. connectionInfoCompleter: connectionInfoCompleter, appStartedCompleter: appStartedCompleter, allowExistingDdsInstance: true, + enableDevTools: boolArg(FlutterCommand.kEnableDevTools), ); }, device, @@ -402,6 +403,7 @@ known, it can be explicitly provided to attach via the command-line, e.g. result = await runner.attach( appStartedCompleter: onAppStart, allowExistingDdsInstance: true, + enableDevTools: boolArg(FlutterCommand.kEnableDevTools), ); if (result != 0) { throwToolExit(null, exitCode: result); @@ -460,9 +462,6 @@ known, it can be explicitly provided to attach via the command-line, e.g. serveObservatory: serveObservatory, usingCISystem: usingCISystem, debugLogsDirectoryPath: debugLogsDirectoryPath, - enableDevTools: boolArg(FlutterCommand.kEnableDevTools), - ipv6: usesIpv6, - printDtd: boolArg(FlutterGlobalOptions.kPrintDtd, global: true), ); return buildInfo.isDebug @@ -473,6 +472,7 @@ known, it can be explicitly provided to attach via the command-line, e.g. packagesFilePath: globalResults![FlutterGlobalOptions.kPackagesOption] as String?, projectRootPath: stringArg('project-root'), dillOutputPath: stringArg('output-dill'), + ipv6: usesIpv6, flutterProject: flutterProject, nativeAssetsYamlFile: stringArg(FlutterOptions.kNativeAssetsYamlFile), nativeAssetsBuilder: _nativeAssetsBuilder, @@ -482,6 +482,7 @@ known, it can be explicitly provided to attach via the command-line, e.g. flutterDevices, target: targetFile, debuggingOptions: debuggingOptions, + ipv6: usesIpv6, ); } @@ -505,6 +506,7 @@ class HotRunnerFactory { String? packagesFilePath, String? dillOutputPath, bool stayResident = true, + bool ipv6 = false, FlutterProject? flutterProject, String? nativeAssetsYamlFile, required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder, @@ -519,6 +521,7 @@ class HotRunnerFactory { projectRootPath: projectRootPath, dillOutputPath: dillOutputPath, stayResident: stayResident, + ipv6: ipv6, nativeAssetsYamlFile: nativeAssetsYamlFile, nativeAssetsBuilder: nativeAssetsBuilder, analytics: analytics, diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 48b1c1dba87c..4f1991aa9737 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart @@ -664,9 +664,11 @@ class AppDomain extends Domain { String? projectRootPath, String? packagesFilePath, String? dillOutputPath, + bool ipv6 = false, String? isolateFilter, bool machine = true, String? userIdentifier, + bool enableDevTools = true, required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder, }) async { if (!await device.supportsRuntimeMode(options.buildInfo.mode)) { @@ -697,6 +699,7 @@ class AppDomain extends Domain { flutterProject: flutterProject, target: target, debuggingOptions: options, + ipv6: ipv6, stayResident: true, urlTunneller: options.webEnableExposeUrl! ? daemon.daemonDomain.exposeUrl : null, machine: machine, @@ -714,6 +717,7 @@ class AppDomain extends Domain { applicationBinary: applicationBinary, projectRootPath: projectRootPath, dillOutputPath: dillOutputPath, + ipv6: ipv6, hostIsIde: true, machine: machine, analytics: globals.analytics, @@ -725,6 +729,7 @@ class AppDomain extends Domain { target: target, debuggingOptions: options, applicationBinary: applicationBinary, + ipv6: ipv6, machine: machine, ); } @@ -738,6 +743,7 @@ class AppDomain extends Domain { return runner.run( connectionInfoCompleter: connectionInfoCompleter, appStartedCompleter: appStartedCompleter, + enableDevTools: enableDevTools, route: route, ); }, @@ -1002,6 +1008,7 @@ class DeviceDomain extends Domain { registerHandler('takeScreenshot', takeScreenshot); registerHandler('startDartDevelopmentService', startDartDevelopmentService); registerHandler('shutdownDartDevelopmentService', shutdownDartDevelopmentService); + registerHandler('setExternalDevToolsUriForDartDevelopmentService', setExternalDevToolsUriForDartDevelopmentService); registerHandler('getDiagnostics', getDiagnostics); registerHandler('startVMServiceDiscoveryForAttach', startVMServiceDiscoveryForAttach); registerHandler('stopVMServiceDiscoveryForAttach', stopVMServiceDiscoveryForAttach); @@ -1189,6 +1196,7 @@ class DeviceDomain extends Domain { route: _getStringArg(args, 'route'), platformArgs: castStringKeyedMap(args['platformArgs']) ?? const {}, prebuiltApplication: _getBoolArg(args, 'prebuiltApplication') ?? false, + ipv6: _getBoolArg(args, 'ipv6') ?? false, userIdentifier: _getStringArg(args, 'userIdentifier'), ); return { @@ -1236,36 +1244,23 @@ class DeviceDomain extends Domain { } /// Starts DDS for the device. - Future> startDartDevelopmentService(Map args) async { + Future startDartDevelopmentService(Map args) async { final String? deviceId = _getStringArg(args, 'deviceId', required: true); final bool? disableServiceAuthCodes = _getBoolArg(args, 'disableServiceAuthCodes'); final String vmServiceUriStr = _getStringArg(args, 'vmServiceUri', required: true)!; - final bool enableDevTools = _getBoolArg(args, 'enableDevTools') ?? false; - final String? devToolsServerAddressStr = _getStringArg(args, 'devToolsServerAddress'); final Device? device = await daemon.deviceDomain._getDevice(deviceId); if (device == null) { throw DaemonException("device '$deviceId' not found"); } - Uri? devToolsServerAddress; - if (devToolsServerAddressStr != null) { - devToolsServerAddress = Uri.parse(devToolsServerAddressStr); - } - await device.dds.startDartDevelopmentService( Uri.parse(vmServiceUriStr), + logger: globals.logger, disableServiceAuthCodes: disableServiceAuthCodes, - enableDevTools: enableDevTools, - devToolsServerAddress: devToolsServerAddress, ); unawaited(device.dds.done.whenComplete(() => sendEvent('device.dds.done.$deviceId'))); - return { - 'ddsUri': device.dds.uri?.toString(), - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // 'devToolsUri': device.dds.devToolsUri?.toString(), - // 'dtdUri': device.dds.dtdUri?.toString(), - }; + return device.dds.uri?.toString(); } /// Starts DDS for the device. @@ -1277,7 +1272,19 @@ class DeviceDomain extends Domain { throw DaemonException("device '$deviceId' not found"); } - device.dds.shutdown(); + await device.dds.shutdown(); + } + + Future setExternalDevToolsUriForDartDevelopmentService(Map args) async { + final String? deviceId = _getStringArg(args, 'deviceId', required: true); + final String uri = _getStringArg(args, 'uri', required: true)!; + + final Device? device = await daemon.deviceDomain._getDevice(deviceId); + if (device == null) { + throw DaemonException("device '$deviceId' not found"); + } + + device.dds.setExternalDevToolsUri(Uri.parse(uri)); } @override diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart index 4365d31ba22f..be6b19c74a27 100644 --- a/packages/flutter_tools/lib/src/commands/drive.dart +++ b/packages/flutter_tools/lib/src/commands/drive.dart @@ -274,6 +274,7 @@ class DriveCommand extends RunCommandBase { buildInfo, device, debuggingOptions, + ipv6 ?? false, applicationBinary: applicationBinary, route: route, userIdentifier: userIdentifier, @@ -294,6 +295,7 @@ class DriveCommand extends RunCommandBase { uri, device, debuggingOptions, + ipv6 ?? false, ); } diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index c8920f2a8c9b..c46524bad512 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -354,9 +354,6 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment enableEmbedderApi: enableEmbedderApi, usingCISystem: usingCISystem, debugLogsDirectoryPath: debugLogsDirectoryPath, - enableDevTools: boolArg(FlutterCommand.kEnableDevTools), - ipv6: boolArg(FlutterCommand.ipv6Flag), - printDtd: boolArg(FlutterGlobalOptions.kPrintDtd, global: true), ); } } @@ -705,6 +702,7 @@ class RunCommand extends RunCommandBase { projectRootPath: stringArg('project-root'), dillOutputPath: stringArg('output-dill'), stayResident: stayResident, + ipv6: ipv6 ?? false, analytics: globals.analytics, nativeAssetsYamlFile: stringArg(FlutterOptions.kNativeAssetsYamlFile), nativeAssetsBuilder: _nativeAssetsBuilder, @@ -714,6 +712,7 @@ class RunCommand extends RunCommandBase { flutterDevices.single, target: targetFile, flutterProject: flutterProject, + ipv6: ipv6, debuggingOptions: await createDebuggingOptions(webMode), stayResident: stayResident, fileSystem: globals.fs, @@ -732,6 +731,7 @@ class RunCommand extends RunCommandBase { applicationBinary: applicationBinaryPath == null ? null : globals.fs.file(applicationBinaryPath), + ipv6: ipv6 ?? false, stayResident: stayResident, ); } @@ -776,7 +776,9 @@ class RunCommand extends RunCommandBase { projectRootPath: stringArg('project-root'), packagesFilePath: globalResults![FlutterGlobalOptions.kPackagesOption] as String?, dillOutputPath: stringArg('output-dill'), + ipv6: ipv6 ?? false, userIdentifier: userIdentifier, + enableDevTools: boolArg(FlutterCommand.kEnableDevTools), nativeAssetsBuilder: _nativeAssetsBuilder, ); } on Exception catch (error) { @@ -864,6 +866,7 @@ class RunCommand extends RunCommandBase { try { final int? result = await runner.run( appStartedCompleter: appStartedTimeRecorder, + enableDevTools: stayResident && boolArg(FlutterCommand.kEnableDevTools), route: route, ); handler?.stop(); diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index 459adcc001f4..482557aa4604 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -16,7 +16,6 @@ import '../globals.dart' as globals; import '../native_assets.dart'; import '../project.dart'; import '../runner/flutter_command.dart'; -import '../runner/flutter_command_runner.dart'; import '../test/coverage_collector.dart'; import '../test/event_printer.dart'; import '../test/runner.dart'; @@ -412,7 +411,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?), debugLogsDirectoryPath: debugLogsDirectoryPath, webRenderer: webRenderer, - printDtd: boolArg(FlutterGlobalOptions.kPrintDtd, global: true), webUseWasm: useWasm, webUseLocalCanvaskit: true, ); @@ -601,6 +599,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { excludeTags: excludeTags, watcher: watcher, enableVmService: collector != null || startPaused || enableVmService, + ipv6: ipv6, machine: machine, updateGoldens: boolArg('update-goldens'), concurrency: jobs, diff --git a/packages/flutter_tools/lib/src/custom_devices/custom_device.dart b/packages/flutter_tools/lib/src/custom_devices/custom_device.dart index 25980ab7d3ff..3a9ee366e372 100644 --- a/packages/flutter_tools/lib/src/custom_devices/custom_device.dart +++ b/packages/flutter_tools/lib/src/custom_devices/custom_device.dart @@ -352,6 +352,7 @@ class CustomDeviceAppSession { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier }) async { final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false; @@ -376,7 +377,7 @@ class CustomDeviceAppSession { logReader, portForwarder: _device._config.usesPortForwarding ? _device.portForwarder : null, logger: _logger, - ipv6: debuggingOptions.ipv6, + ipv6: ipv6, ); // We need to make the discovery listen to the logReader before the logReader @@ -438,7 +439,7 @@ class CustomDeviceAppSession { class CustomDevice extends Device { CustomDevice({ required CustomDeviceConfig config, - required super.logger, + required Logger logger, required ProcessManager processManager, }) : _config = config, _logger = logger, @@ -788,6 +789,7 @@ class CustomDevice extends Device { debuggingOptions: debuggingOptions, platformArgs: platformArgs, prebuiltApplication: prebuiltApplication, + ipv6: ipv6, userIdentifier: userIdentifier, ); } diff --git a/packages/flutter_tools/lib/src/desktop_device.dart b/packages/flutter_tools/lib/src/desktop_device.dart index a7579bdd0852..1044ab2caec0 100644 --- a/packages/flutter_tools/lib/src/desktop_device.dart +++ b/packages/flutter_tools/lib/src/desktop_device.dart @@ -26,7 +26,7 @@ abstract class DesktopDevice extends Device { DesktopDevice(super.id, { required PlatformType super.platformType, required super.ephemeral, - required super.logger, + required Logger logger, required ProcessManager processManager, required FileSystem fileSystem, required OperatingSystemUtils operatingSystemUtils, @@ -114,6 +114,7 @@ abstract class DesktopDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { if (!prebuiltApplication) { @@ -157,7 +158,7 @@ abstract class DesktopDevice extends Device { final ProtocolDiscovery vmServiceDiscovery = ProtocolDiscovery.vmService(_deviceLogReader, devicePort: debuggingOptions.deviceVmServicePort, hostPort: debuggingOptions.hostVmServicePort, - ipv6: debuggingOptions.ipv6, + ipv6: ipv6, logger: _logger, ); try { diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 7c4f32dfa508..35cc939656bc 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -603,11 +603,10 @@ String getNameForDeviceConnectionInterface(DeviceConnectionInterface connectionI /// the host operating system in the case of Flutter Desktop. abstract class Device { Device(this.id, { - required Logger logger, required this.category, required this.platformType, required this.ephemeral, - }) : dds = DartDevelopmentService(logger: logger); + }); final String id; @@ -734,7 +733,7 @@ abstract class Device { DevicePortForwarder? get portForwarder; /// Get the DDS instance for this device. - final DartDevelopmentService dds; + final DartDevelopmentService dds = DartDevelopmentService(); /// Clear the device's logs. void clearLogs(); @@ -779,6 +778,7 @@ abstract class Device { required DebuggingOptions debuggingOptions, Map platformArgs, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }); @@ -1007,11 +1007,7 @@ class DebuggingOptions { this.enableEmbedderApi = false, this.usingCISystem = false, this.debugLogsDirectoryPath, - this.enableDevTools = true, - this.ipv6 = false, - this.google3WorkspaceRoot, - this.printDtd = false, - }) : debuggingEnabled = true, + }) : debuggingEnabled = true, webRenderer = webRenderer ?? WebRendererMode.getDefault(useWasm: webUseWasm); DebuggingOptions.disabled(this.buildInfo, { @@ -1069,10 +1065,6 @@ class DebuggingOptions { nullAssertions = false, nativeNullAssertions = false, serveObservatory = false, - enableDevTools = false, - ipv6 = false, - google3WorkspaceRoot = null, - printDtd = false, webRenderer = webRenderer ?? WebRendererMode.getDefault(useWasm: webUseWasm); DebuggingOptions._({ @@ -1131,10 +1123,6 @@ class DebuggingOptions { required this.enableEmbedderApi, required this.usingCISystem, required this.debugLogsDirectoryPath, - required this.enableDevTools, - required this.ipv6, - required this.google3WorkspaceRoot, - required this.printDtd, }); final bool debuggingEnabled; @@ -1179,10 +1167,6 @@ class DebuggingOptions { final bool enableEmbedderApi; final bool usingCISystem; final String? debugLogsDirectoryPath; - final bool enableDevTools; - final bool ipv6; - final String? google3WorkspaceRoot; - final bool printDtd; /// Whether the tool should try to uninstall a previously installed version of the app. /// @@ -1236,6 +1220,7 @@ class DebuggingOptions { EnvironmentType environmentType, String? route, Map platformArgs, { + bool ipv6 = false, DeviceConnectionInterface interfaceType = DeviceConnectionInterface.attached, bool isCoreDevice = false, }) { @@ -1341,10 +1326,6 @@ class DebuggingOptions { 'enableEmbedderApi': enableEmbedderApi, 'usingCISystem': usingCISystem, 'debugLogsDirectoryPath': debugLogsDirectoryPath, - 'enableDevTools': enableDevTools, - 'ipv6': ipv6, - 'google3WorkspaceRoot': google3WorkspaceRoot, - 'printDtd': printDtd, }; static DebuggingOptions fromJson(Map json, BuildInfo buildInfo) => @@ -1404,10 +1385,6 @@ class DebuggingOptions { enableEmbedderApi: (json['enableEmbedderApi'] as bool?) ?? false, usingCISystem: (json['usingCISystem'] as bool?) ?? false, debugLogsDirectoryPath: json['debugLogsDirectoryPath'] as String?, - enableDevTools: (json['enableDevTools'] as bool?) ?? true, - ipv6: (json['ipv6'] as bool?) ?? false, - google3WorkspaceRoot: json['google3WorkspaceRoot'] as String?, - printDtd: (json['printDtd'] as bool?) ?? false, ); } diff --git a/packages/flutter_tools/lib/src/drive/drive_service.dart b/packages/flutter_tools/lib/src/drive/drive_service.dart index 82bd4bad4d53..b3340db461fe 100644 --- a/packages/flutter_tools/lib/src/drive/drive_service.dart +++ b/packages/flutter_tools/lib/src/drive/drive_service.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:dds/dds.dart' as dds; import 'package:file/file.dart'; import 'package:meta/meta.dart'; import 'package:package_config/package_config_types.dart'; @@ -11,7 +12,6 @@ import 'package:vm_service/vm_service.dart' as vm_service; import '../application_package.dart'; import '../base/common.dart'; -import '../base/dds.dart'; import '../base/logger.dart'; import '../base/process.dart'; import '../build_info.dart'; @@ -65,7 +65,8 @@ abstract class DriverService { Future start( BuildInfo buildInfo, Device device, - DebuggingOptions debuggingOptions, { + DebuggingOptions debuggingOptions, + bool ipv6, { File? applicationBinary, String? route, String? userIdentifier, @@ -78,6 +79,7 @@ abstract class DriverService { Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, + bool ipv6, ); /// Start the test file with the provided [arguments] and [environment], returning @@ -146,7 +148,8 @@ class FlutterDriverService extends DriverService { Future start( BuildInfo buildInfo, Device device, - DebuggingOptions debuggingOptions, { + DebuggingOptions debuggingOptions, + bool ipv6, { File? applicationBinary, String? route, String? userIdentifier, @@ -196,6 +199,7 @@ class FlutterDriverService extends DriverService { result.vmServiceUri!, device, debuggingOptions, + ipv6, ); } @@ -204,6 +208,7 @@ class FlutterDriverService extends DriverService { Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, + bool ipv6, ) async { Uri uri; if (vmServiceUri.scheme == 'ws') { @@ -217,12 +222,15 @@ class FlutterDriverService extends DriverService { _device = device; if (debuggingOptions.enableDds) { try { - await device.dds.startDartDevelopmentServiceFromDebuggingOptions( + await device.dds.startDartDevelopmentService( uri, - debuggingOptions: debuggingOptions, + hostPort: debuggingOptions.ddsPort, + ipv6: ipv6, + disableServiceAuthCodes: debuggingOptions.disableServiceAuthCodes, + logger: _logger, ); _vmServiceUri = device.dds.uri.toString(); - } on DartDevelopmentServiceException { + } on dds.DartDevelopmentServiceException { // If there's another flutter_tools instance still connected to the target // application, DDS will already be running remotely and this call will fail. // This can be ignored to continue to use the existing remote DDS instance. diff --git a/packages/flutter_tools/lib/src/drive/web_driver_service.dart b/packages/flutter_tools/lib/src/drive/web_driver_service.dart index d7194f347602..b7989cc1292b 100644 --- a/packages/flutter_tools/lib/src/drive/web_driver_service.dart +++ b/packages/flutter_tools/lib/src/drive/web_driver_service.dart @@ -55,7 +55,8 @@ class WebDriverService extends DriverService { Future start( BuildInfo buildInfo, Device device, - DebuggingOptions debuggingOptions, { + DebuggingOptions debuggingOptions, + bool ipv6, { File? applicationBinary, String? route, String? userIdentifier, @@ -71,6 +72,7 @@ class WebDriverService extends DriverService { _residentRunner = webRunnerFactory!.createWebRunner( flutterDevice, target: mainPath, + ipv6: ipv6, debuggingOptions: buildInfo.isRelease ? DebuggingOptions.disabled( buildInfo, @@ -232,7 +234,7 @@ class WebDriverService extends DriverService { } @override - Future reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions) async { + Future reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async { throwToolExit('--use-existing-app is not supported with flutter web driver'); } } diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart index 4e7ffe89b018..bb7ffdb0d9cc 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart @@ -58,9 +58,10 @@ Future _kDefaultDartDevelopmentServiceStarter( ) async { await device.dds.startDartDevelopmentService( vmServiceUri, - ddsPort: 0, - disableServiceAuthCodes: disableServiceAuthCodes, + hostPort: 0, ipv6: true, + disableServiceAuthCodes: disableServiceAuthCodes, + logger: globals.logger, ); } @@ -211,7 +212,7 @@ class FuchsiaDevices extends PollingDeviceDiscovery { _logger.printError('Failed to resolve host for Fuchsia device `$name`'); return null; } - return FuchsiaDevice(resolvedHost, name: name, logger: _logger); + return FuchsiaDevice(resolvedHost, name: name); } @override @@ -219,7 +220,7 @@ class FuchsiaDevices extends PollingDeviceDiscovery { } class FuchsiaDevice extends Device { - FuchsiaDevice(super.id, {required this.name, required super.logger}) + FuchsiaDevice(super.id, {required this.name}) : super( platformType: PlatformType.fuchsia, category: null, @@ -294,6 +295,7 @@ class FuchsiaDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { if (await isSession) { diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index 554abf65e66b..4baceaacd78e 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart @@ -272,7 +272,7 @@ class IOSDevice extends Device { required IOSCoreDeviceControl coreDeviceControl, required XcodeDebug xcodeDebug, required IProxy iProxy, - required super.logger, + required Logger logger, }) : _sdkVersion = sdkVersion, _iosDeploy = iosDeploy, @@ -470,6 +470,7 @@ class IOSDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, @visibleForTesting Duration? discoveryTimeout, @visibleForTesting ShutdownHooks? shutdownHooks, @@ -523,6 +524,7 @@ class IOSDevice extends Device { EnvironmentType.physical, route, platformArgs, + ipv6: ipv6, interfaceType: connectionInterface, isCoreDevice: isCoreDevice, ); @@ -539,6 +541,7 @@ class IOSDevice extends Device { bundle: bundle, debuggingOptions: debuggingOptions, launchArguments: launchArguments, + ipv6: ipv6, uninstallFirst: debuggingOptions.uninstallFirst, ); } @@ -616,6 +619,7 @@ class IOSDevice extends Device { localUri = await _discoverDartVMForCoreDevice( debuggingOptions: debuggingOptions, packageId: packageId, + ipv6: ipv6, vmServiceDiscovery: vmServiceDiscovery, ); } else if (isWirelesslyConnected) { @@ -647,7 +651,7 @@ class IOSDevice extends Device { localUri = await MDnsVmServiceDiscovery.instance!.getVMServiceUriForLaunch( packageId, this, - usesIpv6: debuggingOptions.ipv6, + usesIpv6: ipv6, deviceVmservicePort: serviceURL.port, useDeviceIPAsHost: true, ); @@ -669,6 +673,7 @@ class IOSDevice extends Device { bundle: bundle, debuggingOptions: debuggingOptions, launchArguments: launchArguments, + ipv6: ipv6, uninstallFirst: false, skipInstall: true, ); @@ -723,6 +728,7 @@ class IOSDevice extends Device { /// Wireless devices require using the device IP as the host. Future _discoverDartVMForCoreDevice({ required String packageId, + required bool ipv6, required DebuggingOptions debuggingOptions, ProtocolDiscovery? vmServiceDiscovery, }) async { @@ -769,7 +775,7 @@ class IOSDevice extends Device { final Future vmUrlFromMDns = MDnsVmServiceDiscovery.instance!.getVMServiceUriForLaunch( packageId, this, - usesIpv6: debuggingOptions.ipv6, + usesIpv6: ipv6, useDeviceIPAsHost: isWirelesslyConnected, ); @@ -808,6 +814,7 @@ class IOSDevice extends Device { required Directory bundle, required DebuggingOptions debuggingOptions, required List launchArguments, + required bool ipv6, required bool uninstallFirst, bool skipInstall = false, }) { @@ -838,7 +845,7 @@ class IOSDevice extends Device { portForwarder: isWirelesslyConnected ? null : portForwarder, hostPort: debuggingOptions.hostVmServicePort, devicePort: debuggingOptions.deviceVmServicePort, - ipv6: debuggingOptions.ipv6, + ipv6: ipv6, logger: _logger, ); } diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart index 97d61857caf4..fb255f840674 100644 --- a/packages/flutter_tools/lib/src/ios/simulators.dart +++ b/packages/flutter_tools/lib/src/ios/simulators.dart @@ -90,7 +90,6 @@ class IOSSimulatorUtils { name: name, simControl: _simControl, simulatorCategory: device.category, - logger: _simControl._logger, ); }).whereType().toList(); } @@ -357,7 +356,6 @@ class IOSSimulator extends Device { required this.name, required this.simulatorCategory, required SimControl simControl, - required super.logger, }) : _simControl = simControl, super( category: Category.mobile, @@ -474,6 +472,7 @@ class IOSSimulator extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { if (!prebuiltApplication && package is BuildableIOSApp) { @@ -502,7 +501,7 @@ class IOSSimulator extends Device { if (debuggingOptions.debuggingEnabled) { vmServiceDiscovery = ProtocolDiscovery.vmService( getLogReader(app: package), - ipv6: debuggingOptions.ipv6, + ipv6: ipv6, hostPort: debuggingOptions.hostVmServicePort, devicePort: debuggingOptions.deviceVmServicePort, logger: globals.logger, diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart index 52d8368a6994..332e964ce035 100644 --- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart @@ -50,6 +50,7 @@ class DwdsWebRunnerFactory extends WebRunnerFactory { String? target, required bool stayResident, required FlutterProject flutterProject, + required bool? ipv6, required DebuggingOptions debuggingOptions, UrlTunneller? urlTunneller, required Logger logger, @@ -64,6 +65,7 @@ class DwdsWebRunnerFactory extends WebRunnerFactory { target: target, flutterProject: flutterProject, debuggingOptions: debuggingOptions, + ipv6: ipv6, stayResident: stayResident, urlTunneller: urlTunneller, machine: machine, @@ -87,6 +89,7 @@ class ResidentWebRunner extends ResidentRunner { bool stayResident = true, bool machine = false, required this.flutterProject, + required bool? ipv6, required DebuggingOptions debuggingOptions, required FileSystem fileSystem, required Logger logger, @@ -94,7 +97,6 @@ class ResidentWebRunner extends ResidentRunner { required Usage usage, required Analytics analytics, UrlTunneller? urlTunneller, - // TODO(bkonyi): remove when ready to serve DevTools from DDS. ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler, }) : _fileSystem = fileSystem, _logger = logger, @@ -106,6 +108,7 @@ class ResidentWebRunner extends ResidentRunner { [device], target: target ?? fileSystem.path.join('lib', 'main.dart'), debuggingOptions: debuggingOptions, + ipv6: ipv6, stayResident: stayResident, machine: machine, devtoolsHandler: devtoolsHandler, @@ -192,7 +195,6 @@ class ResidentWebRunner extends ResidentRunner { if (_exited) { return; } - // TODO(bkonyi): remove when ready to serve DevTools from DDS. await residentDevtoolsHandler!.shutdown(); await _stdOutSub?.cancel(); await _stdErrSub?.cancel(); @@ -245,6 +247,7 @@ class ResidentWebRunner extends ResidentRunner { Future run({ Completer? connectionInfoCompleter, Completer? appStartedCompleter, + bool enableDevTools = false, // ignored, we don't yet support devtools for web String? route, }) async { final ApplicationPackage? package = await ApplicationPackageFactory.instance!.getPackageForPlatform( @@ -365,6 +368,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). return attach( connectionInfoCompleter: connectionInfoCompleter, appStartedCompleter: appStartedCompleter, + enableDevTools: enableDevTools, ); }); } on WebSocketException catch (error, stackTrace) { @@ -472,14 +476,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). final Duration elapsed = _systemClock.now().difference(start); final String elapsedMS = getElapsedAsMilliseconds(elapsed); _logger.printStatus('Restarted application in $elapsedMS.'); - - // TODO(bkonyi): replace with code below when ready to serve DevTools from DDS. unawaited(residentDevtoolsHandler!.hotRestart(flutterDevices)); - /* - for (final FlutterDevice? device in flutterDevices) { - unawaited(device?.handleHotRestart()); - } - */ // Don't track restart times for dart2js builds or web-server devices. if (debuggingOptions.buildInfo.isDebug && deviceIsDebuggable) { @@ -606,6 +603,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). Completer? connectionInfoCompleter, Completer? appStartedCompleter, bool allowExistingDdsInstance = false, + bool enableDevTools = false, // ignored, we don't yet support devtools for web bool needsFullRestart = true, }) async { if (_chromiumLauncher != null) { @@ -684,14 +682,13 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). } }); } - } - // TODO(bkonyi): remove when ready to serve DevTools from DDS. - if (debuggingOptions.enableDevTools) { - // The method below is guaranteed never to return a failing future. - unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools( - devToolsServerAddress: debuggingOptions.devToolsServerAddress, - flutterDevices: flutterDevices, - )); + if (enableDevTools) { + // The method below is guaranteed never to return a failing future. + unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools( + devToolsServerAddress: debuggingOptions.devToolsServerAddress, + flutterDevices: flutterDevices, + )); + } } if (websocketUri != null) { if (debuggingOptions.vmserviceOutFile != null) { diff --git a/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart b/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart index e371569c73b7..235d01383d56 100644 --- a/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart +++ b/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart @@ -99,6 +99,7 @@ class MacOSDesignedForIPadDevice extends DesktopDevice { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { // Only attaching to a running app launched from Xcode is supported. diff --git a/packages/flutter_tools/lib/src/preview_device.dart b/packages/flutter_tools/lib/src/preview_device.dart index 2577a29e607b..71eba1fcb133 100644 --- a/packages/flutter_tools/lib/src/preview_device.dart +++ b/packages/flutter_tools/lib/src/preview_device.dart @@ -95,7 +95,7 @@ class PreviewDeviceDiscovery extends PollingDeviceDiscovery { class PreviewDevice extends Device { PreviewDevice({ required ProcessManager processManager, - required super.logger, + required Logger logger, required FileSystem fileSystem, required Artifacts artifacts, required File previewBinary, @@ -170,6 +170,7 @@ class PreviewDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { final Directory assetDirectory = _fileSystem.systemTempDirectory @@ -213,7 +214,7 @@ class PreviewDevice extends Device { final ProtocolDiscovery vmServiceDiscovery = ProtocolDiscovery.vmService(_logReader, devicePort: debuggingOptions.deviceVmServicePort, hostPort: debuggingOptions.hostVmServicePort, - ipv6: debuggingOptions.ipv6, + ipv6: ipv6, logger: _logger, ); try { diff --git a/packages/flutter_tools/lib/src/proxied_devices/devices.dart b/packages/flutter_tools/lib/src/proxied_devices/devices.dart index 897c4efa7ce1..c286ce2545f8 100644 --- a/packages/flutter_tools/lib/src/proxied_devices/devices.dart +++ b/packages/flutter_tools/lib/src/proxied_devices/devices.dart @@ -19,7 +19,6 @@ import '../device.dart'; import '../device_port_forwarder.dart'; import '../device_vm_service_discovery_for_attach.dart'; import '../project.dart'; -import '../resident_runner.dart'; import 'debounce_data_stream.dart'; import 'file_transfer.dart'; @@ -176,7 +175,7 @@ class ProxiedDevice extends Device { required this.supportsScreenshot, required this.supportsFastStart, required bool supportsHardwareRendering, - required super.logger, + required Logger logger, FileTransfer fileTransfer = const FileTransfer(), }): _deltaFileTransfer = deltaFileTransfer, _enableDdsProxy = enableDdsProxy, @@ -335,6 +334,7 @@ class ProxiedDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { final Map result = _cast>(await connection.sendRequest('device.startApp', { @@ -345,7 +345,7 @@ class ProxiedDevice extends Device { 'debuggingOptions': debuggingOptions.toJson(), 'platformArgs': platformArgs, 'prebuiltApplication': prebuiltApplication, - 'ipv6': debuggingOptions.ipv6, + 'ipv6': ipv6, 'userIdentifier': userIdentifier, })); final bool started = _cast(result['started']); @@ -748,7 +748,7 @@ Future _defaultCreateServerSocket(Logger logger, int? hostPort, bo /// There are a lot of communications between DDS and the VM service on the /// device. When using proxied device, starting DDS remotely helps reduces the /// amount of data transferred with the remote daemon, hence improving latency. -class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin implements DartDevelopmentService { +class ProxiedDartDevelopmentService implements DartDevelopmentService { ProxiedDartDevelopmentService( this.connection, this.deviceId, { @@ -756,11 +756,10 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi required ProxiedPortForwarder proxiedPortForwarder, required ProxiedPortForwarder devicePortForwarder, @visibleForTesting DartDevelopmentService? localDds, - }) : - _logger = logger, + }) : _logger = logger, _proxiedPortForwarder = proxiedPortForwarder, _devicePortForwarder = devicePortForwarder, - _localDds = localDds ?? DartDevelopmentService(logger: logger); + _localDds = localDds ?? DartDevelopmentService(); final String deviceId; @@ -777,9 +776,10 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi /// It forwards a port on the remotely connected device, to the remote host, then to the local host. final ProxiedPortForwarder _devicePortForwarder; + Uri? _localUri; + @override Uri? get uri => _ddsStartedLocally ? _localDds.uri : _localUri; - Uri? _localUri; @override Future get done => _completer.future; @@ -792,14 +792,11 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi @override Future startDartDevelopmentService( Uri vmServiceUri, { - FlutterDevice? device, - int? ddsPort, + required Logger logger, + int? hostPort, bool? ipv6, bool? disableServiceAuthCodes, - bool enableDevTools = false, bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async { // Locate the original VM service port on the remote daemon. // A proxied device has two PortForwarder. Check both to determine which @@ -808,26 +805,18 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi _proxiedPortForwarder.originalRemotePort(vmServiceUri.port) ?? _devicePortForwarder.originalRemotePort(vmServiceUri.port); - Future startLocalDds() async { + if (remoteVMServicePort == null) { + _logger.printTrace('VM service port is not a forwarded port. Start DDS locally.'); _ddsStartedLocally = true; await _localDds.startDartDevelopmentService( vmServiceUri, - ddsPort: ddsPort, + logger: logger, + hostPort: hostPort, ipv6: ipv6, disableServiceAuthCodes: disableServiceAuthCodes, cacheStartupProfile: cacheStartupProfile, - enableDevTools: enableDevTools, - google3WorkspaceRoot: google3WorkspaceRoot, - devToolsServerAddress: devToolsServerAddress, ); - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // unawaited(_localDds.invokeServiceExtensions(device)); unawaited(_localDds.done.then(_completer.complete)); - } - - if (remoteVMServicePort == null) { - _logger.printTrace('VM service port is not a forwarded port. Start DDS locally.'); - await startLocalDds(); return; } @@ -846,33 +835,11 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi // Ignore if we did not receive any event from the server. }, )); - final Object? response = await connection.sendRequest(method, { - 'deviceId': deviceId, - 'vmServiceUri': remoteVMServiceUri.toString(), - 'disableServiceAuthCodes': disableServiceAuthCodes, - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // 'enableDevTools': enableDevTools, - // if (devToolsServerAddress != null) 'devToolsServerAddress': devToolsServerAddress.toString(), - }); - - if (response is Map) { - remoteUriStr = response['ddsUri'] as String?; - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - /* - final String? devToolsUriStr = response['devToolsUri'] as String?; - if (devToolsUriStr != null) { - _remoteDevToolsUri = Uri.parse(devToolsUriStr); - } - final String? dtdUriStr = response['dtdUri'] as String?; - if (dtdUriStr != null) { - _remoteDtdUri = Uri.parse(dtdUriStr); - } - */ - } else { - // For backwards compatibility in google3. - // TODO(bkonyi): remove once a newer version of the flutter_tool is rolled out. - remoteUriStr = _cast(response); - } + remoteUriStr = _cast(await connection.sendRequest(method, { + 'deviceId': deviceId, + 'vmServiceUri': remoteVMServiceUri.toString(), + 'disableServiceAuthCodes': disableServiceAuthCodes, + })); } on String catch (e) { if (!e.contains(method)) { rethrow; @@ -883,7 +850,16 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi if (remoteUriStr == null) { _logger.printTrace('Remote daemon cannot start DDS. Start a local DDS instead.'); - await startLocalDds(); + _ddsStartedLocally = true; + await _localDds.startDartDevelopmentService( + vmServiceUri, + logger: logger, + hostPort: hostPort, + ipv6: ipv6, + disableServiceAuthCodes: disableServiceAuthCodes, + cacheStartupProfile: cacheStartupProfile, + ); + unawaited(_localDds.done.then(_completer.complete)); return; } @@ -893,7 +869,7 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi final Uri remoteUri = Uri.parse(remoteUriStr); final int localPort = await _proxiedPortForwarder.forward( remoteUri.port, - hostPort: ddsPort, + hostPort: hostPort, ipv6: ipv6, ); @@ -909,7 +885,7 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi @override Future shutdown() async { if (_ddsStartedLocally) { - _localDds.shutdown(); + await _localDds.shutdown(); _ddsStartedLocally = false; } else { await connection.sendRequest('device.shutdownDartDevelopmentService', { @@ -917,6 +893,14 @@ class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMi }); } } + + @override + void setExternalDevToolsUri(Uri uri) { + connection.sendRequest('device.setExternalDevToolsUriForDartDevelopmentService', { + 'deviceId': deviceId, + 'uri': uri.toString(), + }); + } } class ProxiedVMServiceDiscoveryForAttach extends VMServiceDiscoveryForAttach { diff --git a/packages/flutter_tools/lib/src/resident_devtools_handler.dart b/packages/flutter_tools/lib/src/resident_devtools_handler.dart index ae5f2b2a840a..d304451db724 100644 --- a/packages/flutter_tools/lib/src/resident_devtools_handler.dart +++ b/packages/flutter_tools/lib/src/resident_devtools_handler.dart @@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(bkonyi): remove this file when ready to serve DevTools from DDS. -// -// See https://github.com/flutter/flutter/issues/150044 - import 'dart:async'; import 'package:browser_launcher/browser_launcher.dart'; @@ -114,6 +110,18 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler { return; } + final Uri? devToolsUrl = _devToolsLauncher.devToolsUrl; + if (devToolsUrl != null) { + for (final FlutterDevice? device in flutterDevices) { + if (device == null) { + continue; + } + // Notify the DDS instances that there's a DevTools instance available so they can correctly + // redirect DevTools related requests. + device.device?.dds.setExternalDevToolsUri(devToolsUrl); + } + } + Future callServiceExtensions() async { final List devicesWithExtension = await _devicesWithExtensions(flutterDevices); await Future.wait( @@ -206,12 +214,10 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler { }, ); } on Exception catch (e) { - if (!_shutdown) { - _logger.printError( - 'Failed to set DevTools server address: $e. Deep links to' - ' DevTools will not show in Flutter errors.', - ); - } + _logger.printError( + 'Failed to set DevTools server address: $e. Deep links to' + ' DevTools will not show in Flutter errors.', + ); } } @@ -260,13 +266,11 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler { }, ); } on Exception catch (e) { - if (!_shutdown) { - _logger.printError(e.toString()); - _logger.printError( - 'Failed to set vm service URI: $e. Deep links to DevTools' - ' will not show in Flutter errors.', - ); - } + _logger.printError(e.toString()); + _logger.printError( + 'Failed to set vm service URI: $e. Deep links to DevTools' + ' will not show in Flutter errors.', + ); } } @@ -304,10 +308,10 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler { @override Future shutdown() async { - _shutdown = true; - if (_devToolsLauncher == null || !_served) { + if (_devToolsLauncher == null || _shutdown || !_served) { return; } + _shutdown = true; _readyToAnnounce = false; await _devToolsLauncher.close(); } diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index b8e084222840..1af14acbb84e 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:dds/dds.dart' as dds; import 'package:meta/meta.dart'; import 'package:package_config/package_config.dart'; import 'package:vm_service/vm_service.dart' as vm_service; @@ -14,7 +15,6 @@ import 'asset.dart'; import 'base/command_help.dart'; import 'base/common.dart'; import 'base/context.dart'; -import 'base/dds.dart'; import 'base/file_system.dart'; import 'base/io.dart' as io; import 'base/logger.dart'; @@ -252,9 +252,13 @@ class FlutterDevice { CompileExpression? compileExpression, GetSkSLMethod? getSkSLMethod, PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, - required DebuggingOptions debuggingOptions, int? hostVmServicePort, + int? ddsPort, + bool disableServiceAuthCodes = false, + bool cacheStartupProfile = false, + bool enableDds = true, required bool allowExistingDdsInstance, + bool ipv6 = false, }) { final Completer completer = Completer(); late StreamSubscription subscription; @@ -266,11 +270,11 @@ class FlutterDevice { isWaitingForVm = true; bool existingDds = false; FlutterVmService? service; - if (debuggingOptions.enableDds) { + if (enableDds) { void handleError(Exception e, StackTrace st) { globals.printTrace('Fail to connect to service protocol: $vmServiceUri: $e'); if (!completer.isCompleted) { - completer.completeError('failed to connect to $vmServiceUri $e', st); + completer.completeError('failed to connect to $vmServiceUri', st); } } // First check if the VM service is actually listening on vmServiceUri as @@ -282,7 +286,7 @@ class FlutterDevice { } on Exception catch (exception) { globals.printTrace('Fail to connect to service protocol: $vmServiceUri: $exception'); if (!completer.isCompleted && !_isListeningForVmServiceUri!) { - completer.completeError('failed to connect to $vmServiceUri $exception'); + completer.completeError('failed to connect to $vmServiceUri'); } return; } @@ -291,13 +295,17 @@ class FlutterDevice { // (e.g., failure to bind to a port, failure to connect to the VM service, // attaching to a VM service with existing clients, etc.). try { - await device!.dds.startDartDevelopmentServiceFromDebuggingOptions( + await device!.dds.startDartDevelopmentService( vmServiceUri, - debuggingOptions: debuggingOptions, + hostPort: ddsPort, + ipv6: ipv6, + disableServiceAuthCodes: disableServiceAuthCodes, + logger: globals.logger, + cacheStartupProfile: cacheStartupProfile, ); - } on DartDevelopmentServiceException catch (e, st) { + } on dds.DartDevelopmentServiceException catch (e, st) { if (!allowExistingDdsInstance || - (e.errorCode != DartDevelopmentServiceException.existingDdsInstanceError)) { + (e.errorCode != dds.DartDevelopmentServiceException.existingDdsInstanceError)) { handleError(e, st); return; } else { @@ -318,7 +326,7 @@ class FlutterDevice { service = await Future.any( >[ connectToVmService( - debuggingOptions.enableDds ? (device!.dds.uri ?? vmServiceUri!): vmServiceUri!, + enableDds ? (device!.dds.uri ?? vmServiceUri!): vmServiceUri!, reloadSources: reloadSources, restart: restart, compileExpression: compileExpression, @@ -335,7 +343,7 @@ class FlutterDevice { } on Exception catch (exception) { globals.printTrace('Fail to connect to service protocol: $vmServiceUri: $exception'); if (!completer.isCompleted && !_isListeningForVmServiceUri!) { - completer.completeError('failed to connect to $vmServiceUri $exception'); + completer.completeError('failed to connect to $vmServiceUri'); } return; } @@ -345,22 +353,6 @@ class FlutterDevice { globals.printTrace('Successfully connected to service protocol: $vmServiceUri'); vmService = service; - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - /* - if (debuggingOptions.enableDds && !existingDds) { - // Don't await this as service extensions won't return if the target - // isolate is paused on start. - unawaited(device!.dds.invokeServiceExtensions(this)); - } - if (existingDds && debuggingOptions.devToolsServerAddress != null) { - // Don't await this as service extensions won't return if the target - // isolate is paused on start. - unawaited(device!.dds.maybeCallDevToolsUriServiceExtension( - device: this, - uri: debuggingOptions.devToolsServerAddress, - )); - } - */ (await device!.getLogReader(app: package)).connectedVMService = vmService; completer.complete(); await subscription.cancel(); @@ -480,6 +472,7 @@ class FlutterDevice { platformArgs: platformArgs, route: route, prebuiltApplication: prebuiltMode, + ipv6: hotRunner.ipv6!, userIdentifier: userIdentifier, ); @@ -545,6 +538,7 @@ class FlutterDevice { platformArgs: platformArgs, route: route, prebuiltApplication: prebuiltMode, + ipv6: coldRunner.ipv6!, userIdentifier: userIdentifier, ); @@ -616,13 +610,6 @@ class FlutterDevice { await generator?.reject(); } } - - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - /* - Future handleHotRestart() async { - await device?.dds.handleHotRestart(this); - } - */ } /// A subset of the [ResidentRunner] for delegating to attached flutter devices. @@ -661,7 +648,6 @@ abstract class ResidentHandlers { /// Whether all of the connected devices support hot reload. bool get canHotReload; - // TODO(bkonyi): remove when ready to serve DevTools from DDS. ResidentDevtoolsHandler? get residentDevtoolsHandler; @protected @@ -1110,6 +1096,7 @@ abstract class ResidentRunner extends ResidentHandlers { required this.target, required this.debuggingOptions, String? projectRootPath, + this.ipv6, this.stayResident = true, this.hotMode = true, String? dillOutputPath, @@ -1132,7 +1119,6 @@ abstract class ResidentRunner extends ResidentHandlers { if (!artifactDirectory.existsSync()) { artifactDirectory.createSync(recursive: true); } - // TODO(bkonyi): remove when ready to serve DevTools from DDS. _residentDevtoolsHandler = devtoolsHandler(DevtoolsLauncher.instance, this, globals.logger); } @@ -1150,6 +1136,7 @@ abstract class ResidentRunner extends ResidentHandlers { @override final bool stayResident; + final bool? ipv6; final String? _dillOutputPath; /// The parent location of the incremental artifacts. final Directory artifactDirectory; @@ -1161,7 +1148,6 @@ abstract class ResidentRunner extends ResidentHandlers { final CommandHelp commandHelp; final bool machine; - // TODO(bkonyi): remove when ready to serve DevTools from DDS. @override ResidentDevtoolsHandler? get residentDevtoolsHandler => _residentDevtoolsHandler; ResidentDevtoolsHandler? _residentDevtoolsHandler; @@ -1242,6 +1228,7 @@ abstract class ResidentRunner extends ResidentHandlers { Future run({ Completer? connectionInfoCompleter, Completer? appStartedCompleter, + bool enableDevTools = false, String? route, }); @@ -1253,6 +1240,7 @@ abstract class ResidentRunner extends ResidentHandlers { Completer? connectionInfoCompleter, Completer? appStartedCompleter, bool allowExistingDdsInstance = false, + bool enableDevTools = false, bool needsFullRestart = true, }); @@ -1318,21 +1306,19 @@ abstract class ResidentRunner extends ResidentHandlers { @override Future exit() async { _exited = true; - // TODO(bkonyi): remove when ready to serve DevTools from DDS. await residentDevtoolsHandler!.shutdown(); await stopEchoingDeviceLog(); await preExit(); await exitApp(); // calls appFinished - shutdownDartDevelopmentService(); + await shutdownDartDevelopmentService(); } @override Future detach() async { - // TODO(bkonyi): remove when ready to serve DevTools from DDS. await residentDevtoolsHandler!.shutdown(); await stopEchoingDeviceLog(); await preExit(); - shutdownDartDevelopmentService(); + await shutdownDartDevelopmentService(); appFinished(); } @@ -1342,10 +1328,12 @@ abstract class ResidentRunner extends ResidentHandlers { ); } - void shutdownDartDevelopmentService() { - for (final FlutterDevice device in flutterDevices) { - device.device?.dds.shutdown(); - } + Future shutdownDartDevelopmentService() async { + await Future.wait( + flutterDevices.map>( + (FlutterDevice? device) => device?.device?.dds.shutdown() ?? Future.value() + ) + ); } @protected @@ -1414,14 +1402,18 @@ abstract class ResidentRunner extends ResidentHandlers { // Listen for service protocol connection to close. for (final FlutterDevice? device in flutterDevices) { await device!.connect( - debuggingOptions: debuggingOptions, reloadSources: reloadSources, restart: restart, compileExpression: compileExpression, + enableDds: debuggingOptions.enableDds, + ddsPort: debuggingOptions.ddsPort, allowExistingDdsInstance: allowExistingDdsInstance, hostVmServicePort: debuggingOptions.hostVmServicePort, getSkSLMethod: getSkSLMethod, printStructuredErrorLogMethod: printStructuredErrorLog, + ipv6: ipv6 ?? false, + disableServiceAuthCodes: debuggingOptions.disableServiceAuthCodes, + cacheStartupProfile: debuggingOptions.cacheStartupProfile, ); await device.vmService!.getFlutterViews(); @@ -1511,8 +1503,7 @@ abstract class ResidentRunner extends ResidentHandlers { bool get reportedDebuggers => _reportedDebuggers; bool _reportedDebuggers = false; - void printDebuggerList({bool includeVmService = true, bool includeDevtools = true}) { - // TODO(bkonyi): update this logic when ready to serve DevTools from DDS. + void printDebuggerList({ bool includeVmService = true, bool includeDevtools = true }) { final DevToolsServerAddress? devToolsServerAddress = residentDevtoolsHandler!.activeDevToolsServer; if (!residentDevtoolsHandler!.readyToAnnounce) { includeDevtools = false; @@ -1825,13 +1816,6 @@ class TerminalHandler { case 'v': case 'V': return residentRunner.residentDevtoolsHandler!.launchDevToolsInBrowser(flutterDevices: residentRunner.flutterDevices); - // TODO(bkonyi): uncomment and replace above line when ready to serve DevTools from DDS. - /* - return residentRunner.flutterDevices.fold( - true, - (bool s, FlutterDevice? device) => s && device!.device!.dds.launchDevToolsInBrowser(device), - ); - */ case 'w': case 'W': return residentRunner.debugDumpApp(); @@ -1972,7 +1956,6 @@ abstract class DevtoolsLauncher { @protected set dtdUri(Uri? value) => _dtdUri = value; - // TODO(bkonyi): remove when ready to serve DevTools from DDS. /// Whether to print the Dart Tooling Daemon URI. /// /// This will always return false when there is not a DTD instance being diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart index 0302f32fc2d6..63ac8dc2d77a 100644 --- a/packages/flutter_tools/lib/src/run_cold.dart +++ b/packages/flutter_tools/lib/src/run_cold.dart @@ -21,6 +21,7 @@ class ColdRunner extends ResidentRunner { this.traceStartup = false, this.awaitFirstFrameWhenTracing = true, this.applicationBinary, + bool super.ipv6 = false, super.stayResident, super.machine, super.devtoolsHandler, @@ -46,6 +47,7 @@ class ColdRunner extends ResidentRunner { Future run({ Completer? connectionInfoCompleter, Completer? appStartedCompleter, + bool enableDevTools = false, String? route, }) async { try { @@ -76,18 +78,18 @@ class ColdRunner extends ResidentRunner { } } - if (debuggingEnabled && debuggingOptions.serveObservatory) { - await enableObservatory(); - } - - // TODO(bkonyi): remove when ready to serve DevTools from DDS. - if (debuggingEnabled && debuggingOptions.enableDevTools) { - // The method below is guaranteed never to return a failing future. - unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools( - devToolsServerAddress: debuggingOptions.devToolsServerAddress, - flutterDevices: flutterDevices, - isStartPaused: debuggingOptions.startPaused, - )); + if (debuggingEnabled) { + if (enableDevTools) { + // The method below is guaranteed never to return a failing future. + unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools( + devToolsServerAddress: debuggingOptions.devToolsServerAddress, + flutterDevices: flutterDevices, + isStartPaused: debuggingOptions.startPaused, + )); + } + if (debuggingOptions.serveObservatory) { + await enableObservatory(); + } } if (flutterDevices.first.vmServiceUris != null) { @@ -140,6 +142,7 @@ class ColdRunner extends ResidentRunner { Completer? connectionInfoCompleter, Completer? appStartedCompleter, bool allowExistingDdsInstance = false, + bool enableDevTools = false, bool needsFullRestart = true, }) async { _didAttach = true; @@ -163,8 +166,18 @@ class ColdRunner extends ResidentRunner { } } - if (debuggingEnabled && debuggingOptions.serveObservatory) { - await enableObservatory(); + if (debuggingEnabled) { + if (enableDevTools) { + // The method below is guaranteed never to return a failing future. + unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools( + devToolsServerAddress: debuggingOptions.devToolsServerAddress, + flutterDevices: flutterDevices, + isStartPaused: debuggingOptions.startPaused, + )); + } + if (debuggingOptions.serveObservatory) { + await enableObservatory(); + } } appStartedCompleter?.complete(); @@ -190,11 +203,12 @@ class ColdRunner extends ResidentRunner { await flutterDevice!.device!.dispose(); } + await residentDevtoolsHandler!.shutdown(); await stopEchoingDeviceLog(); } @override - void printHelp({required bool details}) { + void printHelp({ required bool details }) { globals.printStatus('Flutter run key commands.'); if (details) { printHelpDetails(); diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index 2684e093b560..d79a01daacea 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -86,6 +86,7 @@ class HotRunner extends ResidentRunner { super.projectRootPath, super.dillOutputPath, super.stayResident, + bool super.ipv6 = false, super.machine, super.devtoolsHandler, StopwatchFactory stopwatchFactory = const StopwatchFactory(), @@ -227,6 +228,7 @@ class HotRunner extends ResidentRunner { Completer? connectionInfoCompleter, Completer? appStartedCompleter, bool allowExistingDdsInstance = false, + bool enableDevTools = false, bool needsFullRestart = true, }) async { _didAttach = true; @@ -251,8 +253,7 @@ class HotRunner extends ResidentRunner { await enableObservatory(); } - // TODO(bkonyi): remove when ready to serve DevTools from DDS. - if (debuggingOptions.enableDevTools) { + if (enableDevTools) { // The method below is guaranteed never to return a failing future. unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools( devToolsServerAddress: debuggingOptions.devToolsServerAddress, @@ -361,6 +362,7 @@ class HotRunner extends ResidentRunner { Future run({ Completer? connectionInfoCompleter, Completer? appStartedCompleter, + bool enableDevTools = false, String? route, }) async { await _calculateTargetPlatform(); @@ -468,6 +470,7 @@ class HotRunner extends ResidentRunner { return attach( connectionInfoCompleter: connectionInfoCompleter, appStartedCompleter: appStartedCompleter, + enableDevTools: enableDevTools, needsFullRestart: false, ); } @@ -787,11 +790,7 @@ class HotRunner extends ResidentRunner { if (!silent) { globals.printStatus('Restarted application in ${getElapsedAsMilliseconds(timer.elapsed)}.'); } - // TODO(bkonyi): remove when ready to serve DevTools from DDS. unawaited(residentDevtoolsHandler!.hotRestart(flutterDevices)); - // for (final FlutterDevice? device in flutterDevices) { - // unawaited(device?.handleHotRestart()); - // } return result; } final OperationResult result = await _hotReloadHelper( diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 8fa6f854291f..e4e474ab6e8e 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -489,7 +489,7 @@ abstract class FlutterCommand extends Command { defaultsTo: true, help: 'Enable (or disable, with "--no-$kEnableDevTools") the launching of the ' 'Flutter DevTools debugger and profiler. ' - 'If "--no-$kEnableDevTools" is specified, "--$kDevToolsServerAddress" is ignored.' + 'If specified, "--$kDevToolsServerAddress" is ignored.' ); argParser.addOption( kDevToolsServerAddress, diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart index 798e129794f2..50783f843510 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart @@ -414,7 +414,6 @@ class FlutterCommandRunner extends CommandRunner { throwToolExit('The "--machine" flag is only valid with the "--version" flag or the "analyze --suggestions" command.', exitCode: 2); } - // TODO(bkonyi): can this be removed and passed solely via DebuggingOptions? final bool shouldPrintDtdUri = topLevelResults[FlutterGlobalOptions.kPrintDtd] as bool? ?? false; DevtoolsLauncher.instance!.printDtdUri = shouldPrintDtdUri; diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart index 3cd32358cc4e..68648b352539 100644 --- a/packages/flutter_tools/lib/src/test/flutter_platform.dart +++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart @@ -6,6 +6,7 @@ import 'dart:async'; +import 'package:dds/dds.dart'; import 'package:meta/meta.dart'; import 'package:package_config/package_config.dart'; import 'package:stream_channel/stream_channel.dart'; @@ -69,6 +70,7 @@ FlutterPlatform installHook({ Device? integrationTestDevice, String? integrationTestUserIdentifier, TestTimeRecorder? testTimeRecorder, + UriConverter? uriConverter, TestCompilerNativeAssetsBuilder? nativeAssetsBuilder, BuildInfo? buildInfo, }) { @@ -100,6 +102,7 @@ FlutterPlatform installHook({ integrationTestDevice: integrationTestDevice, integrationTestUserIdentifier: integrationTestUserIdentifier, testTimeRecorder: testTimeRecorder, + uriConverter: uriConverter, nativeAssetsBuilder: nativeAssetsBuilder, buildInfo: buildInfo, ); @@ -306,6 +309,7 @@ class FlutterPlatform extends PlatformPlugin { this.integrationTestDevice, this.integrationTestUserIdentifier, this.testTimeRecorder, + this.uriConverter, this.nativeAssetsBuilder, this.buildInfo, }); @@ -327,6 +331,9 @@ class FlutterPlatform extends PlatformPlugin { final TestCompilerNativeAssetsBuilder? nativeAssetsBuilder; final BuildInfo? buildInfo; + // This can be used by internal projects that require custom logic for converting package: URIs to local paths. + final UriConverter? uriConverter; + /// The device to run the test on for Integration Tests. /// /// If this is null, the test will run as a regular test with the Flutter @@ -455,6 +462,7 @@ class FlutterPlatform extends PlatformPlugin { icudtlPath: icudtlPath, compileExpression: _compileExpressionService, fontConfigManager: _fontConfigManager, + uriConverter: uriConverter, ); } diff --git a/packages/flutter_tools/lib/src/test/flutter_tester_device.dart b/packages/flutter_tools/lib/src/test/flutter_tester_device.dart index 5e3f2a291b3d..e019556ee623 100644 --- a/packages/flutter_tools/lib/src/test/flutter_tester_device.dart +++ b/packages/flutter_tools/lib/src/test/flutter_tester_device.dart @@ -5,12 +5,12 @@ import 'dart:async'; import 'dart:io' as io; // flutter_ignore: dart_io_import; +import 'package:dds/dds.dart'; import 'package:meta/meta.dart'; import 'package:process/process.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:vm_service/vm_service.dart' as vm_service; -import '../base/dds.dart'; import '../base/file_system.dart'; import '../base/io.dart'; import '../base/logger.dart'; @@ -43,6 +43,7 @@ class FlutterTesterTestDevice extends TestDevice { required this.icudtlPath, required this.compileExpression, required this.fontConfigManager, + required this.uriConverter, }) : assert(!debuggingOptions.startPaused || enableVmService), _gotProcessVmServiceUri = enableVmService ? Completer() : (Completer()..complete()); @@ -63,8 +64,8 @@ class FlutterTesterTestDevice extends TestDevice { final String? icudtlPath; final CompileExpression? compileExpression; final FontConfigManager fontConfigManager; + final UriConverter? uriConverter; - late final DartDevelopmentService _ddsLauncher = DartDevelopmentService(logger: logger); final Completer _gotProcessVmServiceUri; final Completer _exitCode = Completer(); @@ -169,20 +170,16 @@ class FlutterTesterTestDevice extends TestDevice { debuggingOptions.hostVmServicePort == detectedUri.port); Uri? forwardingUri; - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // Uri? devToolsUri; + DartDevelopmentService? dds; if (debuggingOptions.enableDds) { logger.printTrace('test $id: Starting Dart Development Service'); - - await _ddsLauncher.startDartDevelopmentServiceFromDebuggingOptions( + dds = await startDds( detectedUri, - debuggingOptions: debuggingOptions, + uriConverter: uriConverter, ); - forwardingUri = _ddsLauncher.uri; - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // devToolsUri = _ddsLauncher.devToolsUri; - logger.printTrace('test $id: Dart Development Service started at $forwardingUri, forwarding to VM service at $detectedUri.'); + forwardingUri = dds.uri; + logger.printTrace('test $id: Dart Development Service started at ${dds.uri}, forwarding to VM service at ${dds.remoteVmServiceUri}.'); } else { forwardingUri = detectedUri; } @@ -204,11 +201,7 @@ class FlutterTesterTestDevice extends TestDevice { if (debuggingOptions.startPaused && !machine!) { logger.printStatus('The Dart VM service is listening on $forwardingUri'); - await _startDevTools(forwardingUri, _ddsLauncher); - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // if (devToolsUri != null) { - // logger.printStatus('The Flutter DevTools debugger and profiler is available at: $devToolsUri'); - // } + await _startDevTools(forwardingUri, dds); logger.printStatus(''); logger.printStatus('The test process has been started. Set any relevant breakpoints and then resume the test in the debugger.'); } @@ -255,6 +248,28 @@ class FlutterTesterTestDevice extends TestDevice { throw TestDeviceException(_getExitCodeMessage(exitCode), StackTrace.current); } + Uri get _ddsServiceUri { + return Uri( + scheme: 'http', + host: (host!.type == InternetAddressType.IPv6 ? + InternetAddress.loopbackIPv6 : + InternetAddress.loopbackIPv4 + ).host, + port: debuggingOptions.hostVmServicePort ?? 0, + ); + } + + @visibleForTesting + @protected + Future startDds(Uri uri, {UriConverter? uriConverter}) { + return DartDevelopmentService.startDartDevelopmentService( + uri, + serviceUri: _ddsServiceUri, + enableAuthCodes: !debuggingOptions.disableServiceAuthCodes, + ipv6: host!.type == InternetAddressType.IPv6, + uriConverter: uriConverter, + ); + } @visibleForTesting @protected @@ -270,7 +285,6 @@ class FlutterTesterTestDevice extends TestDevice { ); } - // TODO(bkonyi): remove when ready to serve DevTools from DDS. Future _startDevTools(Uri forwardingUri, DartDevelopmentService? dds) async { _devToolsLauncher = DevtoolsLauncher.instance; logger.printTrace('test $id: Serving DevTools...'); @@ -283,6 +297,10 @@ class FlutterTesterTestDevice extends TestDevice { await _devToolsLauncher?.ready; logger.printTrace('test $id: DevTools is being served at ${devToolsServerAddress.uri}'); + // Notify the DDS instance that there's a DevTools instance available so it can correctly + // redirect DevTools related requests. + dds?.setExternalDevToolsUri(devToolsServerAddress.uri!); + final Uri devToolsUri = devToolsServerAddress.uri!.replace( // Use query instead of queryParameters to avoid unnecessary encoding. query: 'uri=$forwardingUri', diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart index 7bbadbb9185d..fa0aff896942 100644 --- a/packages/flutter_tools/lib/src/test/runner.dart +++ b/packages/flutter_tools/lib/src/test/runner.dart @@ -40,6 +40,7 @@ abstract class FlutterTestRunner { String? tags, String? excludeTags, bool enableVmService = false, + bool ipv6 = false, bool machine = false, String? precompiledDillPath, Map? precompiledDillFiles, @@ -107,6 +108,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner { String? tags, String? excludeTags, bool enableVmService = false, + bool ipv6 = false, bool machine = false, String? precompiledDillPath, Map? precompiledDillFiles, @@ -237,7 +239,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner { ..addAll(testFiles.map((Uri uri) => uri.toString())); final InternetAddressType serverType = - debuggingOptions.ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4; + ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4; final loader.FlutterPlatform platform = loader.installHook( testWrapper: testWrapper, diff --git a/packages/flutter_tools/lib/src/tester/flutter_tester.dart b/packages/flutter_tools/lib/src/tester/flutter_tester.dart index 40d83e79abe9..8c895e4aed56 100644 --- a/packages/flutter_tools/lib/src/tester/flutter_tester.dart +++ b/packages/flutter_tools/lib/src/tester/flutter_tester.dart @@ -46,7 +46,7 @@ class FlutterTesterDevice extends Device { FlutterTesterDevice(super.id, { required ProcessManager processManager, required FlutterVersion flutterVersion, - required super.logger, + required Logger logger, required FileSystem fileSystem, required Artifacts artifacts, }) : _processManager = processManager, @@ -135,6 +135,7 @@ class FlutterTesterDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { final BuildInfo buildInfo = debuggingOptions.buildInfo; @@ -192,7 +193,7 @@ class FlutterTesterDevice extends Device { getLogReader(), hostPort: debuggingOptions.hostVmServicePort, devicePort: debuggingOptions.deviceVmServicePort, - ipv6: debuggingOptions.ipv6, + ipv6: ipv6, logger: _logger, ); _logReader.initializeProcess(_process!); diff --git a/packages/flutter_tools/lib/src/web/web_device.dart b/packages/flutter_tools/lib/src/web/web_device.dart index ef729796b484..8969fa50ea8d 100644 --- a/packages/flutter_tools/lib/src/web/web_device.dart +++ b/packages/flutter_tools/lib/src/web/web_device.dart @@ -38,7 +38,7 @@ abstract class ChromiumDevice extends Device { required String name, required this.chromeLauncher, required FileSystem fileSystem, - required super.logger, + required Logger logger, }) : _fileSystem = fileSystem, _logger = logger, super( @@ -124,6 +124,7 @@ abstract class ChromiumDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { // See [ResidentWebRunner.run] in flutter_tools/lib/src/resident_web_runner.dart @@ -381,7 +382,7 @@ String parseVersionForWindows(String input) { /// A special device type to allow serving for arbitrary browsers. class WebServerDevice extends Device { WebServerDevice({ - required super.logger, + required Logger logger, }) : _logger = logger, super( 'web-server', @@ -459,6 +460,7 @@ class WebServerDevice extends Device { required DebuggingOptions debuggingOptions, Map platformArgs = const {}, bool prebuiltApplication = false, + bool ipv6 = false, String? userIdentifier, }) async { final String? url = platformArgs['uri'] as String?; diff --git a/packages/flutter_tools/lib/src/web/web_runner.dart b/packages/flutter_tools/lib/src/web/web_runner.dart index af7424a3b71e..475a3ef5fc60 100644 --- a/packages/flutter_tools/lib/src/web/web_runner.dart +++ b/packages/flutter_tools/lib/src/web/web_runner.dart @@ -26,6 +26,7 @@ abstract class WebRunnerFactory { String? target, required bool stayResident, required FlutterProject flutterProject, + required bool? ipv6, required DebuggingOptions debuggingOptions, UrlTunneller? urlTunneller, required Logger logger, diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart index 33e241492264..dfd23e70cde2 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart @@ -73,7 +73,7 @@ void main() { artifacts = Artifacts.test(fileSystem: testFileSystem); stdio = FakeStdio(); terminal = FakeTerminal(); - signals = FakeSignals(); + signals = Signals.test(); processInfo = FakeProcessInfo(); testDeviceManager = TestDeviceManager(logger: logger); }); @@ -802,13 +802,6 @@ void main() { ProcessManager: () => FakeProcessManager.any(), Logger: () => logger, DeviceManager: () => testDeviceManager, - MDnsVmServiceDiscovery: () => MDnsVmServiceDiscovery( - mdnsClient: FakeMDnsClient([], >{}), - preliminaryMDnsClient: FakeMDnsClient([], >{}), - logger: logger, - flutterUsage: TestUsage(), - analytics: const NoOpAnalytics(), - ), }); testUsingContext('exits when vm-service-port is specified and debug-port is not', () async { @@ -1401,14 +1394,11 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService @override Future startDartDevelopmentService( Uri vmServiceUri, { - int? ddsPort, - FlutterDevice? device, + required Logger logger, + int? hostPort, bool? ipv6, bool? disableServiceAuthCodes, - bool enableDevTools = false, bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async {} @override diff --git a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart index 42ef168caacd..d930dfe674ab 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart @@ -695,22 +695,17 @@ void main() { 'deviceId': 'device', 'disableServiceAuthCodes': false, 'vmServiceUri': 'http://fake_uri/auth_code', - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // 'enableDevTools': true, }, })); final Stream broadcastOutput = daemonStreams.outputs.stream.asBroadcastStream(); final DaemonMessage startResponse = await broadcastOutput.firstWhere(_notEvent); expect(startResponse.data['id'], 0); expect(startResponse.data['error'], isNull); - final Map? result = startResponse.data['result'] as Map?; - final String? ddsUri = result!['ddsUri'] as String?; + final String? ddsUri = startResponse.data['result'] as String?; expect(ddsUri, fakeDdsUri.toString()); expect(device.dds.startCalled, true); expect(device.dds.startDisableServiceAuthCodes, false); expect(device.dds.startVMServiceUri, Uri.parse('http://fake_uri/auth_code')); - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // expect(device.dds.enableDevTools, true); // dds.done event should be sent to the client. ddsDoneCompleter.complete(); @@ -1241,8 +1236,6 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService bool? startDisableServiceAuthCodes; bool shutdownCalled = false; - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // bool enableDevTools = false; @override late Future done; @@ -1250,32 +1243,18 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService @override Uri? uri; - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - /* - @override - Uri? devToolsUri; - - @override - Uri? dtdUri; - */ - @override Future startDartDevelopmentService( Uri vmServiceUri, { - int? ddsPort, - FlutterDevice? device, + required Logger logger, + int? hostPort, bool? ipv6, bool? disableServiceAuthCodes, - bool enableDevTools = false, bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async { startCalled = true; startVMServiceUri = vmServiceUri; startDisableServiceAuthCodes = disableServiceAuthCodes; - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // this.enableDevTools = enableDevTools; } @override diff --git a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart index e0517d855cb6..50ffec8db54f 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart @@ -640,7 +640,7 @@ class NeverEndingDriverService extends Fake implements DriverService { final void Function() callback; @override - Future reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions) async { } + Future reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async { } @override Future startTest( @@ -670,7 +670,7 @@ class FailingFakeFlutterDriverFactory extends Fake implements FlutterDriverFacto class FailingFakeDriverService extends Fake implements DriverService { @override - Future reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions) async { } + Future reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async { } @override Future startTest( diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart index b9550ecd97c1..509ea1efc705 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart @@ -1544,13 +1544,16 @@ class CapturingAppDomain extends AppDomain { String? projectRootPath, String? packagesFilePath, String? dillOutputPath, + bool ipv6 = false, String? isolateFilter, bool machine = true, String? userIdentifier, - required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder, + bool enableDevTools = true, + String? flavor, + HotRunnerNativeAssetsBuilder? nativeAssetsBuilder, }) async { this.userIdentifier = userIdentifier; - enableDevTools = options.enableDevTools; + this.enableDevTools = enableDevTools; throwToolExit(''); } } diff --git a/packages/flutter_tools/test/general.shard/cold_test.dart b/packages/flutter_tools/test/general.shard/cold_test.dart index 4ef1666aed44..e16015ee4cba 100644 --- a/packages/flutter_tools/test/general.shard/cold_test.dart +++ b/packages/flutter_tools/test/general.shard/cold_test.dart @@ -213,9 +213,13 @@ class TestFlutterDevice extends FlutterDevice { GetSkSLMethod? getSkSLMethod, FlutterProject? flutterProject, PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, - required DebuggingOptions debuggingOptions, + bool enableDds = true, + bool cacheStartupProfile = false, + bool disableServiceAuthCodes = false, int? hostVmServicePort, - required bool allowExistingDdsInstance, + int? ddsPort, + bool? ipv6 = false, + bool allowExistingDdsInstance = false, }) async { throw exception; } diff --git a/packages/flutter_tools/test/general.shard/device_test.dart b/packages/flutter_tools/test/general.shard/device_test.dart index 8f7bf361937d..c1a62a17cac1 100644 --- a/packages/flutter_tools/test/general.shard/device_test.dart +++ b/packages/flutter_tools/test/general.shard/device_test.dart @@ -932,13 +932,13 @@ void main() { testWithoutContext('Get launch arguments for physical device with iPv6 network connection', () { final DebuggingOptions original = DebuggingOptions.enabled( BuildInfo.debug, - ipv6: true, ); final List launchArguments = original.getIOSLaunchArguments( EnvironmentType.physical, null, {}, + ipv6: true, interfaceType: DeviceConnectionInterface.wireless, ); 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 50e560c16aa5..2952af5378dc 100644 --- a/packages/flutter_tools/test/general.shard/devtools_launcher_test.dart +++ b/packages/flutter_tools/test/general.shard/devtools_launcher_test.dart @@ -33,8 +33,6 @@ void main() { 'Artifact.engineDartBinary', 'devtools', '--no-launch-browser', - // TODO(bkonyi): does this need to be removed? - // '--print-dtd', ], stdout: 'Serving DevTools at http://127.0.0.1:9100.\n', completer: completer, @@ -51,7 +49,6 @@ void main() { expect(launcher.printDtdUri, false); }); - // TODO(bkonyi): this test can be removed when DevTools is served from DDS. testWithoutContext('DevtoolsLauncher saves the Dart Tooling Daemon uri', () async { final (BufferLogger logger, Artifacts artifacts) = getTestState(); final Completer completer = Completer(); @@ -98,7 +95,6 @@ Serving DevTools at http://127.0.0.1:9100. 'Artifact.engineDartBinary', 'devtools', '--no-launch-browser', - // '--print-dtd', ], stdout: 'Serving DevTools at http://127.0.0.1:9100.\n', completer: completer, @@ -124,7 +120,6 @@ Serving DevTools at http://127.0.0.1:9100. 'Artifact.engineDartBinary', 'devtools', '--no-launch-browser', - // '--print-dtd', '--vm-uri=localhost:8181/abcdefg', '--profile-memory=foo', ], @@ -156,7 +151,6 @@ Serving DevTools at http://127.0.0.1:9100. 'Artifact.engineDartBinary', 'devtools', '--no-launch-browser', - // '--print-dtd', '--vm-uri=http://127.0.0.1:1234/abcdefg', ], exception: ProcessException('pub', []), @@ -182,7 +176,6 @@ Serving DevTools at http://127.0.0.1:9100. 'Artifact.engineDartBinary', 'devtools', '--no-launch-browser', - // '--print-dtd', ], stdout: 'Serving DevTools at http://127.0.0.1:9100.\n', completer: completer, diff --git a/packages/flutter_tools/test/general.shard/drive/drive_service_test.dart b/packages/flutter_tools/test/general.shard/drive/drive_service_test.dart index a461db64318f..c2c114cbb92f 100644 --- a/packages/flutter_tools/test/general.shard/drive/drive_service_test.dart +++ b/packages/flutter_tools/test/general.shard/drive/drive_service_test.dart @@ -93,7 +93,7 @@ void main() { final Device device = FakeDevice(LaunchResult.failed()); expect( - () => driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)), + () => driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true), throwsToolExit(message: 'Application failed to start. Will not run test. Quitting.'), ); }); @@ -118,7 +118,7 @@ void main() { ))..failOnce = true; await expectLater( - () async => driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)), + () async => driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true), returnsNormally, ); }); @@ -142,7 +142,7 @@ void main() { vmServiceUri: Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'), )); - await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)); + await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true); final int testResult = await driverService.startTest( 'foo.test', ['--enable-experiment=non-nullable'], @@ -173,7 +173,7 @@ void main() { vmServiceUri: Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'), )); - await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)); + await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true); final int testResult = await driverService.startTest( 'foo.test', ['--enable-experiment=non-nullable'], @@ -205,7 +205,7 @@ void main() { vmServiceUri: Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'), )); - await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)); + await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true); final int testResult = await driverService.startTest( 'foo.test', ['--enable-experiment=non-nullable'], @@ -237,7 +237,7 @@ void main() { final FakeDartDevelopmentService dds = device.dds as FakeDartDevelopmentService; expect(dds.started, false); - await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, enableDds: false, ipv6: true)); + await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, enableDds: false), true); expect(dds.started, false); final int testResult = await driverService.startTest( @@ -261,7 +261,7 @@ void main() { vmServiceUri: Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'), )); - await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)); + await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true); await driverService.stop(); expect(device.didStopApp, true); @@ -293,7 +293,7 @@ void main() { vmServiceUri: Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'), )); - await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)); + await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true); await driverService.stop(writeSkslOnExit: fileSystem.file('out.json')); expect(device.didStopApp, true); @@ -327,6 +327,7 @@ void main() { Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'), device, DebuggingOptions.enabled(BuildInfo.debug), + false, ); await driverService.stop(); }); @@ -350,6 +351,7 @@ void main() { Uri.parse('ws://127.0.0.1:63426/1UasC_ihpXY=/ws/'), device, DebuggingOptions.enabled(BuildInfo.debug), + false, ); await driverService.stop(); }); @@ -373,6 +375,7 @@ void main() { Uri.parse('ws://127.0.0.1:63426/1UasC_ihpXY=/ws'), device, DebuggingOptions.enabled(BuildInfo.debug), + false, ); await driverService.stop(); }); @@ -396,6 +399,7 @@ void main() { Uri.parse('ws://127.0.0.1:63426/wsasC_ihpXY=/ws'), device, DebuggingOptions.enabled(BuildInfo.debug), + false, ); await driverService.stop(); }); @@ -412,6 +416,7 @@ void main() { Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'), device, DebuggingOptions.enabled(BuildInfo.debug), + false, ); await driverService.stop(); }); @@ -535,9 +540,7 @@ class FakeDevice extends Fake implements Device { } } -class FakeDartDevelopmentService extends Fake - with DartDevelopmentServiceLocalOperationsMixin - implements DartDevelopmentService { +class FakeDartDevelopmentService extends Fake implements DartDevelopmentService { bool started = false; bool disposed = false; @@ -547,14 +550,11 @@ class FakeDartDevelopmentService extends Fake @override Future startDartDevelopmentService( Uri vmServiceUri, { - FlutterDevice? device, - int? ddsPort, + required Logger logger, + int? hostPort, bool? ipv6, bool? disableServiceAuthCodes, - bool enableDevTools = false, bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async { started = true; } diff --git a/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart b/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart index 8854e2c7a628..47fd1645b723 100644 --- a/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart +++ b/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart @@ -248,7 +248,7 @@ void main() { testUsingContext('WebDriverService starts and stops an app', () async { final WebDriverService service = setUpDriverService(); final FakeDevice device = FakeDevice(); - await service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)); + await service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true); await service.stop(); expect(FakeResidentRunner.instance.callLog, [ 'run', @@ -263,7 +263,7 @@ void main() { final WebDriverService service = setUpDriverService(); final FakeDevice device = FakeDevice(); const String testUrl = 'http://localhost:1234/test'; - await service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, webLaunchUrl: testUrl, ipv6: true)); + await service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, webLaunchUrl: testUrl), true); await service.stop(); expect(service.webUri, Uri.parse(testUrl)); }, overrides: { @@ -275,7 +275,7 @@ void main() { final FakeDevice device = FakeDevice(); const String invalidTestUrl = '::INVALID_URL::'; await expectLater( - service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, webLaunchUrl: invalidTestUrl, ipv6: true)), + service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, webLaunchUrl: invalidTestUrl), true), throwsA(isA()), ); }, overrides: { @@ -286,7 +286,7 @@ void main() { final WebDriverService service = setUpDriverService(); final Device device = FakeDevice(); await expectLater( - service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)), + service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true), throwsA('This is a test error'), ); }, overrides: { diff --git a/packages/flutter_tools/test/general.shard/flutter_platform_test.dart b/packages/flutter_tools/test/general.shard/flutter_platform_test.dart index ed4fa844a210..60a6b1610fba 100644 --- a/packages/flutter_tools/test/general.shard/flutter_platform_test.dart +++ b/packages/flutter_tools/test/general.shard/flutter_platform_test.dart @@ -102,6 +102,7 @@ void main() { platformPluginRegistration: (FlutterPlatform platform) { capturedPlatform = platform; }, + uriConverter: (String input) => '$input/test', ); expect(identical(capturedPlatform, flutterPlatform), equals(true)); @@ -118,6 +119,7 @@ void main() { expect(flutterPlatform.updateGoldens, equals(true)); expect(flutterPlatform.testAssetDirectory, '/build/test'); expect(flutterPlatform.icudtlPath, equals('ghi')); + expect(flutterPlatform.uriConverter?.call('hello'), 'hello/test'); }); }); diff --git a/packages/flutter_tools/test/general.shard/flutter_tester_device_test.dart b/packages/flutter_tools/test/general.shard/flutter_tester_device_test.dart index 7a52bf22af04..adf6c4403767 100644 --- a/packages/flutter_tools/test/general.shard/flutter_tester_device_test.dart +++ b/packages/flutter_tools/test/general.shard/flutter_tester_device_test.dart @@ -4,8 +4,8 @@ import 'dart:async'; +import 'package:dds/dds.dart'; import 'package:file/memory.dart'; -import 'package:flutter_tools/src/base/dds.dart'; 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'; @@ -48,6 +48,7 @@ void main() { processManager: processManager, enableVmService: enableVmService, dartEntrypointArgs: dartEntrypointArgs, + uriConverter: (String input) => '$input/converted', enableImpeller: enableImpeller, ); @@ -197,7 +198,6 @@ void main() { }); group('DDS', () { - late DDSLauncherCallback originalDdsLauncher; setUp(() { processManager = FakeProcessManager.list([ const FakeCommand( @@ -221,30 +221,26 @@ void main() { ), ]); device = createDevice(enableVmService: true); - originalDdsLauncher = ddsLauncherCallback; - ddsLauncherCallback = (Uri remoteVmServiceUri, { - required bool enableAuthCodes, - required bool ipv6, - required bool enableDevTools, - required List cachedUserTags, - Uri? serviceUri, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, - }) async { - return (process: null, serviceUri: Uri.parse('http://localhost:1234'), devToolsUri: null, dtdUri: null); - }; }); - tearDown(() { - ddsLauncherCallback = originalDdsLauncher; + testUsingContext('skips setting VM Service port and uses the input port for DDS instead', () async { + await device.start('example.dill'); + await device.vmServiceUri; + + final Uri uri = await (device as TestFlutterTesterDevice).ddsServiceUriFuture(); + expect(uri.port, 1234); }); - testUsingContext('skips setting VM Service port and uses the input port for DDS instead', () async { + testUsingContext('sets up UriConverter from context', () async { await device.start('example.dill'); await device.vmServiceUri; - final Uri? uri = await (device as TestFlutterTesterDevice).vmServiceUri; - expect(uri!.port, 1234); + final FakeDartDevelopmentService dds = (device as TestFlutterTesterDevice).dds + as FakeDartDevelopmentService; + final String? result = dds + .uriConverter + ?.call('test'); + expect(result, 'test/converted'); }); }); } @@ -259,6 +255,7 @@ class TestFlutterTesterDevice extends FlutterTesterTestDevice { required super.processManager, required super.enableVmService, required List dartEntrypointArgs, + required UriConverter uriConverter, required bool enableImpeller, }) : super( id: 999, @@ -282,7 +279,27 @@ class TestFlutterTesterDevice extends FlutterTesterTestDevice { icudtlPath: null, compileExpression: null, fontConfigManager: FontConfigManager(), + uriConverter: uriConverter, ); + late DartDevelopmentService dds; + + final Completer _ddsServiceUriCompleter = Completer(); + + Future ddsServiceUriFuture() => _ddsServiceUriCompleter.future; + + @override + Future startDds( + Uri uri, { + UriConverter? uriConverter, + }) async { + _ddsServiceUriCompleter.complete(uri); + dds = FakeDartDevelopmentService( + Uri.parse('http://localhost:${debuggingOptions.hostVmServicePort}'), + Uri.parse('http://localhost:8080'), + uriConverter: uriConverter, + ); + return dds; + } @override Future connectToVmServiceImpl( @@ -302,6 +319,18 @@ class TestFlutterTesterDevice extends FlutterTesterTestDevice { Future> get remoteChannel async => StreamChannelController().foreign; } +class FakeDartDevelopmentService extends Fake implements DartDevelopmentService { + FakeDartDevelopmentService(this.uri, this.original, {this.uriConverter}); + + final Uri original; + final UriConverter? uriConverter; + + @override + final Uri uri; + + @override + Uri get remoteVmServiceUri => original; +} class FakeHttpServer extends Fake implements HttpServer { @override int get port => 0; diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart index 18e1a03feee9..e9e24d7b4d59 100644 --- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart +++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart @@ -9,7 +9,6 @@ import 'package:file/memory.dart'; import 'package:flutter_tools/src/artifacts.dart'; 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/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/build_info.dart'; @@ -39,7 +38,6 @@ void main() { late FakeProcessManager fakeSuccessfulProcessManager; late FakeProcessManager fakeFailedProcessManagerForHostAddress; late File sshConfig; - final Logger logger = FakeLogger(); setUp(() { memoryFileSystem = MemoryFileSystem.test(); @@ -116,7 +114,7 @@ void main() { required BuildMode mode, }) async { const String appName = 'app_name'; - final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123', logger: logger); + final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123'); globals.fs.directory('fuchsia').createSync(recursive: true); final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync(); pubspecFile.writeAsStringSync('name: $appName'); @@ -188,7 +186,7 @@ void main() { 'start and stop prebuilt in release mode fails without session', () async { const String appName = 'app_name'; - final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123', logger: logger); + final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123'); globals.fs.directory('fuchsia').createSync(recursive: true); final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync(); pubspecFile.writeAsStringSync('name: $appName'); @@ -218,7 +216,7 @@ void main() { testUsingContext('start and stop prebuilt in release mode with session', () async { const String appName = 'app_name'; - final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123', logger: logger); + final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123'); globals.fs.directory('fuchsia').createSync(recursive: true); final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync(); pubspecFile.writeAsStringSync('name: $appName'); @@ -411,7 +409,7 @@ void main() { }); testUsingContext('fail when cant get host address', () async { - expect(() async => FuchsiaDeviceWithFakeDiscovery('123', logger: logger).hostAddress, + expect(() async => FuchsiaDeviceWithFakeDiscovery('123').hostAddress, throwsToolExit(message: 'Failed to get local address, aborting.')); }, overrides: { Artifacts: () => artifacts, @@ -481,7 +479,7 @@ Process _createFakeProcess({ } class FuchsiaDeviceWithFakeDiscovery extends FuchsiaDevice { - FuchsiaDeviceWithFakeDiscovery(super.id, {super.name = '', required super.logger}); + FuchsiaDeviceWithFakeDiscovery(super.id, {super.name = ''}); @override FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol( diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart index 90a849b664e9..b68c2a4abeff 100644 --- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart +++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart @@ -26,7 +26,6 @@ import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart'; import 'package:flutter_tools/src/fuchsia/fuchsia_workflow.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/project.dart'; -import 'package:flutter_tools/src/resident_runner.dart'; import 'package:flutter_tools/src/vmservice.dart'; import 'package:test/fake.dart'; import 'package:vm_service/vm_service.dart' as vm_service; @@ -59,7 +58,6 @@ void main() { late MemoryFileSystem memoryFileSystem; late File sshConfig; late FakeProcessManager processManager; - final Logger logger = FakeLogger(); setUp(() { memoryFileSystem = MemoryFileSystem.test(); @@ -70,7 +68,7 @@ void main() { testWithoutContext('stores the requested id and name', () { const String deviceId = 'e80::0000:a00a:f00f:2002/3'; const String name = 'halfbaked'; - final FuchsiaDevice device = FuchsiaDevice(deviceId, name: name, logger: logger); + final FuchsiaDevice device = FuchsiaDevice(deviceId, name: name); expect(device.id, deviceId); expect(device.name, name); @@ -79,7 +77,7 @@ void main() { testWithoutContext('supports all runtime modes besides jitRelease', () { const String deviceId = 'e80::0000:a00a:f00f:2002/3'; const String name = 'halfbaked'; - final FuchsiaDevice device = FuchsiaDevice(deviceId, name: name, logger: logger); + final FuchsiaDevice device = FuchsiaDevice(deviceId, name: name); expect(device.supportsRuntimeMode(BuildMode.debug), true); expect(device.supportsRuntimeMode(BuildMode.profile), true); @@ -159,7 +157,7 @@ void main() { testUsingContext('disposing device disposes the portForwarder', () async { final FakePortForwarder portForwarder = FakePortForwarder(); - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); device.portForwarder = portForwarder; await device.dispose(); @@ -167,7 +165,7 @@ void main() { }); testWithoutContext('default capabilities', () async { - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); final FlutterProject project = FlutterProject.fromDirectoryTest(memoryFileSystem.currentDirectory); memoryFileSystem.directory('fuchsia').createSync(recursive: true); @@ -180,13 +178,13 @@ void main() { }); test('is ephemeral', () { - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(device.ephemeral, true); }); testWithoutContext('supported for project', () async { - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); final FlutterProject project = FlutterProject.fromDirectoryTest(memoryFileSystem.currentDirectory); memoryFileSystem.directory('fuchsia').createSync(recursive: true); @@ -196,7 +194,7 @@ void main() { }); testWithoutContext('not supported for project', () async { - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); final FlutterProject project = FlutterProject.fromDirectoryTest(memoryFileSystem.currentDirectory); memoryFileSystem.file('pubspec.yaml').createSync(); @@ -206,7 +204,7 @@ void main() { testUsingContext('targetPlatform does not throw when sshConfig is missing', () async { - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64); }, overrides: { @@ -221,7 +219,7 @@ void main() { stdout: 'aarch64', )); - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64); }, overrides: { FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), @@ -235,7 +233,7 @@ void main() { stdout: 'x86_64', )); - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(await device.targetPlatform, TargetPlatform.fuchsia_x64); }, overrides: { FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), @@ -256,7 +254,7 @@ void main() { 'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22', )); - final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'device'); expect(await device.hostAddress, 'fe80::8c6c:2fff:fe3d:c5e1%25ethp0003'); }, overrides: { FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), @@ -277,7 +275,7 @@ void main() { exitCode: 1, )); - final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'device'); await expectLater(() => device.hostAddress, throwsToolExit()); }, overrides: { FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), @@ -297,7 +295,7 @@ void main() { ], )); - final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'device'); expect(() async => device.hostAddress, throwsToolExit()); }, overrides: { FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), @@ -309,7 +307,6 @@ void main() { group('displays friendly error when', () { late File artifactFile; late FakeProcessManager processManager; - final Logger logger = FakeLogger(); setUp(() { processManager = FakeProcessManager.empty(); @@ -326,7 +323,7 @@ void main() { 'find /hub -name vmservice-port' ], )); - final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'device'); await expectLater( device.servicePorts, @@ -355,7 +352,6 @@ void main() { late FakeProcessManager processManager; late File ffx; late File sshConfig; - final Logger logger = FakeLogger(); setUp(() { processManager = FakeProcessManager.empty(); @@ -378,7 +374,7 @@ void main() { stdout: exampleUtcLogs, completer: lock, )); - final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester'); final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app')); final List logLines = []; @@ -415,7 +411,7 @@ void main() { stdout: exampleUtcLogs, completer: lock, )); - final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester'); final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app')); final List logLines = []; @@ -450,7 +446,7 @@ void main() { stdout: exampleUtcLogs, completer: lock, )); - final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester'); final DeviceLogReader reader = device.getLogReader(); final List logLines = []; reader.logLines.listen((String line) { @@ -479,14 +475,13 @@ void main() { group('screenshot', () { late FakeProcessManager processManager; - final Logger logger = FakeLogger(); setUp(() { processManager = FakeProcessManager.empty(); }); testUsingContext('is supported on posix platforms', () { - final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester'); expect(device.supportsScreenshot, true); }, overrides: { Platform: () => FakePlatform(), @@ -494,7 +489,7 @@ void main() { }); testUsingContext('is not supported on Windows', () { - final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester'); expect(device.supportsScreenshot, false); }, overrides: { @@ -505,7 +500,7 @@ void main() { }); test("takeScreenshot throws if file isn't .ppm", () async { - final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester'); await expectLater( () => device.takeScreenshot(globals.fs.file('file.invalid')), throwsA(isA().having( @@ -523,7 +518,7 @@ void main() { '0.0.0.0', 'screencap > /tmp/screenshot.ppm', ], exitCode: 1, stderr: '')); - final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester'); await expectLater( () => device.takeScreenshot(globals.fs.file('file.ppm')), @@ -545,7 +540,7 @@ void main() { }); testUsingContext('takeScreenshot throws if scp failed', () async { - final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester'); processManager.addCommand(const FakeCommand( command: [ 'ssh', @@ -598,7 +593,7 @@ void main() { testUsingContext( "takeScreenshot prints error if can't delete file from device", () async { - final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester'); processManager.addCommand(const FakeCommand( command: [ 'ssh', @@ -647,7 +642,7 @@ void main() { }, testOn: 'posix'); testUsingContext('takeScreenshot returns', () async { - final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester'); processManager.addCommand(const FakeCommand( command: [ 'ssh', @@ -693,7 +688,6 @@ void main() { group('portForwarder', () { late FakeProcessManager processManager; late File sshConfig; - final Logger logger = FakeLogger(); setUp(() { processManager = FakeProcessManager.empty(); @@ -703,7 +697,7 @@ void main() { testUsingContext( '`unforward` prints stdout and stderr if ssh command failed', () async { - final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester'); processManager.addCommand(const FakeCommand( command: [ 'ssh', @@ -867,7 +861,6 @@ void main() { group('sdkNameAndVersion: ', () { late File sshConfig; late FakeProcessManager processManager; - final Logger logger = FakeLogger(); setUp(() { sshConfig = MemoryFileSystem.test().file('ssh_config') @@ -876,7 +869,7 @@ void main() { }); testUsingContext('does not throw on non-existent ssh config', () async { - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(await device.sdkNameAndVersion, equals('Fuchsia')); }, overrides: { @@ -894,7 +887,7 @@ void main() { '123', 'cat /pkgfs/packages/build-info/0/data/version' ], stdout: 'version')); - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(await device.sdkNameAndVersion, equals('Fuchsia version')); }, overrides: { @@ -914,7 +907,7 @@ void main() { ], exitCode: 1, )); - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(await device.sdkNameAndVersion, equals('Fuchsia')); }, overrides: { @@ -934,7 +927,7 @@ void main() { 'cat /pkgfs/packages/build-info/0/data/version' ], )); - final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger); + final FuchsiaDevice device = FuchsiaDevice('123', name: 'device'); expect(await device.sdkNameAndVersion, equals('Fuchsia')); }, overrides: { @@ -1048,14 +1041,11 @@ class FakeDartDevelopmentService extends Fake @override Future startDartDevelopmentService( Uri vmServiceUri, { - FlutterDevice? device, - int? ddsPort, + required Logger logger, + int? hostPort, bool? ipv6, bool? disableServiceAuthCodes, bool cacheStartupProfile = false, - bool enableDevTools = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async {} @override diff --git a/packages/flutter_tools/test/general.shard/hot_shared.dart b/packages/flutter_tools/test/general.shard/hot_shared.dart index b0bdfe8e0003..30d2c5fc9b29 100644 --- a/packages/flutter_tools/test/general.shard/hot_shared.dart +++ b/packages/flutter_tools/test/general.shard/hot_shared.dart @@ -128,10 +128,6 @@ class FakeFlutterDevice extends Fake implements FlutterDevice { required PackageConfig packageConfig, }) => updateDevFSReportCallback(); - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // @override - // Future handleHotRestart() async {} - @override TargetPlatform? get targetPlatform => device._targetPlatform; } @@ -154,10 +150,12 @@ class TestFlutterDevice extends FlutterDevice { GetSkSLMethod? getSkSLMethod, FlutterProject? flutterProject, PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, - required DebuggingOptions debuggingOptions, - int? hostVmServicePort, + bool disableServiceAuthCodes = false, + bool enableDds = true, + bool cacheStartupProfile = false, bool? ipv6 = false, - bool enableDevTools = false, + int? hostVmServicePort, + int? ddsPort, bool allowExistingDdsInstance = false, }) async { throw exception; diff --git a/packages/flutter_tools/test/general.shard/hot_test.dart b/packages/flutter_tools/test/general.shard/hot_test.dart index 469f6dc97461..35f06af00faf 100644 --- a/packages/flutter_tools/test/general.shard/hot_test.dart +++ b/packages/flutter_tools/test/general.shard/hot_test.dart @@ -137,7 +137,8 @@ void main() { ..writeAsStringSync('\n'); final FakeDevice device = FakeDevice(); final List devices = [ - FakeFlutterDevice(device), + FlutterDevice(device, generator: residentCompiler, buildInfo: BuildInfo.debug, developmentShaderCompiler: const FakeShaderCompiler()) + ..devFS = FakeDevFs(), ]; final OperationResult result = await HotRunner( devices, @@ -145,6 +146,7 @@ void main() { target: 'main.dart', devtoolsHandler: createNoOpHandler, analytics: fakeAnalytics, + ).restart(fullRestart: true); expect(result.isOk, false); expect(result.message, 'setupHotRestart failed'); diff --git a/packages/flutter_tools/test/general.shard/ios/simulators_test.dart b/packages/flutter_tools/test/general.shard/ios/simulators_test.dart index 26d82f81fdc6..1a9d5eec3fd3 100644 --- a/packages/flutter_tools/test/general.shard/ios/simulators_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/simulators_test.dart @@ -37,7 +37,6 @@ void main() { late FakePlatform osx; late FileSystemUtils fsUtils; late MemoryFileSystem fileSystem; - final Logger logger = FakeLogger(); setUp(() { osx = FakePlatform( @@ -63,7 +62,6 @@ void main() { name: 'iPhone 11', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-14-4', - logger: logger, ); final DevicePortForwarder portForwarder = simulator.portForwarder; await portForwarder.forward(123); @@ -89,7 +87,6 @@ void main() { name: 'iPhone 11', simControl: FakeSimControl(), simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-14-4', - logger: logger, ); expect(simulator.supportsRuntimeMode(BuildMode.debug), true); @@ -116,7 +113,6 @@ void main() { name: 'iPhone 11', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-14-4', - logger: logger, ); expect(simulator.logFilePath, '/foo/bar/Library/Logs/CoreSimulator/123/system.log'); }, overrides: { @@ -134,7 +130,6 @@ void main() { name: 'iPhone 11', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-14-4', - logger: logger, ); expect(simulator.logFilePath, '/baz/qux/456/system.log'); }, overrides: { @@ -159,7 +154,6 @@ void main() { name: 'iPhone SE', simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', simControl: simControl, - logger: logger, ); expect(await device.sdkMajorVersion, 11); @@ -171,7 +165,6 @@ void main() { name: 'iPhone SE', simulatorCategory: 'iOS 11.2', simControl: simControl, - logger: logger, ); expect(await device.sdkMajorVersion, 11); @@ -183,7 +176,6 @@ void main() { name: 'iPhone SE', simulatorCategory: 'iOS 11.2', simControl: simControl, - logger: logger, ); expect(device.category, Category.mobile); @@ -203,7 +195,6 @@ void main() { name: 'Apple TV', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.tvOS-14-5', - logger: logger, ); expect(simulator.isSupported(), false); }, overrides: { @@ -218,7 +209,6 @@ void main() { name: 'Apple Watch', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.watchOS-8-0', - logger: logger, ).isSupported(), false); }, overrides: { Platform: () => osx, @@ -232,7 +222,6 @@ void main() { name: 'iPad 2', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ).isSupported(), true); }, overrides: { Platform: () => osx, @@ -246,7 +235,6 @@ void main() { name: 'iPad Retina', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ).isSupported(), true); }, overrides: { Platform: () => osx, @@ -260,7 +248,6 @@ void main() { name: 'iPhone 5', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ).isSupported(), true); }, overrides: { Platform: () => osx, @@ -274,7 +261,6 @@ void main() { name: 'iPhone 5s', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ).isSupported(), true); }, overrides: { Platform: () => osx, @@ -288,7 +274,6 @@ void main() { name: 'iPhone SE', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ).isSupported(), true); }, overrides: { Platform: () => osx, @@ -302,7 +287,6 @@ void main() { name: 'iPhone 7 Plus', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ).isSupported(), true); }, overrides: { Platform: () => osx, @@ -316,7 +300,6 @@ void main() { name: 'iPhone X', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ).isSupported(), true); }, overrides: { Platform: () => osx, @@ -354,7 +337,6 @@ void main() { name: 'iPhone SE', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ); final File screenshot = MemoryFileSystem.test().file('screenshot.png'); @@ -378,7 +360,6 @@ void main() { name: 'iPhone SE', simulatorCategory: 'iOS 9.3', simControl: simControl, - logger: logger, ); fakeProcessManager.addCommand(const FakeCommand(command: [ 'tail', @@ -406,7 +387,6 @@ void main() { name: 'iPhone SE', simulatorCategory: 'iOS 11.0', simControl: simControl, - logger: logger, ); const String expectedPredicate = 'eventType = logEvent AND ' 'processImagePath ENDSWITH "My Super Awesome App" AND ' @@ -441,7 +421,6 @@ void main() { name: 'iPhone SE', simulatorCategory: 'iOS 11.0', simControl: simControl, - logger: logger, ); const String expectedPredicate = 'eventType = logEvent AND ' '(senderImagePath ENDSWITH "/Flutter" OR senderImagePath ENDSWITH "/libswiftCore.dylib" OR processImageUUID == senderImageUUID) AND ' @@ -506,7 +485,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone 11', simulatorCategory: 'iOS 10.0', simControl: simControl, - logger: logger, ); final DeviceLogReader logReader = device.getLogReader( app: await BuildableIOSApp.fromProject(mockIosProject, null), @@ -542,7 +520,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone 11', simulatorCategory: 'iOS 10.3', simControl: simControl, - logger: logger, ); final DeviceLogReader logReader = device.getLogReader( app: await BuildableIOSApp.fromProject(mockIosProject, null), @@ -591,7 +568,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone 11', simulatorCategory: 'iOS 10.3', simControl: simControl, - logger: logger, ); final DeviceLogReader logReader = device.getLogReader( app: await BuildableIOSApp.fromProject(mockIosProject, null), @@ -664,7 +640,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone 11', simulatorCategory: 'iOS 11.0', simControl: simControl, - logger: logger, ); final DeviceLogReader logReader = device.getLogReader( app: await BuildableIOSApp.fromProject(mockIosProject, null), @@ -708,7 +683,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone 11', simulatorCategory: 'iOS 11.0', simControl: simControl, - logger: logger, ); final DeviceLogReader logReader = device.getLogReader( app: await BuildableIOSApp.fromProject(mockIosProject, null), @@ -850,7 +824,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'Testo', simulatorCategory: 'NaN', simControl: simControl, - logger: logger, ); expect(await iosSimulatorA.sdkMajorVersion, 11); @@ -935,7 +908,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'Testo', simulatorCategory: 'NaN', simControl: simControl, - logger: logger, ); expect(await iosSimulator.stopApp(null), isFalse); @@ -1114,7 +1086,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone SE', simulatorCategory: 'iOS 11.2', simControl: simControl, - logger: logger, ); testPlistParser.setProperty('CFBundleIdentifier', 'correct'); @@ -1144,7 +1115,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone SE', simulatorCategory: 'iOS 11.2', simControl: simControl, - logger: logger, ); final Directory mockDir = globals.fs.currentDirectory; @@ -1176,7 +1146,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone SE', simulatorCategory: 'iOS 11.2', simControl: simControl, - logger: logger, ); testPlistParser.setProperty('CFBundleIdentifier', 'correct'); @@ -1249,7 +1218,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' name: 'iPhone SE', simulatorCategory: 'iOS 11.2', simControl: simControl, - logger: logger, ); testPlistParser.setProperty('CFBundleIdentifier', 'correct'); @@ -1300,7 +1268,6 @@ flutter: name: 'iPhone 11', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ); expect(simulator.isSupportedForProject(flutterProject), true); }, overrides: { @@ -1321,7 +1288,6 @@ flutter: name: 'iPhone 11', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ); expect(simulator.isSupportedForProject(flutterProject), true); }, overrides: { @@ -1340,7 +1306,6 @@ flutter: name: 'iPhone 11', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ); expect(simulator.isSupportedForProject(flutterProject), false); }, overrides: { @@ -1355,7 +1320,6 @@ flutter: name: 'iPhone 11', simControl: simControl, simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3', - logger: logger, ); expect(simulator.createDevFSWriter(null, ''), isA()); diff --git a/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart b/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart index 98bfc545993b..8efd65c20387 100644 --- a/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart +++ b/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart @@ -17,7 +17,6 @@ import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device_vm_service_discovery_for_attach.dart'; import 'package:flutter_tools/src/proxied_devices/devices.dart'; import 'package:flutter_tools/src/proxied_devices/file_transfer.dart'; -import 'package:flutter_tools/src/resident_runner.dart'; import 'package:test/fake.dart'; import '../../src/common.dart'; @@ -645,8 +644,9 @@ void main() { final Future startFuture = dds.startDartDevelopmentService( Uri.parse('http://127.0.0.1:100/fake'), disableServiceAuthCodes: true, - ddsPort: 150, + hostPort: 150, ipv6: false, + logger: bufferLogger, ); final DaemonMessage startMessage = await broadcastOutput.first; @@ -656,13 +656,9 @@ void main() { 'deviceId': 'test_id', 'vmServiceUri': 'http://127.0.0.1:200/fake', 'disableServiceAuthCodes': true, - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // 'enableDevTools': false, }); - serverDaemonConnection.sendResponse( startMessage.data['id']!, const { - 'ddsUri': 'http://127.0.0.1:300/remote', - }); + serverDaemonConnection.sendResponse(startMessage.data['id']!, 'http://127.0.0.1:300/remote'); await startFuture; expect(portForwarder.receivedLocalForwardedPort, 100); @@ -705,8 +701,9 @@ void main() { final Future startFuture = dds.startDartDevelopmentService( Uri.parse('http://127.0.0.1:100/fake'), disableServiceAuthCodes: true, - ddsPort: 150, + hostPort: 150, ipv6: false, + logger: bufferLogger, ); final DaemonMessage startMessage = await broadcastOutput.first; @@ -716,13 +713,9 @@ void main() { 'deviceId': 'test_id', 'vmServiceUri': 'http://127.0.0.1:200/fake', 'disableServiceAuthCodes': true, - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // 'enableDevTools': false, }); - serverDaemonConnection.sendResponse(startMessage.data['id']!, { - 'ddsUri': 'http://127.0.0.1:300/remote', - }); + serverDaemonConnection.sendResponse(startMessage.data['id']!, 'http://127.0.0.1:300/remote'); await startFuture; expect(portForwarder.receivedLocalForwardedPort, 100); @@ -765,8 +758,9 @@ void main() { await dds.startDartDevelopmentService( Uri.parse('http://127.0.0.1:100/fake'), disableServiceAuthCodes: true, - ddsPort: 150, + hostPort: 150, ipv6: false, + logger: bufferLogger, ); expect(localDds.startCalled, true); @@ -803,8 +797,9 @@ void main() { final Future startFuture = dds.startDartDevelopmentService( Uri.parse('http://127.0.0.1:100/fake'), disableServiceAuthCodes: true, - ddsPort: 150, + hostPort: 150, ipv6: false, + logger: bufferLogger, ); expect(localDds.startCalled, false); @@ -815,8 +810,6 @@ void main() { 'deviceId': 'test_id', 'vmServiceUri': 'http://127.0.0.1:200/fake', 'disableServiceAuthCodes': true, - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // 'enableDevTools': false, }); serverDaemonConnection.sendErrorResponse(startMessage.data['id']!, 'command not understood: device.startDartDevelopmentService', StackTrace.current); @@ -1185,14 +1178,11 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService @override Future startDartDevelopmentService( Uri vmServiceUri, { - FlutterDevice? device, - int? ddsPort, + required Logger logger, + int? hostPort, bool? ipv6, bool? disableServiceAuthCodes, - bool enableDevTools = false, bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async { startCalled = true; startUri = vmServiceUri; @@ -1200,10 +1190,6 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService @override Future shutdown() async => shutdownCalled = true; - - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // @override - // Future invokeServiceExtensions(FlutterDevice? device) async {} } class FakePrebuiltApplicationPackage extends Fake implements PrebuiltApplicationPackage { diff --git a/packages/flutter_tools/test/general.shard/resident_devtools_handler_test.dart b/packages/flutter_tools/test/general.shard/resident_devtools_handler_test.dart index d25d9134fd24..fb2c7242401a 100644 --- a/packages/flutter_tools/test/general.shard/resident_devtools_handler_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_devtools_handler_test.dart @@ -469,14 +469,12 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService @override Future startDartDevelopmentService( - Uri vmServiceUri, { - int? ddsPort, - bool? disableServiceAuthCodes, + Uri observatoryUri, { + required Logger logger, + int? hostPort, bool? ipv6, - bool enableDevTools = true, + bool? disableServiceAuthCodes, bool cacheStartupProfile = false, - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, }) async { started = true; } @@ -485,4 +483,7 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService Future shutdown() async { disposed = true; } + + @override + void setExternalDevToolsUri(Uri uri) {} } diff --git a/packages/flutter_tools/test/general.shard/resident_runner_helpers.dart b/packages/flutter_tools/test/general.shard/resident_runner_helpers.dart index b8b6e4d9725e..c6da20415e37 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_helpers.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_helpers.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:dds/dds.dart' as dds; import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/asset.dart'; import 'package:flutter_tools/src/base/dds.dart'; @@ -150,44 +151,33 @@ const FakeVmServiceRequest evictShader = FakeVmServiceRequest( } ); -const DartDevelopmentServiceInstance fakeDartDevelopmentServiceInstance = ( - process: null, - serviceUri: null, - devToolsUri: null, - dtdUri: null, -); - final Uri testUri = Uri.parse('foo://bar'); -class FakeDartDevelopmentService extends Fake with DartDevelopmentServiceLocalOperationsMixin implements DartDevelopmentService { +// This implements [dds.DartDevelopmentService], not the [DartDevelopmentService] +// interface from package:flutter_tools. +class FakeDartDevelopmentService extends Fake implements dds.DartDevelopmentService { @override Future get done => Future.value(); @override Uri? get uri => null; - - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS> - /* - @override - Uri? get devToolsUri => null; - - @override - Uri? get dtdUri => null; - - @override - Future handleHotRestart(FlutterDevice? device) async {} - */ } -class FakeDartDevelopmentServiceException implements DartDevelopmentServiceException { +class FakeDartDevelopmentServiceException implements dds.DartDevelopmentServiceException { FakeDartDevelopmentServiceException({this.message = defaultMessage}); @override - final int errorCode = DartDevelopmentServiceException.existingDdsInstanceError; + final int errorCode = dds.DartDevelopmentServiceException.existingDdsInstanceError; @override final String message; static const String defaultMessage = 'A DDS instance is already connected at http://localhost:8181'; + + @override + Map toJson() => { + 'error_code': errorCode, + 'message': message, + }; } class TestFlutterDevice extends FlutterDevice { @@ -282,10 +272,13 @@ class FakeFlutterDevice extends Fake implements FlutterDevice { GetSkSLMethod? getSkSLMethod, FlutterProject? flutterProject, PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, - required DebuggingOptions debuggingOptions, int? hostVmServicePort, - bool? ipv6 = false, - bool allowExistingDdsInstance = false, + int? ddsPort, + bool disableServiceAuthCodes = false, + bool enableDds = true, + bool cacheStartupProfile = false, + required bool allowExistingDdsInstance, + bool ipv6 = false, }) async { } @override @@ -310,10 +303,6 @@ class FakeFlutterDevice extends Fake implements FlutterDevice { @override Future updateReloadStatus(bool wasReloadSuccessful) async { } - - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // @override - // Future handleHotRestart() async {} } class FakeDelegateFlutterDevice extends FlutterDevice { @@ -328,13 +317,16 @@ class FakeDelegateFlutterDevice extends FlutterDevice { Future connect({ ReloadSources? reloadSources, Restart? restart, + bool enableDds = true, + bool cacheStartupProfile = false, + bool disableServiceAuthCodes = false, + bool ipv6 = false, CompileExpression? compileExpression, GetSkSLMethod? getSkSLMethod, FlutterProject? flutterProject, - PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, - required DebuggingOptions debuggingOptions, int? hostVmServicePort, - bool? ipv6 = false, + int? ddsPort, + PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, bool allowExistingDdsInstance = false, }) async { } @@ -443,7 +435,7 @@ class FakeDevice extends Fake implements Device { String get name => 'FakeDevice'; @override - late DartDevelopmentService dds = FakeDartDevelopmentService(); + late DartDevelopmentService dds; @override Future dispose() async { 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 b0f4f8623ee2..7c1a8b899ebf 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart @@ -4,10 +4,12 @@ import 'dart:async'; +import 'package:dds/dds.dart' as dds; import 'package:file/memory.dart'; import 'package:file_testing/file_testing.dart'; import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/command_help.dart'; +import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/dds.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/io.dart' as io; @@ -63,8 +65,8 @@ void main() { stayResident: false, debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), target: 'main.dart', - analytics: fakeAnalytics, devtoolsHandler: createNoOpHandler, + analytics: globals.analytics, ); }, overrides: { Analytics: () => FakeAnalytics(), @@ -88,6 +90,7 @@ void main() { final Future result = residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, ); final Future connectionInfo = futureConnectionInfo.future; @@ -119,7 +122,7 @@ void main() { ); flutterDevice.generator = residentCompiler; - expect(await residentRunner.run(), 0); + expect(await residentRunner.run(enableDevTools: true), 0); expect(residentCompiler.didSuppressErrors, true); expect(fakeVmServiceHost?.hasRemainingExpectations, false); })); @@ -213,7 +216,7 @@ void main() { ); flutterDevice.generator = residentCompiler; - expect(await residentRunner.run(), 0); + expect(await residentRunner.run(enableDevTools: true), 0); expect(residentCompiler.didSuppressErrors, false); expect(fakeVmServiceHost?.hasRemainingExpectations, false); })); @@ -276,6 +279,7 @@ void main() { final Future result = residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, ); final Future connectionInfo = futureConnectionInfo.future; @@ -297,6 +301,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; flutterDevice.reportError = vm_service.RPCError('something bad happened', 666, ''); @@ -338,6 +343,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; @@ -383,6 +389,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; flutterDevice.reportError = vm_service.RPCError('something bad happened', kIsolateReloadBarred, ''); @@ -426,15 +433,13 @@ void main() { ], stayResident: false, target: 'main.dart', - debuggingOptions: DebuggingOptions.enabled( - const BuildInfo( - BuildMode.debug, '', treeShakeIcons: false, extraFrontEndOptions: [ - '--enable-experiment=non-nullable', - ], - packageConfigPath: '.dart_tool/package_config.json', - ), - enableDevTools: false, - ), + debuggingOptions: DebuggingOptions.enabled(const BuildInfo( + BuildMode.debug, '', treeShakeIcons: false, extraFrontEndOptions: [ + '--enable-experiment=non-nullable', + ], + packageConfigPath: '.dart_tool/package_config.json' + )), + devtoolsHandler: createNoOpHandler, analytics: fakeAnalytics, ); final Completer futureConnectionInfo = Completer.sync(); @@ -442,6 +447,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; flutterDevice.reportError = vm_service.RPCError('something bad happened', 666, ''); @@ -506,6 +512,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; flutterDevice.report = UpdateFSReport(success: true); @@ -563,6 +570,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; flutterDevice.report = UpdateFSReport(success: true, invalidatedSourcesCount: 1); @@ -626,6 +634,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; flutterDevice.report = UpdateFSReport(success: true, invalidatedSourcesCount: 1); @@ -685,6 +694,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; @@ -775,6 +785,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; @@ -836,6 +847,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); final OperationResult result = await residentRunner.restart(fullRestart: true); @@ -925,6 +937,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); final OperationResult result = await residentRunner.restart(fullRestart: true); @@ -1045,6 +1058,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await residentRunner.restart(fullRestart: true); @@ -1064,6 +1078,7 @@ void main() { unawaited(residentRunner.attach( appStartedCompleter: futureAppStart, connectionInfoCompleter: futureConnectionInfo, + enableDevTools: true, )); await futureAppStart.future; flutterDevice.reportError = vm_service.RPCError('something bad happened', 666, ''); @@ -1506,7 +1521,7 @@ flutter: flutterDevice, ], stayResident: false, - debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo', enableDevTools: false), + debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'), target: 'main.dart', devtoolsHandler: createNoOpHandler, ); @@ -1556,7 +1571,7 @@ flutter: analytics: fakeAnalytics, ); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(fakeVmServiceHost?.hasRemainingExpectations, false); expect(await globals.fs.file('foo').readAsString(), testUri.toString()); @@ -1587,7 +1602,7 @@ flutter: ); residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC'); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill')).readAsString(), 'ABC'); })); @@ -1618,7 +1633,7 @@ flutter: ); residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC'); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(await globals.fs.file(globals.fs.path.join( 'build', '187ef4436122d1cc2f40dc2b92f0eba0.cache.dill')).readAsString(), 'ABC'); @@ -1650,7 +1665,7 @@ flutter: ); residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC'); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(await globals.fs.file(globals.fs.path.join( 'build', 'cache.dill')).readAsString(), 'ABC'); @@ -1674,7 +1689,7 @@ flutter: ); residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC'); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(await globals.fs.file(globals.fs.path.join( 'build', 'cache.dill.track.dill')).readAsString(), 'ABC'); @@ -1699,7 +1714,7 @@ flutter: ); residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC'); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(globals.fs.file(globals.fs.path.join('build', 'cache.dill')), isNot(exists)); })); @@ -1728,7 +1743,7 @@ flutter: ); residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC'); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill.track.dill')).readAsString(), 'ABC'); })); @@ -1771,7 +1786,7 @@ flutter: analytics: fakeAnalytics, ); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(testLogger.errorText, contains('Failed to write vmservice-out-file at foo')); expect(fakeVmServiceHost?.hasRemainingExpectations, false); @@ -1790,11 +1805,11 @@ flutter: ], stayResident: false, debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'), - devtoolsHandler: createNoOpHandler, target: 'main.dart', + devtoolsHandler: createNoOpHandler, ); - await residentRunner.run(); + await residentRunner.run(enableDevTools: true); expect(await globals.fs.file('foo').readAsString(), testUri.toString()); expect(fakeVmServiceHost?.hasRemainingExpectations, false); @@ -1960,19 +1975,61 @@ flutter: ProcessManager: () => FakeProcessManager.any(), }); + testUsingContext('Handle existing VM service clients DDS error', () => testbed.run(() async { + fakeVmServiceHost = FakeVmServiceHost(requests: []); + final FakeDevice device = FakeDevice() + ..dds = DartDevelopmentService(); + ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List cachedUserTags = const [], dds.UriConverter? uriConverter}) { + expect(uri, Uri(scheme: 'foo', host: 'bar')); + expect(enableAuthCodes, isTrue); + expect(ipv6, isFalse); + expect(serviceUri, Uri(scheme: 'http', host: '127.0.0.1', port: 0)); + expect(cachedUserTags, isEmpty); + expect(uriConverter, isNull); + throw FakeDartDevelopmentServiceException(message: + 'Existing VM service clients prevent DDS from taking control.', + ); + }; + final TestFlutterDevice flutterDevice = TestFlutterDevice( + device, + vmServiceUris: Stream.value(testUri), + ); + bool caught = false; + final Completerdone = Completer(); + runZonedGuarded(() { + flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete()); + }, (Object e, StackTrace st) { + expect(e, isA()); + expect((e as ToolExit).message, + contains('Existing VM service clients prevent DDS from taking control.', + )); + done.complete(); + caught = true; + }); + await done.future; + if (!caught) { + fail('Expected ToolExit to be thrown.'); + } + }, overrides: { + VMServiceConnector: () => (Uri httpUri, { + ReloadSources? reloadSources, + Restart? restart, + CompileExpression? compileExpression, + GetSkSLMethod? getSkSLMethod, + FlutterProject? flutterProject, + PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, + io.CompressionOptions? compression, + Device? device, + required Logger logger, + }) async => FakeVmServiceHost(requests: []).vmService, + })); + testUsingContext('Uses existing DDS URI from exception field', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: []); final FakeDevice device = FakeDevice() - ..dds = DartDevelopmentService(logger: testLogger); - ddsLauncherCallback = (Uri uri, - {bool enableDevTools = false, - bool enableAuthCodes = true, - bool ipv6 = false, Uri? serviceUri, - List cachedUserTags = const [], - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, - }) { - throw DartDevelopmentServiceException.existingDdsInstance( + ..dds = DartDevelopmentService(); + ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List cachedUserTags = const [], dds.UriConverter? uriConverter}) { + throw dds.DartDevelopmentServiceException.existingDdsInstance( 'Existing DDS at http://localhost/existingDdsInMessage.', ddsUri: Uri.parse('http://localhost/existingDdsInField'), ); @@ -1983,10 +2040,7 @@ flutter: ); final Completer done = Completer(); unawaited(runZonedGuarded( - () => flutterDevice.connect( - allowExistingDdsInstance: true, - debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), - ).then((_) => done.complete()), + () => flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete()), (_, __) => done.complete(), )); await done.future; @@ -1998,7 +2052,41 @@ flutter: CompileExpression? compileExpression, GetSkSLMethod? getSkSLMethod, FlutterProject? flutterProject, - PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, + PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, + io.CompressionOptions? compression, + Device? device, + required Logger logger, + }) async => FakeVmServiceHost(requests: []).vmService, + })); + + testUsingContext('Falls back to existing DDS URI from exception message', () => testbed.run(() async { + fakeVmServiceHost = FakeVmServiceHost(requests: []); + final FakeDevice device = FakeDevice() + ..dds = DartDevelopmentService(); + ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List cachedUserTags = const [], dds.UriConverter? uriConverter}) { + throw dds.DartDevelopmentServiceException.existingDdsInstance( + 'Existing DDS at http://localhost/existingDdsInMessage.', + ); + }; + final TestFlutterDevice flutterDevice = TestFlutterDevice( + device, + vmServiceUris: Stream.value(testUri), + ); + final Completerdone = Completer(); + unawaited(runZonedGuarded( + () => flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete()), + (_, __) => done.complete(), + )); + await done.future; + expect(device.dds.uri, Uri.parse('http://localhost/existingDdsInMessage')); + }, overrides: { + VMServiceConnector: () => (Uri httpUri, { + ReloadSources? reloadSources, + Restart? restart, + CompileExpression? compileExpression, + GetSkSLMethod? getSkSLMethod, + FlutterProject? flutterProject, + PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, io.CompressionOptions? compression, Device? device, required Logger logger, @@ -2008,34 +2096,23 @@ flutter: testUsingContext('Host VM service ipv6 defaults', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: []); final FakeDevice device = FakeDevice() - ..dds = DartDevelopmentService(logger: testLogger); + ..dds = DartDevelopmentService(); final Completerdone = Completer(); - ddsLauncherCallback = (Uri uri, - {bool enableDevTools = false, - bool enableAuthCodes = true, - bool ipv6 = false, Uri? serviceUri, - List cachedUserTags = const [], - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, - }) async { + ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List cachedUserTags = const [], dds.UriConverter? uriConverter}) async { expect(uri, Uri(scheme: 'foo', host: 'bar')); expect(enableAuthCodes, isFalse); expect(ipv6, isTrue); expect(serviceUri, Uri(scheme: 'http', host: '::1', port: 0)); expect(cachedUserTags, isEmpty); + expect(uriConverter, isNull); done.complete(); - return fakeDartDevelopmentServiceInstance; + return FakeDartDevelopmentService(); }; final TestFlutterDevice flutterDevice = TestFlutterDevice( device, vmServiceUris: Stream.value(testUri), ); - await flutterDevice.connect( - allowExistingDdsInstance: true, - debuggingOptions: DebuggingOptions.enabled( - BuildInfo.debug, disableServiceAuthCodes: true, ipv6: true, - ) - ); + await flutterDevice.connect(allowExistingDdsInstance: true, ipv6: true, disableServiceAuthCodes: true); await done.future; }, overrides: { VMServiceConnector: () => (Uri httpUri, { @@ -2051,25 +2128,67 @@ flutter: }) async => FakeVmServiceHost(requests: []).vmService, })); + testUsingContext('Context includes URI converter', () => testbed.run(() async { + fakeVmServiceHost = FakeVmServiceHost(requests: []); + final FakeDevice device = FakeDevice() + ..dds = DartDevelopmentService(); + final Completerdone = Completer(); + ddsLauncherCallback = ( + Uri uri, { + bool enableAuthCodes = false, + bool ipv6 = false, + Uri? serviceUri, + List cachedUserTags = const [], + dds.UriConverter? uriConverter, + }) async { + expect(uri, Uri(scheme: 'foo', host: 'bar')); + expect(enableAuthCodes, isFalse); + expect(ipv6, isTrue); + expect(serviceUri, Uri(scheme: 'http', host: '::1', port: 0)); + expect(cachedUserTags, isEmpty); + expect(uriConverter, isNotNull); + done.complete(); + return FakeDartDevelopmentService(); + }; + final TestFlutterDevice flutterDevice = TestFlutterDevice( + device, + vmServiceUris: Stream.value(testUri), + ); + await flutterDevice.connect(allowExistingDdsInstance: true, ipv6: true, disableServiceAuthCodes: true); + await done.future; + }, overrides: { + VMServiceConnector: () => (Uri httpUri, { + ReloadSources? reloadSources, + Restart? restart, + CompileExpression? compileExpression, + GetSkSLMethod? getSkSLMethod, + FlutterProject? flutterProject, + PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, + io.CompressionOptions compression = io.CompressionOptions.compressionDefault, + Device? device, + required Logger logger, + }) async => FakeVmServiceHost(requests: []).vmService, + dds.UriConverter: () => (String uri) => 'test', + })); + testUsingContext('Failed DDS start outputs error message', () => testbed.run(() async { // See https://github.com/flutter/flutter/issues/72385 for context. final FakeDevice device = FakeDevice() - ..dds = DartDevelopmentService(logger: testLogger); + ..dds = DartDevelopmentService(); ddsLauncherCallback = ( Uri uri, { - bool enableDevTools = false, bool enableAuthCodes = false, bool ipv6 = false, Uri? serviceUri, List cachedUserTags = const [], - String? google3WorkspaceRoot, - Uri? devToolsServerAddress, + dds.UriConverter? uriConverter, }) { expect(uri, Uri(scheme: 'foo', host: 'bar')); expect(enableAuthCodes, isTrue); expect(ipv6, isFalse); expect(serviceUri, Uri(scheme: 'http', host: '127.0.0.1', port: 0)); expect(cachedUserTags, isEmpty); + expect(uriConverter, isNull); throw FakeDartDevelopmentServiceException(message: 'No URI'); }; final TestFlutterDevice flutterDevice = TestFlutterDevice( @@ -2079,10 +2198,7 @@ flutter: bool caught = false; final Completerdone = Completer(); runZonedGuarded(() { - flutterDevice.connect( - allowExistingDdsInstance: true, - debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, enableDevTools: false), - ).then((_) => done.complete()); + flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete()); }, (Object e, StackTrace st) { expect(e, isA()); expect((e as StateError).message, contains('No URI')); @@ -2120,7 +2236,6 @@ flutter: expect(() => nextPlatform('unknown'), throwsAssertionError); }); - // TODO(bkonyi): remove when ready to serve DevTools from DDS. testUsingContext('cleanupAtFinish shuts down resident devtools handler', () => testbed.run(() async { residentRunner = HotRunner( [ diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart index 96881920a123..131734100ca2 100644 --- a/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart @@ -50,6 +50,7 @@ void main() { mockFlutterDevice, flutterProject: project, debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), @@ -80,6 +81,7 @@ void main() { mockFlutterDevice, flutterProject: project, debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), @@ -105,6 +107,7 @@ void main() { mockFlutterDevice, flutterProject: project, debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), @@ -129,6 +132,7 @@ void main() { mockFlutterDevice, flutterProject: project, debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), @@ -158,6 +162,7 @@ void main() { mockFlutterDevice, flutterProject: project, debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), @@ -240,8 +245,4 @@ class FakeFlutterDevice extends Fake implements FlutterDevice { @override FlutterVmService? vmService; - - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // @override - // Future handleHotRestart() async {} } diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart index c175539951cc..34ef199025b5 100644 --- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart @@ -162,6 +162,7 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), usage: globals.flutterUsage, @@ -194,6 +195,7 @@ void main() { FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), usage: globals.flutterUsage, @@ -213,6 +215,7 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), usage: globals.flutterUsage, @@ -226,6 +229,7 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), usage: globals.flutterUsage, @@ -358,13 +362,13 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, stayResident: false, fileSystem: fileSystem, logger: logger, usage: globals.flutterUsage, analytics: globals.analytics, systemClock: globals.systemClock, - devtoolsHandler: createNoOpHandler, ); expect(await residentWebRunner.run(), 0); @@ -385,13 +389,13 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, stayResident: false, fileSystem: fileSystem, logger: BufferLogger.test(), usage: globals.flutterUsage, analytics: globals.analytics, systemClock: globals.systemClock, - devtoolsHandler: createNoOpHandler, ); expect(await residentWebRunner.run(), 0); @@ -587,12 +591,12 @@ void main() { FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true), + ipv6: true, fileSystem: fileSystem, logger: BufferLogger.test(), usage: globals.flutterUsage, analytics: globals.analytics, systemClock: globals.systemClock, - devtoolsHandler: createNoOpHandler, ); fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations.toList()); @@ -1008,7 +1012,7 @@ void main() { testUsingContext('cleanup of resources is safe to call multiple times', () async { final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice); - mockDevice.dds = DartDevelopmentService(logger: test_fakes.FakeLogger()); + mockDevice.dds = DartDevelopmentService(); fakeVmServiceHost = FakeVmServiceHost(requests: [ ...kAttachExpectations, ]); @@ -1111,12 +1115,12 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, fileSystem: fileSystem, logger: logger, usage: globals.flutterUsage, analytics: globals.analytics, systemClock: globals.systemClock, - devtoolsHandler: createNoOpHandler, ); final Completer connectionInfoCompleter = @@ -1160,12 +1164,12 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, fileSystem: fileSystem, logger: logger, usage: globals.flutterUsage, analytics: globals.analytics, systemClock: globals.systemClock, - devtoolsHandler: createNoOpHandler, ); final Completer connectionInfoCompleter = @@ -1202,13 +1206,13 @@ void main() { flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, stayResident: false, fileSystem: fileSystem, logger: BufferLogger.test(), usage: globals.flutterUsage, analytics: globals.analytics, systemClock: globals.systemClock, - devtoolsHandler: createNoOpHandler, ); // Create necessary files. @@ -1406,6 +1410,7 @@ ResidentRunner setUpResidentRunner( FlutterProject.fromDirectoryTest(globals.fs.currentDirectory), debuggingOptions: debuggingOptions ?? DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, usage: globals.flutterUsage, analytics: globals.analytics, systemClock: systemClock ?? SystemClock.fixed(DateTime.now()), @@ -1714,11 +1719,13 @@ class FakeFlutterDevice extends Fake implements FlutterDevice { GetSkSLMethod? getSkSLMethod, FlutterProject? flutterProject, PrintStructuredErrorLogMethod? printStructuredErrorLogMethod, - required DebuggingOptions debuggingOptions, int? hostVmServicePort, + int? ddsPort, + bool disableServiceAuthCodes = false, + bool enableDds = true, + bool cacheStartupProfile = false, + required bool allowExistingDdsInstance, bool? ipv6 = false, - bool enableDevTools = false, - bool allowExistingDdsInstance = false, }) async {} @override @@ -1744,10 +1751,6 @@ class FakeFlutterDevice extends Fake implements FlutterDevice { @override Future updateReloadStatus(bool wasReloadSuccessful) async {} - - // TODO(bkonyi): uncomment when ready to serve DevTools from DDS. - // @override - // Future handleHotRestart() async {} } class FakeShaderCompiler implements DevelopmentShaderCompiler { diff --git a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart index 6e6f8b462497..30ea65af5af6 100644 --- a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart @@ -191,7 +191,6 @@ void main() { Analytics: () => fakeAnalytics, }); - // TODO(bkonyi): remove when ready to serve DevTools from DDS. group('${FlutterGlobalOptions.kPrintDtd} flag', () { testUsingContext('sets DevtoolsLauncher.printDtdUri to false when not present', () async { final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner; 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 e9232691e8fd..ba43d15f3112 100644 --- a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart +++ b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart @@ -7,7 +7,6 @@ import 'dart:async'; import 'package:file/file.dart'; import 'package:file/memory.dart'; import 'package:file_testing/file_testing.dart'; -import 'package:flutter_tools/src/base/dds.dart'; import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/signals.dart'; @@ -26,7 +25,6 @@ import 'package:vm_service/vm_service.dart' as vm_service; import '../src/common.dart'; import '../src/fake_vm_services.dart'; -import '../src/fakes.dart'; final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate( id: '1', @@ -834,20 +832,8 @@ void main() { final FakeResidentDevtoolsHandler devtoolsHandler = runner.residentDevtoolsHandler as FakeResidentDevtoolsHandler; expect(devtoolsHandler.calledLaunchDevToolsInBrowser, isFalse); - // TODO(bkonyi): uncomment these checks and remove existing checks when ready to - // serve DevTools from DDS. - /* - for (final FlutterDevice? device in runner.flutterDevices) { - expect(device!.device!.dds.calledLaunchDevToolsInBrowser, isFalse); - } - */ await terminalHandler.processTerminalInput('v'); expect(devtoolsHandler.calledLaunchDevToolsInBrowser, isTrue); - /* - for (final FlutterDevice? device in runner.flutterDevices) { - expect(device!.device!.dds.calledLaunchDevToolsInBrowser, isTrue); - } - */ }); testWithoutContext('w,W - debugDumpApp without service protocol is skipped', () async { @@ -1322,13 +1308,11 @@ class FakeResidentRunner extends ResidentHandlers { return OperationResult(reloadExitCode, '', fatal: fatalReloadError); } - // TODO(bkonyi): remove when ready to serve DevTools from DDS. @override ResidentDevtoolsHandler get residentDevtoolsHandler => _residentDevtoolsHandler; final ResidentDevtoolsHandler _residentDevtoolsHandler = FakeResidentDevtoolsHandler(); } -// TODO(bkonyi): remove when ready to serve DevTools from DDS. class FakeResidentDevtoolsHandler extends Fake implements ResidentDevtoolsHandler { bool calledLaunchDevToolsInBrowser = false; @@ -1348,9 +1332,6 @@ class FakeDevice extends Fake implements Device { @override String get name => 'Fake Device'; - @override - DartDevelopmentService dds = DartDevelopmentService(logger: FakeLogger()); - @override Future takeScreenshot(File file) async { if (!supportsScreenshot) { @@ -1358,6 +1339,7 @@ class FakeDevice extends Fake implements Device { } file.writeAsBytesSync([1, 2, 3, 4]); } + } TerminalHandler setUpTerminalHandler(List requests, { diff --git a/packages/flutter_tools/test/src/fake_devices.dart b/packages/flutter_tools/test/src/fake_devices.dart index 558624432709..4f6ab9e329ed 100644 --- a/packages/flutter_tools/test/src/fake_devices.dart +++ b/packages/flutter_tools/test/src/fake_devices.dart @@ -9,8 +9,6 @@ import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/project.dart'; -import 'fakes.dart'; - /// A list of fake devices to test JSON serialization /// (`Device.toJson()` and `--machine` flag for `devices` command) List fakeDevices = [ @@ -131,7 +129,6 @@ class FakeDevice extends Device { platformType: type, category: Category.mobile, ephemeral: ephemeral, - logger: FakeLogger(), ); final bool _isSupported; diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart index cc6d456b441b..ff6f6deebc5c 100644 --- a/packages/flutter_tools/test/src/fakes.dart +++ b/packages/flutter_tools/test/src/fakes.dart @@ -741,12 +741,6 @@ class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher { } } -/// A fake [Logger] that throws the [Invocation] for any method call. -class FakeLogger implements Logger { - @override - dynamic noSuchMethod(Invocation invocation) => throw invocation; // ignore: only_throw_errors -} - class ClosedStdinController extends Fake implements StreamSink> { @override Future addStream(Stream> stream) async => throw const SocketException('Bad pipe');