Reland "Launch DDS from Dart SDK and prepare to serve DevTools from DDS (#146593)" (#152386)

This reverts commit 7cdc23b3e1bae2bc7bc2d1f34773eaa3629d4fcc.

The failure in the `native_assets_test` integration test on Windows was caused by the DevTools process not being shutdown by the `ColdRunner` when running the profile mode portion of the test. This resulted in the test being unable to clean up the project created by the test as DevTools was still holding onto a handle within the directory. This PR adds back the mistakenly removed DevTools shutdown logic in the `ColdRunner`.
This commit is contained in:
Ben Konyi 2024-07-26 16:51:19 -04:00 committed by GitHub
parent 3a737c9a56
commit 33b402d24c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 790 additions and 752 deletions

View File

@ -59,7 +59,7 @@ class AndroidDevice extends Device {
this.productID,
required this.modelID,
this.deviceCodeName,
required Logger logger,
required super.logger,
required ProcessManager processManager,
required Platform platform,
required AndroidSdk androidSdk,

View File

@ -4,112 +4,328 @@
import 'dart:async';
import 'package:dds/dds.dart' as dds;
import 'package:meta/meta.dart';
import 'common.dart';
import 'context.dart';
import '../artifacts.dart';
import '../convert.dart';
import '../device.dart';
import '../globals.dart' as globals;
import 'io.dart' as io;
import 'logger.dart';
// TODO(fujino): This should be direct injected, rather than mutable global state.
@visibleForTesting
Future<dds.DartDevelopmentService> Function(
Uri remoteVmServiceUri, {
bool enableAuthCodes,
bool ipv6,
/// 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,
List<String> cachedUserTags,
dds.UriConverter? uriConverter,
}) ddsLauncherCallback = dds.DartDevelopmentService.startDartDevelopmentService;
Uri? devToolsUri,
Uri? dtdUri,
});
/// The default DDSLauncherCallback used to spawn DDS.
Future<DartDevelopmentServiceInstance> defaultStartDartDevelopmentService(
Uri remoteVmServiceUri, {
required bool enableAuthCodes,
required bool ipv6,
required bool enableDevTools,
required List<String> 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,
<String>[
'development-service',
'--vm-service-uri=$remoteVmServiceUri',
if (serviceUri != null) ...<String>[
'--bind-address=${serviceUri.host}',
'--bind-port=${serviceUri.port}',
],
if (!enableAuthCodes) '--disable-service-auth-codes',
if (google3WorkspaceRoot != null)
'--google3-workspace-root=$google3WorkspaceRoot',
for (final String tag in cachedUserTags) '--cached-user-tags=$tag',
],
);
final Completer<DartDevelopmentServiceInstance> completer =
Completer<DartDevelopmentServiceInstance>();
late StreamSubscription<Object?> 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<String, Object?>?)?['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<String, Object?>? exceptionDetails =
result['ddsExceptionDetails'] as Map<String, Object?>?;
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<DartDevelopmentServiceInstance> Function(
Uri remoteVmServiceUri, {
required bool enableAuthCodes,
required bool ipv6,
required bool enableDevTools,
required List<String> 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<String, Object?> 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;
}
/// Helper class to launch a [dds.DartDevelopmentService]. Allows for us to
/// mock out this functionality for testing purposes.
class DartDevelopmentService {
dds.DartDevelopmentService? _ddsInstance;
class DartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin {
DartDevelopmentService({required Logger logger}) : _logger = logger;
Uri? get uri => _ddsInstance?.uri ?? _existingDdsUri;
DartDevelopmentServiceInstance? _ddsInstance;
Uri? get uri => _ddsInstance?.serviceUri ?? _existingDdsUri;
Uri? _existingDdsUri;
Future<void> get done => _completer.future;
final Completer<void> _completer = Completer<void>();
final Logger _logger;
@override
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
required Logger logger,
int? hostPort,
bool? ipv6,
int? ddsPort,
bool? disableServiceAuthCodes,
bool? ipv6,
bool enableDevTools = true,
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: hostPort ?? 0,
host: ((ipv6 ?? false)
? io.InternetAddress.loopbackIPv6
: io.InternetAddress.loopbackIPv4)
.host,
port: ddsPort ?? 0,
);
logger.printTrace(
_logger.printTrace(
'Launching a Dart Developer Service (DDS) instance at $ddsUri, '
'connecting to VM service at $vmServiceUri.',
);
try {
_ddsInstance = await ddsLauncherCallback(
vmServiceUri,
serviceUri: ddsUri,
enableAuthCodes: disableServiceAuthCodes != true,
ipv6: ipv6 ?? false,
// Enables caching of CPU samples collected during application startup.
cachedUserTags: cacheStartupProfile ? const <String>['AppStartUp'] : const <String>[],
uriConverter: context.get<dds.UriConverter>(),
);
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);
}
}
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 <String>['AppStartUp']
: const <String>[],
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(
'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);
}
completeFuture();
rethrow;
}
}
Future<void> shutdown() async => _ddsInstance?.shutdown();
void setExternalDevToolsUri(Uri uri) {
_ddsInstance?.setExternalDevToolsUri(uri);
}
void shutdown() => _ddsInstance?.process?.kill();
}
/// Contains common functionality that can be used with any implementation of
/// [DartDevelopmentService].
mixin DartDevelopmentServiceLocalOperationsMixin {
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
int? ddsPort,
bool? disableServiceAuthCodes,
bool? ipv6,
bool enableDevTools = true,
bool cacheStartupProfile = false,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
});
/// A convenience method used to create a [DartDevelopmentService] instance
/// from a [DebuggingOptions] instance.
Future<void> 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,
);
}

View File

@ -361,7 +361,6 @@ 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,
@ -403,7 +402,6 @@ 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);
@ -462,6 +460,9 @@ 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
@ -472,7 +473,6 @@ 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,7 +482,6 @@ known, it can be explicitly provided to attach via the command-line, e.g.
flutterDevices,
target: targetFile,
debuggingOptions: debuggingOptions,
ipv6: usesIpv6,
);
}
@ -506,7 +505,6 @@ class HotRunnerFactory {
String? packagesFilePath,
String? dillOutputPath,
bool stayResident = true,
bool ipv6 = false,
FlutterProject? flutterProject,
String? nativeAssetsYamlFile,
required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
@ -521,7 +519,6 @@ class HotRunnerFactory {
projectRootPath: projectRootPath,
dillOutputPath: dillOutputPath,
stayResident: stayResident,
ipv6: ipv6,
nativeAssetsYamlFile: nativeAssetsYamlFile,
nativeAssetsBuilder: nativeAssetsBuilder,
analytics: analytics,

View File

@ -664,11 +664,9 @@ 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)) {
@ -699,7 +697,6 @@ class AppDomain extends Domain {
flutterProject: flutterProject,
target: target,
debuggingOptions: options,
ipv6: ipv6,
stayResident: true,
urlTunneller: options.webEnableExposeUrl! ? daemon.daemonDomain.exposeUrl : null,
machine: machine,
@ -717,7 +714,6 @@ class AppDomain extends Domain {
applicationBinary: applicationBinary,
projectRootPath: projectRootPath,
dillOutputPath: dillOutputPath,
ipv6: ipv6,
hostIsIde: true,
machine: machine,
analytics: globals.analytics,
@ -729,7 +725,6 @@ class AppDomain extends Domain {
target: target,
debuggingOptions: options,
applicationBinary: applicationBinary,
ipv6: ipv6,
machine: machine,
);
}
@ -743,7 +738,6 @@ class AppDomain extends Domain {
return runner.run(
connectionInfoCompleter: connectionInfoCompleter,
appStartedCompleter: appStartedCompleter,
enableDevTools: enableDevTools,
route: route,
);
},
@ -1008,7 +1002,6 @@ 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);
@ -1196,7 +1189,6 @@ class DeviceDomain extends Domain {
route: _getStringArg(args, 'route'),
platformArgs: castStringKeyedMap(args['platformArgs']) ?? const <String, Object>{},
prebuiltApplication: _getBoolArg(args, 'prebuiltApplication') ?? false,
ipv6: _getBoolArg(args, 'ipv6') ?? false,
userIdentifier: _getStringArg(args, 'userIdentifier'),
);
return <String, Object?>{
@ -1244,23 +1236,33 @@ class DeviceDomain extends Domain {
}
/// Starts DDS for the device.
Future<String?> startDartDevelopmentService(Map<String, Object?> args) async {
Future<Map<String, Object?>> startDartDevelopmentService(Map<String, Object?> 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 device.dds.uri?.toString();
return <String, Object?>{
'ddsUri': device.dds.uri?.toString(),
};
}
/// Starts DDS for the device.
@ -1272,19 +1274,7 @@ class DeviceDomain extends Domain {
throw DaemonException("device '$deviceId' not found");
}
await device.dds.shutdown();
}
Future<void> setExternalDevToolsUriForDartDevelopmentService(Map<String, Object?> 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));
device.dds.shutdown();
}
@override

View File

@ -274,7 +274,6 @@ class DriveCommand extends RunCommandBase {
buildInfo,
device,
debuggingOptions,
ipv6 ?? false,
applicationBinary: applicationBinary,
route: route,
userIdentifier: userIdentifier,
@ -295,7 +294,6 @@ class DriveCommand extends RunCommandBase {
uri,
device,
debuggingOptions,
ipv6 ?? false,
);
}

View File

@ -354,6 +354,9 @@ 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),
);
}
}
@ -702,7 +705,6 @@ 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,
@ -712,7 +714,6 @@ class RunCommand extends RunCommandBase {
flutterDevices.single,
target: targetFile,
flutterProject: flutterProject,
ipv6: ipv6,
debuggingOptions: await createDebuggingOptions(webMode),
stayResident: stayResident,
fileSystem: globals.fs,
@ -731,7 +732,6 @@ class RunCommand extends RunCommandBase {
applicationBinary: applicationBinaryPath == null
? null
: globals.fs.file(applicationBinaryPath),
ipv6: ipv6 ?? false,
stayResident: stayResident,
);
}
@ -776,9 +776,7 @@ 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) {
@ -866,7 +864,6 @@ class RunCommand extends RunCommandBase {
try {
final int? result = await runner.run(
appStartedCompleter: appStartedTimeRecorder,
enableDevTools: stayResident && boolArg(FlutterCommand.kEnableDevTools),
route: route,
);
handler?.stop();

View File

@ -16,6 +16,7 @@ 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';
@ -411,6 +412,7 @@ 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,
);
@ -599,7 +601,6 @@ 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,

View File

@ -352,7 +352,6 @@ class CustomDeviceAppSession {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier
}) async {
final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
@ -377,7 +376,7 @@ class CustomDeviceAppSession {
logReader,
portForwarder: _device._config.usesPortForwarding ? _device.portForwarder : null,
logger: _logger,
ipv6: ipv6,
ipv6: debuggingOptions.ipv6,
);
// We need to make the discovery listen to the logReader before the logReader
@ -439,7 +438,7 @@ class CustomDeviceAppSession {
class CustomDevice extends Device {
CustomDevice({
required CustomDeviceConfig config,
required Logger logger,
required super.logger,
required ProcessManager processManager,
}) : _config = config,
_logger = logger,
@ -789,7 +788,6 @@ class CustomDevice extends Device {
debuggingOptions: debuggingOptions,
platformArgs: platformArgs,
prebuiltApplication: prebuiltApplication,
ipv6: ipv6,
userIdentifier: userIdentifier,
);
}

View File

@ -26,7 +26,7 @@ abstract class DesktopDevice extends Device {
DesktopDevice(super.id, {
required PlatformType super.platformType,
required super.ephemeral,
required Logger logger,
required super.logger,
required ProcessManager processManager,
required FileSystem fileSystem,
required OperatingSystemUtils operatingSystemUtils,
@ -114,7 +114,6 @@ abstract class DesktopDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, dynamic> platformArgs = const <String, dynamic>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
if (!prebuiltApplication) {
@ -158,7 +157,7 @@ abstract class DesktopDevice extends Device {
final ProtocolDiscovery vmServiceDiscovery = ProtocolDiscovery.vmService(_deviceLogReader,
devicePort: debuggingOptions.deviceVmServicePort,
hostPort: debuggingOptions.hostVmServicePort,
ipv6: ipv6,
ipv6: debuggingOptions.ipv6,
logger: _logger,
);
try {

View File

@ -603,10 +603,11 @@ 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;
@ -733,7 +734,7 @@ abstract class Device {
DevicePortForwarder? get portForwarder;
/// Get the DDS instance for this device.
final DartDevelopmentService dds = DartDevelopmentService();
final DartDevelopmentService dds;
/// Clear the device's logs.
void clearLogs();
@ -778,7 +779,6 @@ abstract class Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs,
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
});
@ -1007,7 +1007,11 @@ class DebuggingOptions {
this.enableEmbedderApi = false,
this.usingCISystem = false,
this.debugLogsDirectoryPath,
}) : debuggingEnabled = true,
this.enableDevTools = true,
this.ipv6 = false,
this.google3WorkspaceRoot,
this.printDtd = false,
}) : debuggingEnabled = true,
webRenderer = webRenderer ?? WebRendererMode.getDefault(useWasm: webUseWasm);
DebuggingOptions.disabled(this.buildInfo, {
@ -1065,6 +1069,10 @@ class DebuggingOptions {
nullAssertions = false,
nativeNullAssertions = false,
serveObservatory = false,
enableDevTools = false,
ipv6 = false,
google3WorkspaceRoot = null,
printDtd = false,
webRenderer = webRenderer ?? WebRendererMode.getDefault(useWasm: webUseWasm);
DebuggingOptions._({
@ -1123,6 +1131,10 @@ 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;
@ -1167,6 +1179,10 @@ 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.
///
@ -1220,7 +1236,6 @@ class DebuggingOptions {
EnvironmentType environmentType,
String? route,
Map<String, Object?> platformArgs, {
bool ipv6 = false,
DeviceConnectionInterface interfaceType = DeviceConnectionInterface.attached,
bool isCoreDevice = false,
}) {
@ -1326,6 +1341,10 @@ class DebuggingOptions {
'enableEmbedderApi': enableEmbedderApi,
'usingCISystem': usingCISystem,
'debugLogsDirectoryPath': debugLogsDirectoryPath,
'enableDevTools': enableDevTools,
'ipv6': ipv6,
'google3WorkspaceRoot': google3WorkspaceRoot,
'printDtd': printDtd,
};
static DebuggingOptions fromJson(Map<String, Object?> json, BuildInfo buildInfo) =>
@ -1385,6 +1404,10 @@ 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,
);
}

View File

@ -4,7 +4,6 @@
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';
@ -12,6 +11,7 @@ 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,8 +65,7 @@ abstract class DriverService {
Future<void> start(
BuildInfo buildInfo,
Device device,
DebuggingOptions debuggingOptions,
bool ipv6, {
DebuggingOptions debuggingOptions, {
File? applicationBinary,
String? route,
String? userIdentifier,
@ -79,7 +78,6 @@ abstract class DriverService {
Uri vmServiceUri,
Device device,
DebuggingOptions debuggingOptions,
bool ipv6,
);
/// Start the test file with the provided [arguments] and [environment], returning
@ -148,8 +146,7 @@ class FlutterDriverService extends DriverService {
Future<void> start(
BuildInfo buildInfo,
Device device,
DebuggingOptions debuggingOptions,
bool ipv6, {
DebuggingOptions debuggingOptions, {
File? applicationBinary,
String? route,
String? userIdentifier,
@ -199,7 +196,6 @@ class FlutterDriverService extends DriverService {
result.vmServiceUri!,
device,
debuggingOptions,
ipv6,
);
}
@ -208,7 +204,6 @@ class FlutterDriverService extends DriverService {
Uri vmServiceUri,
Device device,
DebuggingOptions debuggingOptions,
bool ipv6,
) async {
Uri uri;
if (vmServiceUri.scheme == 'ws') {
@ -222,15 +217,12 @@ class FlutterDriverService extends DriverService {
_device = device;
if (debuggingOptions.enableDds) {
try {
await device.dds.startDartDevelopmentService(
await device.dds.startDartDevelopmentServiceFromDebuggingOptions(
uri,
hostPort: debuggingOptions.ddsPort,
ipv6: ipv6,
disableServiceAuthCodes: debuggingOptions.disableServiceAuthCodes,
logger: _logger,
debuggingOptions: debuggingOptions,
);
_vmServiceUri = device.dds.uri.toString();
} on dds.DartDevelopmentServiceException {
} on 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.

View File

@ -55,8 +55,7 @@ class WebDriverService extends DriverService {
Future<void> start(
BuildInfo buildInfo,
Device device,
DebuggingOptions debuggingOptions,
bool ipv6, {
DebuggingOptions debuggingOptions, {
File? applicationBinary,
String? route,
String? userIdentifier,
@ -72,7 +71,6 @@ class WebDriverService extends DriverService {
_residentRunner = webRunnerFactory!.createWebRunner(
flutterDevice,
target: mainPath,
ipv6: ipv6,
debuggingOptions: buildInfo.isRelease ?
DebuggingOptions.disabled(
buildInfo,
@ -234,7 +232,7 @@ class WebDriverService extends DriverService {
}
@override
Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async {
Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions) async {
throwToolExit('--use-existing-app is not supported with flutter web driver');
}
}

View File

@ -58,10 +58,9 @@ Future<void> _kDefaultDartDevelopmentServiceStarter(
) async {
await device.dds.startDartDevelopmentService(
vmServiceUri,
hostPort: 0,
ipv6: true,
ddsPort: 0,
disableServiceAuthCodes: disableServiceAuthCodes,
logger: globals.logger,
ipv6: true,
);
}
@ -212,7 +211,7 @@ class FuchsiaDevices extends PollingDeviceDiscovery {
_logger.printError('Failed to resolve host for Fuchsia device `$name`');
return null;
}
return FuchsiaDevice(resolvedHost, name: name);
return FuchsiaDevice(resolvedHost, name: name, logger: _logger);
}
@override
@ -220,7 +219,7 @@ class FuchsiaDevices extends PollingDeviceDiscovery {
}
class FuchsiaDevice extends Device {
FuchsiaDevice(super.id, {required this.name})
FuchsiaDevice(super.id, {required this.name, required super.logger})
: super(
platformType: PlatformType.fuchsia,
category: null,
@ -295,7 +294,6 @@ class FuchsiaDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object?>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
if (await isSession) {

View File

@ -272,7 +272,7 @@ class IOSDevice extends Device {
required IOSCoreDeviceControl coreDeviceControl,
required XcodeDebug xcodeDebug,
required IProxy iProxy,
required Logger logger,
required super.logger,
})
: _sdkVersion = sdkVersion,
_iosDeploy = iosDeploy,
@ -470,7 +470,6 @@ class IOSDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object?>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
@visibleForTesting Duration? discoveryTimeout,
@visibleForTesting ShutdownHooks? shutdownHooks,
@ -524,7 +523,6 @@ class IOSDevice extends Device {
EnvironmentType.physical,
route,
platformArgs,
ipv6: ipv6,
interfaceType: connectionInterface,
isCoreDevice: isCoreDevice,
);
@ -541,7 +539,6 @@ class IOSDevice extends Device {
bundle: bundle,
debuggingOptions: debuggingOptions,
launchArguments: launchArguments,
ipv6: ipv6,
uninstallFirst: debuggingOptions.uninstallFirst,
);
}
@ -619,7 +616,6 @@ class IOSDevice extends Device {
localUri = await _discoverDartVMForCoreDevice(
debuggingOptions: debuggingOptions,
packageId: packageId,
ipv6: ipv6,
vmServiceDiscovery: vmServiceDiscovery,
);
} else if (isWirelesslyConnected) {
@ -651,7 +647,7 @@ class IOSDevice extends Device {
localUri = await MDnsVmServiceDiscovery.instance!.getVMServiceUriForLaunch(
packageId,
this,
usesIpv6: ipv6,
usesIpv6: debuggingOptions.ipv6,
deviceVmservicePort: serviceURL.port,
useDeviceIPAsHost: true,
);
@ -673,7 +669,6 @@ class IOSDevice extends Device {
bundle: bundle,
debuggingOptions: debuggingOptions,
launchArguments: launchArguments,
ipv6: ipv6,
uninstallFirst: false,
skipInstall: true,
);
@ -728,7 +723,6 @@ class IOSDevice extends Device {
/// Wireless devices require using the device IP as the host.
Future<Uri?> _discoverDartVMForCoreDevice({
required String packageId,
required bool ipv6,
required DebuggingOptions debuggingOptions,
ProtocolDiscovery? vmServiceDiscovery,
}) async {
@ -775,7 +769,7 @@ class IOSDevice extends Device {
final Future<Uri?> vmUrlFromMDns = MDnsVmServiceDiscovery.instance!.getVMServiceUriForLaunch(
packageId,
this,
usesIpv6: ipv6,
usesIpv6: debuggingOptions.ipv6,
useDeviceIPAsHost: isWirelesslyConnected,
);
@ -814,7 +808,6 @@ class IOSDevice extends Device {
required Directory bundle,
required DebuggingOptions debuggingOptions,
required List<String> launchArguments,
required bool ipv6,
required bool uninstallFirst,
bool skipInstall = false,
}) {
@ -845,7 +838,7 @@ class IOSDevice extends Device {
portForwarder: isWirelesslyConnected ? null : portForwarder,
hostPort: debuggingOptions.hostVmServicePort,
devicePort: debuggingOptions.deviceVmServicePort,
ipv6: ipv6,
ipv6: debuggingOptions.ipv6,
logger: _logger,
);
}

View File

@ -90,6 +90,7 @@ class IOSSimulatorUtils {
name: name,
simControl: _simControl,
simulatorCategory: device.category,
logger: _simControl._logger,
);
}).whereType<IOSSimulator>().toList();
}
@ -356,6 +357,7 @@ class IOSSimulator extends Device {
required this.name,
required this.simulatorCategory,
required SimControl simControl,
required super.logger,
}) : _simControl = simControl,
super(
category: Category.mobile,
@ -472,7 +474,6 @@ class IOSSimulator extends Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object?>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
if (!prebuiltApplication && package is BuildableIOSApp) {
@ -501,7 +502,7 @@ class IOSSimulator extends Device {
if (debuggingOptions.debuggingEnabled) {
vmServiceDiscovery = ProtocolDiscovery.vmService(
getLogReader(app: package),
ipv6: ipv6,
ipv6: debuggingOptions.ipv6,
hostPort: debuggingOptions.hostVmServicePort,
devicePort: debuggingOptions.deviceVmServicePort,
logger: globals.logger,

View File

@ -50,7 +50,6 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
String? target,
required bool stayResident,
required FlutterProject flutterProject,
required bool? ipv6,
required DebuggingOptions debuggingOptions,
UrlTunneller? urlTunneller,
required Logger logger,
@ -65,7 +64,6 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
target: target,
flutterProject: flutterProject,
debuggingOptions: debuggingOptions,
ipv6: ipv6,
stayResident: stayResident,
urlTunneller: urlTunneller,
machine: machine,
@ -89,7 +87,6 @@ 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,
@ -97,6 +94,7 @@ 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,
@ -108,7 +106,6 @@ class ResidentWebRunner extends ResidentRunner {
<FlutterDevice>[device],
target: target ?? fileSystem.path.join('lib', 'main.dart'),
debuggingOptions: debuggingOptions,
ipv6: ipv6,
stayResident: stayResident,
machine: machine,
devtoolsHandler: devtoolsHandler,
@ -195,6 +192,7 @@ 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();
@ -247,7 +245,6 @@ class ResidentWebRunner extends ResidentRunner {
Future<int> run({
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool enableDevTools = false, // ignored, we don't yet support devtools for web
String? route,
}) async {
final ApplicationPackage? package = await ApplicationPackageFactory.instance!.getPackageForPlatform(
@ -368,7 +365,6 @@ 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) {
@ -476,6 +472,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.');
unawaited(residentDevtoolsHandler!.hotRestart(flutterDevices));
// Don't track restart times for dart2js builds or web-server devices.
@ -603,7 +600,6 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false, // ignored, we don't yet support devtools for web
bool needsFullRestart = true,
}) async {
if (_chromiumLauncher != null) {
@ -682,13 +678,14 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
}
});
}
if (enableDevTools) {
// The method below is guaranteed never to return a failing future.
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
));
}
}
// 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 (websocketUri != null) {
if (debuggingOptions.vmserviceOutFile != null) {

View File

@ -99,7 +99,6 @@ class MacOSDesignedForIPadDevice extends DesktopDevice {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
// Only attaching to a running app launched from Xcode is supported.

View File

@ -95,7 +95,7 @@ class PreviewDeviceDiscovery extends PollingDeviceDiscovery {
class PreviewDevice extends Device {
PreviewDevice({
required ProcessManager processManager,
required Logger logger,
required super.logger,
required FileSystem fileSystem,
required Artifacts artifacts,
required File previewBinary,
@ -170,7 +170,6 @@ class PreviewDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, dynamic> platformArgs = const <String, dynamic>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
final Directory assetDirectory = _fileSystem.systemTempDirectory
@ -214,7 +213,7 @@ class PreviewDevice extends Device {
final ProtocolDiscovery vmServiceDiscovery = ProtocolDiscovery.vmService(_logReader,
devicePort: debuggingOptions.deviceVmServicePort,
hostPort: debuggingOptions.hostVmServicePort,
ipv6: ipv6,
ipv6: debuggingOptions.ipv6,
logger: _logger,
);
try {

View File

@ -19,6 +19,7 @@ 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';
@ -175,7 +176,7 @@ class ProxiedDevice extends Device {
required this.supportsScreenshot,
required this.supportsFastStart,
required bool supportsHardwareRendering,
required Logger logger,
required super.logger,
FileTransfer fileTransfer = const FileTransfer(),
}): _deltaFileTransfer = deltaFileTransfer,
_enableDdsProxy = enableDdsProxy,
@ -334,7 +335,6 @@ class ProxiedDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object?>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
final Map<String, Object?> result = _cast<Map<String, Object?>>(await connection.sendRequest('device.startApp', <String, Object?>{
@ -345,7 +345,7 @@ class ProxiedDevice extends Device {
'debuggingOptions': debuggingOptions.toJson(),
'platformArgs': platformArgs,
'prebuiltApplication': prebuiltApplication,
'ipv6': ipv6,
'ipv6': debuggingOptions.ipv6,
'userIdentifier': userIdentifier,
}));
final bool started = _cast<bool>(result['started']);
@ -748,7 +748,7 @@ Future<ServerSocket> _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 implements DartDevelopmentService {
class ProxiedDartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin implements DartDevelopmentService {
ProxiedDartDevelopmentService(
this.connection,
this.deviceId, {
@ -756,10 +756,11 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
required ProxiedPortForwarder proxiedPortForwarder,
required ProxiedPortForwarder devicePortForwarder,
@visibleForTesting DartDevelopmentService? localDds,
}) : _logger = logger,
}) :
_logger = logger,
_proxiedPortForwarder = proxiedPortForwarder,
_devicePortForwarder = devicePortForwarder,
_localDds = localDds ?? DartDevelopmentService();
_localDds = localDds ?? DartDevelopmentService(logger: logger);
final String deviceId;
@ -776,10 +777,9 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
/// 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<void> get done => _completer.future;
@ -792,11 +792,14 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
@override
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
required Logger logger,
int? hostPort,
FlutterDevice? device,
int? ddsPort,
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
@ -805,18 +808,24 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
_proxiedPortForwarder.originalRemotePort(vmServiceUri.port) ??
_devicePortForwarder.originalRemotePort(vmServiceUri.port);
if (remoteVMServicePort == null) {
_logger.printTrace('VM service port is not a forwarded port. Start DDS locally.');
Future<void> startLocalDds() async {
_ddsStartedLocally = true;
await _localDds.startDartDevelopmentService(
vmServiceUri,
logger: logger,
hostPort: hostPort,
ddsPort: ddsPort,
ipv6: ipv6,
disableServiceAuthCodes: disableServiceAuthCodes,
cacheStartupProfile: cacheStartupProfile,
enableDevTools: enableDevTools,
google3WorkspaceRoot: google3WorkspaceRoot,
devToolsServerAddress: devToolsServerAddress,
);
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;
}
@ -835,11 +844,19 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
// Ignore if we did not receive any event from the server.
},
));
remoteUriStr = _cast<String?>(await connection.sendRequest(method, <String, Object?>{
'deviceId': deviceId,
'vmServiceUri': remoteVMServiceUri.toString(),
'disableServiceAuthCodes': disableServiceAuthCodes,
}));
final Object? response = await connection.sendRequest(method, <String, Object?>{
'deviceId': deviceId,
'vmServiceUri': remoteVMServiceUri.toString(),
'disableServiceAuthCodes': disableServiceAuthCodes,
});
if (response is Map<String, Object?>) {
remoteUriStr = response['ddsUri'] as String?;
} else {
// For backwards compatibility in google3.
// TODO(bkonyi): remove once a newer version of the flutter_tool is rolled out.
remoteUriStr = _cast<String?>(response);
}
} on String catch (e) {
if (!e.contains(method)) {
rethrow;
@ -850,16 +867,7 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
if (remoteUriStr == null) {
_logger.printTrace('Remote daemon cannot start DDS. Start a local DDS instead.');
_ddsStartedLocally = true;
await _localDds.startDartDevelopmentService(
vmServiceUri,
logger: logger,
hostPort: hostPort,
ipv6: ipv6,
disableServiceAuthCodes: disableServiceAuthCodes,
cacheStartupProfile: cacheStartupProfile,
);
unawaited(_localDds.done.then(_completer.complete));
await startLocalDds();
return;
}
@ -869,7 +877,7 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
final Uri remoteUri = Uri.parse(remoteUriStr);
final int localPort = await _proxiedPortForwarder.forward(
remoteUri.port,
hostPort: hostPort,
hostPort: ddsPort,
ipv6: ipv6,
);
@ -885,7 +893,7 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
@override
Future<void> shutdown() async {
if (_ddsStartedLocally) {
await _localDds.shutdown();
_localDds.shutdown();
_ddsStartedLocally = false;
} else {
await connection.sendRequest('device.shutdownDartDevelopmentService', <String, Object?>{
@ -893,14 +901,6 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService {
});
}
}
@override
void setExternalDevToolsUri(Uri uri) {
connection.sendRequest('device.setExternalDevToolsUriForDartDevelopmentService', <String, Object?>{
'deviceId': deviceId,
'uri': uri.toString(),
});
}
}
class ProxiedVMServiceDiscoveryForAttach extends VMServiceDiscoveryForAttach {

View File

@ -2,6 +2,10 @@
// 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';
@ -110,18 +114,6 @@ 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<void> callServiceExtensions() async {
final List<FlutterDevice?> devicesWithExtension = await _devicesWithExtensions(flutterDevices);
await Future.wait(
@ -214,10 +206,12 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
},
);
} on Exception catch (e) {
_logger.printError(
'Failed to set DevTools server address: $e. Deep links to'
' DevTools will not show in Flutter errors.',
);
if (!_shutdown) {
_logger.printError(
'Failed to set DevTools server address: $e. Deep links to'
' DevTools will not show in Flutter errors.',
);
}
}
}
@ -266,11 +260,13 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
},
);
} on Exception catch (e) {
_logger.printError(e.toString());
_logger.printError(
'Failed to set vm service URI: $e. Deep links to DevTools'
' will not show in Flutter errors.',
);
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.',
);
}
}
}
@ -308,10 +304,10 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
@override
Future<void> shutdown() async {
if (_devToolsLauncher == null || _shutdown || !_served) {
_shutdown = true;
if (_devToolsLauncher == null || !_served) {
return;
}
_shutdown = true;
_readyToAnnounce = false;
await _devToolsLauncher.close();
}

View File

@ -4,7 +4,6 @@
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;
@ -15,6 +14,7 @@ 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,13 +252,9 @@ 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<void> completer = Completer<void>();
late StreamSubscription<void> subscription;
@ -270,11 +266,11 @@ class FlutterDevice {
isWaitingForVm = true;
bool existingDds = false;
FlutterVmService? service;
if (enableDds) {
if (debuggingOptions.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', st);
completer.completeError('failed to connect to $vmServiceUri $e', st);
}
}
// First check if the VM service is actually listening on vmServiceUri as
@ -286,7 +282,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');
completer.completeError('failed to connect to $vmServiceUri $exception');
}
return;
}
@ -295,17 +291,13 @@ 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.startDartDevelopmentService(
await device!.dds.startDartDevelopmentServiceFromDebuggingOptions(
vmServiceUri,
hostPort: ddsPort,
ipv6: ipv6,
disableServiceAuthCodes: disableServiceAuthCodes,
logger: globals.logger,
cacheStartupProfile: cacheStartupProfile,
debuggingOptions: debuggingOptions,
);
} on dds.DartDevelopmentServiceException catch (e, st) {
} on DartDevelopmentServiceException catch (e, st) {
if (!allowExistingDdsInstance ||
(e.errorCode != dds.DartDevelopmentServiceException.existingDdsInstanceError)) {
(e.errorCode != DartDevelopmentServiceException.existingDdsInstanceError)) {
handleError(e, st);
return;
} else {
@ -326,7 +318,7 @@ class FlutterDevice {
service = await Future.any<dynamic>(
<Future<dynamic>>[
connectToVmService(
enableDds ? (device!.dds.uri ?? vmServiceUri!): vmServiceUri!,
debuggingOptions.enableDds ? (device!.dds.uri ?? vmServiceUri!): vmServiceUri!,
reloadSources: reloadSources,
restart: restart,
compileExpression: compileExpression,
@ -343,7 +335,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');
completer.completeError('failed to connect to $vmServiceUri $exception');
}
return;
}
@ -472,7 +464,6 @@ class FlutterDevice {
platformArgs: platformArgs,
route: route,
prebuiltApplication: prebuiltMode,
ipv6: hotRunner.ipv6!,
userIdentifier: userIdentifier,
);
@ -538,7 +529,6 @@ class FlutterDevice {
platformArgs: platformArgs,
route: route,
prebuiltApplication: prebuiltMode,
ipv6: coldRunner.ipv6!,
userIdentifier: userIdentifier,
);
@ -648,6 +638,7 @@ 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
@ -1096,7 +1087,6 @@ abstract class ResidentRunner extends ResidentHandlers {
required this.target,
required this.debuggingOptions,
String? projectRootPath,
this.ipv6,
this.stayResident = true,
this.hotMode = true,
String? dillOutputPath,
@ -1119,6 +1109,7 @@ 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);
}
@ -1136,7 +1127,6 @@ 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;
@ -1148,6 +1138,7 @@ 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;
@ -1228,7 +1219,6 @@ abstract class ResidentRunner extends ResidentHandlers {
Future<int?> run({
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool enableDevTools = false,
String? route,
});
@ -1240,7 +1230,6 @@ abstract class ResidentRunner extends ResidentHandlers {
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false,
bool needsFullRestart = true,
});
@ -1306,19 +1295,21 @@ abstract class ResidentRunner extends ResidentHandlers {
@override
Future<void> 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
await shutdownDartDevelopmentService();
shutdownDartDevelopmentService();
}
@override
Future<void> detach() async {
// TODO(bkonyi): remove when ready to serve DevTools from DDS.
await residentDevtoolsHandler!.shutdown();
await stopEchoingDeviceLog();
await preExit();
await shutdownDartDevelopmentService();
shutdownDartDevelopmentService();
appFinished();
}
@ -1328,12 +1319,10 @@ abstract class ResidentRunner extends ResidentHandlers {
);
}
Future<void> shutdownDartDevelopmentService() async {
await Future.wait<void>(
flutterDevices.map<Future<void>>(
(FlutterDevice? device) => device?.device?.dds.shutdown() ?? Future<void>.value()
)
);
void shutdownDartDevelopmentService() {
for (final FlutterDevice device in flutterDevices) {
device.device?.dds.shutdown();
}
}
@protected
@ -1402,18 +1391,14 @@ 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();
@ -1503,7 +1488,8 @@ abstract class ResidentRunner extends ResidentHandlers {
bool get reportedDebuggers => _reportedDebuggers;
bool _reportedDebuggers = false;
void printDebuggerList({ bool includeVmService = true, bool includeDevtools = true }) {
void printDebuggerList({bool includeVmService = true, bool includeDevtools = true}) {
// TODO(bkonyi): update this logic when ready to serve DevTools from DDS.
final DevToolsServerAddress? devToolsServerAddress = residentDevtoolsHandler!.activeDevToolsServer;
if (!residentDevtoolsHandler!.readyToAnnounce) {
includeDevtools = false;
@ -1956,6 +1942,7 @@ 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

View File

@ -21,7 +21,6 @@ class ColdRunner extends ResidentRunner {
this.traceStartup = false,
this.awaitFirstFrameWhenTracing = true,
this.applicationBinary,
bool super.ipv6 = false,
super.stayResident,
super.machine,
super.devtoolsHandler,
@ -47,7 +46,6 @@ class ColdRunner extends ResidentRunner {
Future<int> run({
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool enableDevTools = false,
String? route,
}) async {
try {
@ -78,18 +76,18 @@ class ColdRunner extends ResidentRunner {
}
}
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 (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 (flutterDevices.first.vmServiceUris != null) {
@ -142,7 +140,6 @@ class ColdRunner extends ResidentRunner {
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false,
bool needsFullRestart = true,
}) async {
_didAttach = true;
@ -166,18 +163,8 @@ class ColdRunner extends ResidentRunner {
}
}
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 (debuggingEnabled && debuggingOptions.serveObservatory) {
await enableObservatory();
}
appStartedCompleter?.complete();
@ -202,13 +189,12 @@ class ColdRunner extends ResidentRunner {
for (final FlutterDevice? flutterDevice in flutterDevices) {
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();

View File

@ -86,7 +86,6 @@ class HotRunner extends ResidentRunner {
super.projectRootPath,
super.dillOutputPath,
super.stayResident,
bool super.ipv6 = false,
super.machine,
super.devtoolsHandler,
StopwatchFactory stopwatchFactory = const StopwatchFactory(),
@ -228,7 +227,6 @@ class HotRunner extends ResidentRunner {
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false,
bool needsFullRestart = true,
}) async {
_didAttach = true;
@ -253,7 +251,8 @@ class HotRunner extends ResidentRunner {
await enableObservatory();
}
if (enableDevTools) {
// 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,
@ -362,7 +361,6 @@ class HotRunner extends ResidentRunner {
Future<int> run({
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool enableDevTools = false,
String? route,
}) async {
await _calculateTargetPlatform();
@ -470,7 +468,6 @@ class HotRunner extends ResidentRunner {
return attach(
connectionInfoCompleter: connectionInfoCompleter,
appStartedCompleter: appStartedCompleter,
enableDevTools: enableDevTools,
needsFullRestart: false,
);
}
@ -790,7 +787,11 @@ 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(

View File

@ -489,7 +489,7 @@ abstract class FlutterCommand extends Command<void> {
defaultsTo: true,
help: 'Enable (or disable, with "--no-$kEnableDevTools") the launching of the '
'Flutter DevTools debugger and profiler. '
'If specified, "--$kDevToolsServerAddress" is ignored.'
'If "--no-$kEnableDevTools" is specified, "--$kDevToolsServerAddress" is ignored.'
);
argParser.addOption(
kDevToolsServerAddress,

View File

@ -414,6 +414,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
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;

View File

@ -6,7 +6,6 @@
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';
@ -70,7 +69,6 @@ FlutterPlatform installHook({
Device? integrationTestDevice,
String? integrationTestUserIdentifier,
TestTimeRecorder? testTimeRecorder,
UriConverter? uriConverter,
TestCompilerNativeAssetsBuilder? nativeAssetsBuilder,
BuildInfo? buildInfo,
}) {
@ -102,7 +100,6 @@ FlutterPlatform installHook({
integrationTestDevice: integrationTestDevice,
integrationTestUserIdentifier: integrationTestUserIdentifier,
testTimeRecorder: testTimeRecorder,
uriConverter: uriConverter,
nativeAssetsBuilder: nativeAssetsBuilder,
buildInfo: buildInfo,
);
@ -309,7 +306,6 @@ class FlutterPlatform extends PlatformPlugin {
this.integrationTestDevice,
this.integrationTestUserIdentifier,
this.testTimeRecorder,
this.uriConverter,
this.nativeAssetsBuilder,
this.buildInfo,
});
@ -331,9 +327,6 @@ 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
@ -462,7 +455,6 @@ class FlutterPlatform extends PlatformPlugin {
icudtlPath: icudtlPath,
compileExpression: _compileExpressionService,
fontConfigManager: _fontConfigManager,
uriConverter: uriConverter,
);
}

View File

@ -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,7 +43,6 @@ class FlutterTesterTestDevice extends TestDevice {
required this.icudtlPath,
required this.compileExpression,
required this.fontConfigManager,
required this.uriConverter,
}) : assert(!debuggingOptions.startPaused || enableVmService),
_gotProcessVmServiceUri = enableVmService
? Completer<Uri?>() : (Completer<Uri?>()..complete());
@ -64,8 +63,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<Uri?> _gotProcessVmServiceUri;
final Completer<int> _exitCode = Completer<int>();
@ -170,16 +169,16 @@ class FlutterTesterTestDevice extends TestDevice {
debuggingOptions.hostVmServicePort == detectedUri.port);
Uri? forwardingUri;
DartDevelopmentService? dds;
if (debuggingOptions.enableDds) {
logger.printTrace('test $id: Starting Dart Development Service');
dds = await startDds(
await _ddsLauncher.startDartDevelopmentServiceFromDebuggingOptions(
detectedUri,
uriConverter: uriConverter,
debuggingOptions: debuggingOptions,
);
forwardingUri = dds.uri;
logger.printTrace('test $id: Dart Development Service started at ${dds.uri}, forwarding to VM service at ${dds.remoteVmServiceUri}.');
forwardingUri = _ddsLauncher.uri;
logger.printTrace('test $id: Dart Development Service started at $forwardingUri, forwarding to VM service at $detectedUri.');
} else {
forwardingUri = detectedUri;
}
@ -201,7 +200,7 @@ class FlutterTesterTestDevice extends TestDevice {
if (debuggingOptions.startPaused && !machine!) {
logger.printStatus('The Dart VM service is listening on $forwardingUri');
await _startDevTools(forwardingUri, dds);
await _startDevTools(forwardingUri, _ddsLauncher);
logger.printStatus('');
logger.printStatus('The test process has been started. Set any relevant breakpoints and then resume the test in the debugger.');
}
@ -248,28 +247,6 @@ 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<DartDevelopmentService> startDds(Uri uri, {UriConverter? uriConverter}) {
return DartDevelopmentService.startDartDevelopmentService(
uri,
serviceUri: _ddsServiceUri,
enableAuthCodes: !debuggingOptions.disableServiceAuthCodes,
ipv6: host!.type == InternetAddressType.IPv6,
uriConverter: uriConverter,
);
}
@visibleForTesting
@protected
@ -285,6 +262,7 @@ class FlutterTesterTestDevice extends TestDevice {
);
}
// TODO(bkonyi): remove when ready to serve DevTools from DDS.
Future<void> _startDevTools(Uri forwardingUri, DartDevelopmentService? dds) async {
_devToolsLauncher = DevtoolsLauncher.instance;
logger.printTrace('test $id: Serving DevTools...');
@ -297,10 +275,6 @@ 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',

View File

@ -40,7 +40,6 @@ abstract class FlutterTestRunner {
String? tags,
String? excludeTags,
bool enableVmService = false,
bool ipv6 = false,
bool machine = false,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
@ -108,7 +107,6 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
String? tags,
String? excludeTags,
bool enableVmService = false,
bool ipv6 = false,
bool machine = false,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
@ -239,7 +237,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
..addAll(testFiles.map((Uri uri) => uri.toString()));
final InternetAddressType serverType =
ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4;
debuggingOptions.ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4;
final loader.FlutterPlatform platform = loader.installHook(
testWrapper: testWrapper,

View File

@ -46,7 +46,7 @@ class FlutterTesterDevice extends Device {
FlutterTesterDevice(super.id, {
required ProcessManager processManager,
required FlutterVersion flutterVersion,
required Logger logger,
required super.logger,
required FileSystem fileSystem,
required Artifacts artifacts,
}) : _processManager = processManager,
@ -135,7 +135,6 @@ class FlutterTesterDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
final BuildInfo buildInfo = debuggingOptions.buildInfo;
@ -193,7 +192,7 @@ class FlutterTesterDevice extends Device {
getLogReader(),
hostPort: debuggingOptions.hostVmServicePort,
devicePort: debuggingOptions.deviceVmServicePort,
ipv6: ipv6,
ipv6: debuggingOptions.ipv6,
logger: _logger,
);
_logReader.initializeProcess(_process!);

View File

@ -38,7 +38,7 @@ abstract class ChromiumDevice extends Device {
required String name,
required this.chromeLauncher,
required FileSystem fileSystem,
required Logger logger,
required super.logger,
}) : _fileSystem = fileSystem,
_logger = logger,
super(
@ -124,7 +124,6 @@ abstract class ChromiumDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object?>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
// See [ResidentWebRunner.run] in flutter_tools/lib/src/resident_web_runner.dart
@ -382,7 +381,7 @@ String parseVersionForWindows(String input) {
/// A special device type to allow serving for arbitrary browsers.
class WebServerDevice extends Device {
WebServerDevice({
required Logger logger,
required super.logger,
}) : _logger = logger,
super(
'web-server',
@ -460,7 +459,6 @@ class WebServerDevice extends Device {
required DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object?>{},
bool prebuiltApplication = false,
bool ipv6 = false,
String? userIdentifier,
}) async {
final String? url = platformArgs['uri'] as String?;

View File

@ -26,7 +26,6 @@ abstract class WebRunnerFactory {
String? target,
required bool stayResident,
required FlutterProject flutterProject,
required bool? ipv6,
required DebuggingOptions debuggingOptions,
UrlTunneller? urlTunneller,
required Logger logger,

View File

@ -73,7 +73,7 @@ void main() {
artifacts = Artifacts.test(fileSystem: testFileSystem);
stdio = FakeStdio();
terminal = FakeTerminal();
signals = Signals.test();
signals = FakeSignals();
processInfo = FakeProcessInfo();
testDeviceManager = TestDeviceManager(logger: logger);
});
@ -802,6 +802,13 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
Logger: () => logger,
DeviceManager: () => testDeviceManager,
MDnsVmServiceDiscovery: () => MDnsVmServiceDiscovery(
mdnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}),
preliminaryMDnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}),
logger: logger,
flutterUsage: TestUsage(),
analytics: const NoOpAnalytics(),
),
});
testUsingContext('exits when vm-service-port is specified and debug-port is not', () async {
@ -1394,11 +1401,14 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
@override
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
required Logger logger,
int? hostPort,
int? ddsPort,
FlutterDevice? device,
bool? ipv6,
bool? disableServiceAuthCodes,
bool enableDevTools = false,
bool cacheStartupProfile = false,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) async {}
@override

View File

@ -701,7 +701,8 @@ void main() {
final DaemonMessage startResponse = await broadcastOutput.firstWhere(_notEvent);
expect(startResponse.data['id'], 0);
expect(startResponse.data['error'], isNull);
final String? ddsUri = startResponse.data['result'] as String?;
final Map<String, Object?>? result = startResponse.data['result'] as Map<String, Object?>?;
final String? ddsUri = result!['ddsUri'] as String?;
expect(ddsUri, fakeDdsUri.toString());
expect(device.dds.startCalled, true);
expect(device.dds.startDisableServiceAuthCodes, false);
@ -1246,11 +1247,14 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
@override
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
required Logger logger,
int? hostPort,
int? ddsPort,
FlutterDevice? device,
bool? ipv6,
bool? disableServiceAuthCodes,
bool enableDevTools = false,
bool cacheStartupProfile = false,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) async {
startCalled = true;
startVMServiceUri = vmServiceUri;

View File

@ -640,7 +640,7 @@ class NeverEndingDriverService extends Fake implements DriverService {
final void Function() callback;
@override
Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async { }
Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions) async { }
@override
Future<int> startTest(
@ -670,7 +670,7 @@ class FailingFakeFlutterDriverFactory extends Fake implements FlutterDriverFacto
class FailingFakeDriverService extends Fake implements DriverService {
@override
Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions, bool ipv6) async { }
Future<void> reuseApplication(Uri vmServiceUri, Device device, DebuggingOptions debuggingOptions) async { }
@override
Future<int> startTest(

View File

@ -1544,16 +1544,13 @@ class CapturingAppDomain extends AppDomain {
String? projectRootPath,
String? packagesFilePath,
String? dillOutputPath,
bool ipv6 = false,
String? isolateFilter,
bool machine = true,
String? userIdentifier,
bool enableDevTools = true,
String? flavor,
HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
}) async {
this.userIdentifier = userIdentifier;
this.enableDevTools = enableDevTools;
enableDevTools = options.enableDevTools;
throwToolExit('');
}
}

View File

@ -213,13 +213,9 @@ class TestFlutterDevice extends FlutterDevice {
GetSkSLMethod? getSkSLMethod,
FlutterProject? flutterProject,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
bool enableDds = true,
bool cacheStartupProfile = false,
bool disableServiceAuthCodes = false,
required DebuggingOptions debuggingOptions,
int? hostVmServicePort,
int? ddsPort,
bool? ipv6 = false,
bool allowExistingDdsInstance = false,
required bool allowExistingDdsInstance,
}) async {
throw exception;
}

View File

@ -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<String> launchArguments = original.getIOSLaunchArguments(
EnvironmentType.physical,
null,
<String, Object?>{},
ipv6: true,
interfaceType: DeviceConnectionInterface.wireless,
);

View File

@ -33,6 +33,8 @@ 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,
@ -49,6 +51,7 @@ 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<void> completer = Completer<void>();
@ -95,6 +98,7 @@ 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,
@ -120,6 +124,7 @@ 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',
],
@ -151,6 +156,7 @@ 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', <String>[]),
@ -176,6 +182,7 @@ 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,

View File

@ -93,7 +93,7 @@ void main() {
final Device device = FakeDevice(LaunchResult.failed());
expect(
() => driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile), true),
() => driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: 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), true),
() async => driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: 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), true);
await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true));
final int testResult = await driverService.startTest(
'foo.test',
<String>['--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), true);
await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true));
final int testResult = await driverService.startTest(
'foo.test',
<String>['--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), true);
await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true));
final int testResult = await driverService.startTest(
'foo.test',
<String>['--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), true);
await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, enableDds: false, ipv6: 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), true);
await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: 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), true);
await driverService.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true));
await driverService.stop(writeSkslOnExit: fileSystem.file('out.json'));
expect(device.didStopApp, true);
@ -327,7 +327,6 @@ void main() {
Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'),
device,
DebuggingOptions.enabled(BuildInfo.debug),
false,
);
await driverService.stop();
});
@ -351,7 +350,6 @@ void main() {
Uri.parse('ws://127.0.0.1:63426/1UasC_ihpXY=/ws/'),
device,
DebuggingOptions.enabled(BuildInfo.debug),
false,
);
await driverService.stop();
});
@ -375,7 +373,6 @@ void main() {
Uri.parse('ws://127.0.0.1:63426/1UasC_ihpXY=/ws'),
device,
DebuggingOptions.enabled(BuildInfo.debug),
false,
);
await driverService.stop();
});
@ -399,7 +396,6 @@ void main() {
Uri.parse('ws://127.0.0.1:63426/wsasC_ihpXY=/ws'),
device,
DebuggingOptions.enabled(BuildInfo.debug),
false,
);
await driverService.stop();
});
@ -416,7 +412,6 @@ void main() {
Uri.parse('http://127.0.0.1:63426/1UasC_ihpXY=/'),
device,
DebuggingOptions.enabled(BuildInfo.debug),
false,
);
await driverService.stop();
});
@ -540,7 +535,9 @@ class FakeDevice extends Fake implements Device {
}
}
class FakeDartDevelopmentService extends Fake implements DartDevelopmentService {
class FakeDartDevelopmentService extends Fake
with DartDevelopmentServiceLocalOperationsMixin
implements DartDevelopmentService {
bool started = false;
bool disposed = false;
@ -550,11 +547,14 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
@override
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
required Logger logger,
int? hostPort,
FlutterDevice? device,
int? ddsPort,
bool? ipv6,
bool? disableServiceAuthCodes,
bool enableDevTools = false,
bool cacheStartupProfile = false,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) async {
started = true;
}

View File

@ -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), true);
await service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true));
await service.stop();
expect(FakeResidentRunner.instance.callLog, <String>[
'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), true);
await service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, webLaunchUrl: testUrl, ipv6: true));
await service.stop();
expect(service.webUri, Uri.parse(testUrl));
}, overrides: <Type, Generator>{
@ -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), true),
service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, webLaunchUrl: invalidTestUrl, ipv6: true)),
throwsA(isA<FormatException>()),
);
}, overrides: <Type, Generator>{
@ -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), true),
service.start(BuildInfo.profile, device, DebuggingOptions.enabled(BuildInfo.profile, ipv6: true)),
throwsA('This is a test error'),
);
}, overrides: <Type, Generator>{

View File

@ -102,7 +102,6 @@ void main() {
platformPluginRegistration: (FlutterPlatform platform) {
capturedPlatform = platform;
},
uriConverter: (String input) => '$input/test',
);
expect(identical(capturedPlatform, flutterPlatform), equals(true));
@ -119,7 +118,6 @@ void main() {
expect(flutterPlatform.updateGoldens, equals(true));
expect(flutterPlatform.testAssetDirectory, '/build/test');
expect(flutterPlatform.icudtlPath, equals('ghi'));
expect(flutterPlatform.uriConverter?.call('hello'), 'hello/test');
});
});

View File

@ -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,7 +48,6 @@ void main() {
processManager: processManager,
enableVmService: enableVmService,
dartEntrypointArgs: dartEntrypointArgs,
uriConverter: (String input) => '$input/converted',
enableImpeller: enableImpeller,
);
@ -198,6 +197,7 @@ void main() {
});
group('DDS', () {
late DDSLauncherCallback originalDdsLauncher;
setUp(() {
processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(
@ -221,26 +221,30 @@ void main() {
),
]);
device = createDevice(enableVmService: true);
originalDdsLauncher = ddsLauncherCallback;
ddsLauncherCallback = (Uri remoteVmServiceUri, {
required bool enableAuthCodes,
required bool ipv6,
required bool enableDevTools,
required List<String> 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('sets up UriConverter from context', () async {
await device.start('example.dill');
await device.vmServiceUri;
final FakeDartDevelopmentService dds = (device as TestFlutterTesterDevice).dds
as FakeDartDevelopmentService;
final String? result = dds
.uriConverter
?.call('test');
expect(result, 'test/converted');
final Uri? uri = await (device as TestFlutterTesterDevice).vmServiceUri;
expect(uri!.port, 1234);
});
});
}
@ -255,7 +259,6 @@ class TestFlutterTesterDevice extends FlutterTesterTestDevice {
required super.processManager,
required super.enableVmService,
required List<String> dartEntrypointArgs,
required UriConverter uriConverter,
required bool enableImpeller,
}) : super(
id: 999,
@ -279,27 +282,7 @@ class TestFlutterTesterDevice extends FlutterTesterTestDevice {
icudtlPath: null,
compileExpression: null,
fontConfigManager: FontConfigManager(),
uriConverter: uriConverter,
);
late DartDevelopmentService dds;
final Completer<Uri> _ddsServiceUriCompleter = Completer<Uri>();
Future<Uri> ddsServiceUriFuture() => _ddsServiceUriCompleter.future;
@override
Future<DartDevelopmentService> 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<FlutterVmService> connectToVmServiceImpl(
@ -319,18 +302,6 @@ class TestFlutterTesterDevice extends FlutterTesterTestDevice {
Future<StreamChannel<String>> get remoteChannel async => StreamChannelController<String>().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;

View File

@ -9,6 +9,7 @@ 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';
@ -38,6 +39,7 @@ void main() {
late FakeProcessManager fakeSuccessfulProcessManager;
late FakeProcessManager fakeFailedProcessManagerForHostAddress;
late File sshConfig;
final Logger logger = FakeLogger();
setUp(() {
memoryFileSystem = MemoryFileSystem.test();
@ -114,7 +116,7 @@ void main() {
required BuildMode mode,
}) async {
const String appName = 'app_name';
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123', logger: logger);
globals.fs.directory('fuchsia').createSync(recursive: true);
final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync();
pubspecFile.writeAsStringSync('name: $appName');
@ -186,7 +188,7 @@ void main() {
'start and stop prebuilt in release mode fails without session',
() async {
const String appName = 'app_name';
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123', logger: logger);
globals.fs.directory('fuchsia').createSync(recursive: true);
final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync();
pubspecFile.writeAsStringSync('name: $appName');
@ -216,7 +218,7 @@ void main() {
testUsingContext('start and stop prebuilt in release mode with session',
() async {
const String appName = 'app_name';
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123', logger: logger);
globals.fs.directory('fuchsia').createSync(recursive: true);
final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync();
pubspecFile.writeAsStringSync('name: $appName');
@ -409,7 +411,7 @@ void main() {
});
testUsingContext('fail when cant get host address', () async {
expect(() async => FuchsiaDeviceWithFakeDiscovery('123').hostAddress,
expect(() async => FuchsiaDeviceWithFakeDiscovery('123', logger: logger).hostAddress,
throwsToolExit(message: 'Failed to get local address, aborting.'));
}, overrides: <Type, Generator>{
Artifacts: () => artifacts,
@ -479,7 +481,7 @@ Process _createFakeProcess({
}
class FuchsiaDeviceWithFakeDiscovery extends FuchsiaDevice {
FuchsiaDeviceWithFakeDiscovery(super.id, {super.name = ''});
FuchsiaDeviceWithFakeDiscovery(super.id, {super.name = '', required super.logger});
@override
FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(

View File

@ -26,6 +26,7 @@ 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;
@ -58,6 +59,7 @@ void main() {
late MemoryFileSystem memoryFileSystem;
late File sshConfig;
late FakeProcessManager processManager;
final Logger logger = FakeLogger();
setUp(() {
memoryFileSystem = MemoryFileSystem.test();
@ -68,7 +70,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);
final FuchsiaDevice device = FuchsiaDevice(deviceId, name: name, logger: logger);
expect(device.id, deviceId);
expect(device.name, name);
@ -77,7 +79,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);
final FuchsiaDevice device = FuchsiaDevice(deviceId, name: name, logger: logger);
expect(device.supportsRuntimeMode(BuildMode.debug), true);
expect(device.supportsRuntimeMode(BuildMode.profile), true);
@ -157,7 +159,7 @@ void main() {
testUsingContext('disposing device disposes the portForwarder', () async {
final FakePortForwarder portForwarder = FakePortForwarder();
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
device.portForwarder = portForwarder;
await device.dispose();
@ -165,7 +167,7 @@ void main() {
});
testWithoutContext('default capabilities', () async {
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
final FlutterProject project =
FlutterProject.fromDirectoryTest(memoryFileSystem.currentDirectory);
memoryFileSystem.directory('fuchsia').createSync(recursive: true);
@ -178,13 +180,13 @@ void main() {
});
test('is ephemeral', () {
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(device.ephemeral, true);
});
testWithoutContext('supported for project', () async {
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
final FlutterProject project =
FlutterProject.fromDirectoryTest(memoryFileSystem.currentDirectory);
memoryFileSystem.directory('fuchsia').createSync(recursive: true);
@ -194,7 +196,7 @@ void main() {
});
testWithoutContext('not supported for project', () async {
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
final FlutterProject project =
FlutterProject.fromDirectoryTest(memoryFileSystem.currentDirectory);
memoryFileSystem.file('pubspec.yaml').createSync();
@ -204,7 +206,7 @@ void main() {
testUsingContext('targetPlatform does not throw when sshConfig is missing',
() async {
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64);
}, overrides: <Type, Generator>{
@ -219,7 +221,7 @@ void main() {
stdout: 'aarch64',
));
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64);
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
@ -233,7 +235,7 @@ void main() {
stdout: 'x86_64',
));
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(await device.targetPlatform, TargetPlatform.fuchsia_x64);
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
@ -254,7 +256,7 @@ void main() {
'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22',
));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger);
expect(await device.hostAddress, 'fe80::8c6c:2fff:fe3d:c5e1%25ethp0003');
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
@ -275,7 +277,7 @@ void main() {
exitCode: 1,
));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger);
await expectLater(() => device.hostAddress, throwsToolExit());
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
@ -295,7 +297,7 @@ void main() {
],
));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger);
expect(() async => device.hostAddress, throwsToolExit());
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
@ -307,6 +309,7 @@ void main() {
group('displays friendly error when', () {
late File artifactFile;
late FakeProcessManager processManager;
final Logger logger = FakeLogger();
setUp(() {
processManager = FakeProcessManager.empty();
@ -323,7 +326,7 @@ void main() {
'find /hub -name vmservice-port'
],
));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'device', logger: logger);
await expectLater(
device.servicePorts,
@ -352,6 +355,7 @@ void main() {
late FakeProcessManager processManager;
late File ffx;
late File sshConfig;
final Logger logger = FakeLogger();
setUp(() {
processManager = FakeProcessManager.empty();
@ -374,7 +378,7 @@ void main() {
stdout: exampleUtcLogs,
completer: lock,
));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger);
final DeviceLogReader reader =
device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
final List<String> logLines = <String>[];
@ -411,7 +415,7 @@ void main() {
stdout: exampleUtcLogs,
completer: lock,
));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger);
final DeviceLogReader reader =
device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
final List<String> logLines = <String>[];
@ -446,7 +450,7 @@ void main() {
stdout: exampleUtcLogs,
completer: lock,
));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger);
final DeviceLogReader reader = device.getLogReader();
final List<String> logLines = <String>[];
reader.logLines.listen((String line) {
@ -475,13 +479,14 @@ 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');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger);
expect(device.supportsScreenshot, true);
}, overrides: <Type, Generator>{
Platform: () => FakePlatform(),
@ -489,7 +494,7 @@ void main() {
});
testUsingContext('is not supported on Windows', () {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger);
expect(device.supportsScreenshot, false);
}, overrides: <Type, Generator>{
@ -500,7 +505,7 @@ void main() {
});
test("takeScreenshot throws if file isn't .ppm", () async {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger);
await expectLater(
() => device.takeScreenshot(globals.fs.file('file.invalid')),
throwsA(isA<Exception>().having(
@ -518,7 +523,7 @@ void main() {
'0.0.0.0',
'screencap > /tmp/screenshot.ppm',
], exitCode: 1, stderr: '<error-message>'));
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger);
await expectLater(
() => device.takeScreenshot(globals.fs.file('file.ppm')),
@ -540,7 +545,7 @@ void main() {
});
testUsingContext('takeScreenshot throws if scp failed', () async {
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger);
processManager.addCommand(const FakeCommand(
command: <String>[
'ssh',
@ -593,7 +598,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');
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger);
processManager.addCommand(const FakeCommand(
command: <String>[
'ssh',
@ -642,7 +647,7 @@ void main() {
}, testOn: 'posix');
testUsingContext('takeScreenshot returns', () async {
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester', logger: logger);
processManager.addCommand(const FakeCommand(
command: <String>[
'ssh',
@ -688,6 +693,7 @@ void main() {
group('portForwarder', () {
late FakeProcessManager processManager;
late File sshConfig;
final Logger logger = FakeLogger();
setUp(() {
processManager = FakeProcessManager.empty();
@ -697,7 +703,7 @@ void main() {
testUsingContext(
'`unforward` prints stdout and stderr if ssh command failed', () async {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester', logger: logger);
processManager.addCommand(const FakeCommand(
command: <String>[
'ssh',
@ -861,6 +867,7 @@ void main() {
group('sdkNameAndVersion: ', () {
late File sshConfig;
late FakeProcessManager processManager;
final Logger logger = FakeLogger();
setUp(() {
sshConfig = MemoryFileSystem.test().file('ssh_config')
@ -869,7 +876,7 @@ void main() {
});
testUsingContext('does not throw on non-existent ssh config', () async {
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(await device.sdkNameAndVersion, equals('Fuchsia'));
}, overrides: <Type, Generator>{
@ -887,7 +894,7 @@ void main() {
'123',
'cat /pkgfs/packages/build-info/0/data/version'
], stdout: 'version'));
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(await device.sdkNameAndVersion, equals('Fuchsia version'));
}, overrides: <Type, Generator>{
@ -907,7 +914,7 @@ void main() {
],
exitCode: 1,
));
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(await device.sdkNameAndVersion, equals('Fuchsia'));
}, overrides: <Type, Generator>{
@ -927,7 +934,7 @@ void main() {
'cat /pkgfs/packages/build-info/0/data/version'
],
));
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device');
final FuchsiaDevice device = FuchsiaDevice('123', name: 'device', logger: logger);
expect(await device.sdkNameAndVersion, equals('Fuchsia'));
}, overrides: <Type, Generator>{
@ -1041,11 +1048,14 @@ class FakeDartDevelopmentService extends Fake
@override
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
required Logger logger,
int? hostPort,
FlutterDevice? device,
int? ddsPort,
bool? ipv6,
bool? disableServiceAuthCodes,
bool cacheStartupProfile = false,
bool enableDevTools = false,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) async {}
@override

View File

@ -150,12 +150,10 @@ class TestFlutterDevice extends FlutterDevice {
GetSkSLMethod? getSkSLMethod,
FlutterProject? flutterProject,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
bool disableServiceAuthCodes = false,
bool enableDds = true,
bool cacheStartupProfile = false,
bool? ipv6 = false,
required DebuggingOptions debuggingOptions,
int? hostVmServicePort,
int? ddsPort,
bool? ipv6 = false,
bool enableDevTools = false,
bool allowExistingDdsInstance = false,
}) async {
throw exception;

View File

@ -137,8 +137,7 @@ void main() {
..writeAsStringSync('\n');
final FakeDevice device = FakeDevice();
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(device, generator: residentCompiler, buildInfo: BuildInfo.debug, developmentShaderCompiler: const FakeShaderCompiler())
..devFS = FakeDevFs(),
FakeFlutterDevice(device),
];
final OperationResult result = await HotRunner(
devices,
@ -146,7 +145,6 @@ void main() {
target: 'main.dart',
devtoolsHandler: createNoOpHandler,
analytics: fakeAnalytics,
).restart(fullRestart: true);
expect(result.isOk, false);
expect(result.message, 'setupHotRestart failed');

View File

@ -37,6 +37,7 @@ void main() {
late FakePlatform osx;
late FileSystemUtils fsUtils;
late MemoryFileSystem fileSystem;
final Logger logger = FakeLogger();
setUp(() {
osx = FakePlatform(
@ -62,6 +63,7 @@ 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);
@ -87,6 +89,7 @@ void main() {
name: 'iPhone 11',
simControl: FakeSimControl(),
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-14-4',
logger: logger,
);
expect(simulator.supportsRuntimeMode(BuildMode.debug), true);
@ -113,6 +116,7 @@ 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: <Type, Generator>{
@ -130,6 +134,7 @@ 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: <Type, Generator>{
@ -154,6 +159,7 @@ void main() {
name: 'iPhone SE',
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
simControl: simControl,
logger: logger,
);
expect(await device.sdkMajorVersion, 11);
@ -165,6 +171,7 @@ void main() {
name: 'iPhone SE',
simulatorCategory: 'iOS 11.2',
simControl: simControl,
logger: logger,
);
expect(await device.sdkMajorVersion, 11);
@ -176,6 +183,7 @@ void main() {
name: 'iPhone SE',
simulatorCategory: 'iOS 11.2',
simControl: simControl,
logger: logger,
);
expect(device.category, Category.mobile);
@ -195,6 +203,7 @@ void main() {
name: 'Apple TV',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.tvOS-14-5',
logger: logger,
);
expect(simulator.isSupported(), false);
}, overrides: <Type, Generator>{
@ -209,6 +218,7 @@ void main() {
name: 'Apple Watch',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.watchOS-8-0',
logger: logger,
).isSupported(), false);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -222,6 +232,7 @@ void main() {
name: 'iPad 2',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
).isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -235,6 +246,7 @@ void main() {
name: 'iPad Retina',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
).isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -248,6 +260,7 @@ void main() {
name: 'iPhone 5',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
).isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -261,6 +274,7 @@ void main() {
name: 'iPhone 5s',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
).isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -274,6 +288,7 @@ void main() {
name: 'iPhone SE',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
).isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -287,6 +302,7 @@ void main() {
name: 'iPhone 7 Plus',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
).isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -300,6 +316,7 @@ void main() {
name: 'iPhone X',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
).isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
@ -337,6 +354,7 @@ 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');
@ -360,6 +378,7 @@ void main() {
name: 'iPhone SE',
simulatorCategory: 'iOS 9.3',
simControl: simControl,
logger: logger,
);
fakeProcessManager.addCommand(const FakeCommand(command: <String>[
'tail',
@ -387,6 +406,7 @@ 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 '
@ -421,6 +441,7 @@ 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 '
@ -485,6 +506,7 @@ 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),
@ -520,6 +542,7 @@ 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),
@ -568,6 +591,7 @@ 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),
@ -640,6 +664,7 @@ 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),
@ -683,6 +708,7 @@ 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),
@ -824,6 +850,7 @@ 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);
@ -908,6 +935,7 @@ 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);
@ -1086,6 +1114,7 @@ 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');
@ -1115,6 +1144,7 @@ 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;
@ -1146,6 +1176,7 @@ 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');
@ -1218,6 +1249,7 @@ 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');
@ -1268,6 +1300,7 @@ flutter:
name: 'iPhone 11',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
);
expect(simulator.isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
@ -1288,6 +1321,7 @@ flutter:
name: 'iPhone 11',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
);
expect(simulator.isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
@ -1306,6 +1340,7 @@ flutter:
name: 'iPhone 11',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
);
expect(simulator.isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
@ -1320,6 +1355,7 @@ flutter:
name: 'iPhone 11',
simControl: simControl,
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
logger: logger,
);
expect(simulator.createDevFSWriter(null, ''), isA<LocalDevFSWriter>());

View File

@ -17,6 +17,7 @@ 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';
@ -644,9 +645,8 @@ void main() {
final Future<void> startFuture = dds.startDartDevelopmentService(
Uri.parse('http://127.0.0.1:100/fake'),
disableServiceAuthCodes: true,
hostPort: 150,
ddsPort: 150,
ipv6: false,
logger: bufferLogger,
);
final DaemonMessage startMessage = await broadcastOutput.first;
@ -658,7 +658,9 @@ void main() {
'disableServiceAuthCodes': true,
});
serverDaemonConnection.sendResponse(startMessage.data['id']!, 'http://127.0.0.1:300/remote');
serverDaemonConnection.sendResponse( startMessage.data['id']!, const <String, Object?>{
'ddsUri': 'http://127.0.0.1:300/remote',
});
await startFuture;
expect(portForwarder.receivedLocalForwardedPort, 100);
@ -701,9 +703,8 @@ void main() {
final Future<void> startFuture = dds.startDartDevelopmentService(
Uri.parse('http://127.0.0.1:100/fake'),
disableServiceAuthCodes: true,
hostPort: 150,
ddsPort: 150,
ipv6: false,
logger: bufferLogger,
);
final DaemonMessage startMessage = await broadcastOutput.first;
@ -715,7 +716,9 @@ void main() {
'disableServiceAuthCodes': true,
});
serverDaemonConnection.sendResponse(startMessage.data['id']!, 'http://127.0.0.1:300/remote');
serverDaemonConnection.sendResponse(startMessage.data['id']!, <String, Object?>{
'ddsUri': 'http://127.0.0.1:300/remote',
});
await startFuture;
expect(portForwarder.receivedLocalForwardedPort, 100);
@ -758,9 +761,8 @@ void main() {
await dds.startDartDevelopmentService(
Uri.parse('http://127.0.0.1:100/fake'),
disableServiceAuthCodes: true,
hostPort: 150,
ddsPort: 150,
ipv6: false,
logger: bufferLogger,
);
expect(localDds.startCalled, true);
@ -797,9 +799,8 @@ void main() {
final Future<void> startFuture = dds.startDartDevelopmentService(
Uri.parse('http://127.0.0.1:100/fake'),
disableServiceAuthCodes: true,
hostPort: 150,
ddsPort: 150,
ipv6: false,
logger: bufferLogger,
);
expect(localDds.startCalled, false);
@ -1178,11 +1179,14 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
@override
Future<void> startDartDevelopmentService(
Uri vmServiceUri, {
required Logger logger,
int? hostPort,
FlutterDevice? device,
int? ddsPort,
bool? ipv6,
bool? disableServiceAuthCodes,
bool enableDevTools = false,
bool cacheStartupProfile = false,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) async {
startCalled = true;
startUri = vmServiceUri;

View File

@ -469,12 +469,14 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
@override
Future<void> startDartDevelopmentService(
Uri observatoryUri, {
required Logger logger,
int? hostPort,
bool? ipv6,
Uri vmServiceUri, {
int? ddsPort,
bool? disableServiceAuthCodes,
bool? ipv6,
bool enableDevTools = true,
bool cacheStartupProfile = false,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) async {
started = true;
}
@ -483,7 +485,4 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
Future<void> shutdown() async {
disposed = true;
}
@override
void setExternalDevToolsUri(Uri uri) {}
}

View File

@ -4,7 +4,6 @@
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';
@ -151,11 +150,16 @@ const FakeVmServiceRequest evictShader = FakeVmServiceRequest(
}
);
const DartDevelopmentServiceInstance fakeDartDevelopmentServiceInstance = (
process: null,
serviceUri: null,
devToolsUri: null,
dtdUri: null,
);
final Uri testUri = Uri.parse('foo://bar');
// This implements [dds.DartDevelopmentService], not the [DartDevelopmentService]
// interface from package:flutter_tools.
class FakeDartDevelopmentService extends Fake implements dds.DartDevelopmentService {
class FakeDartDevelopmentService extends Fake with DartDevelopmentServiceLocalOperationsMixin implements DartDevelopmentService {
@override
Future<void> get done => Future<void>.value();
@ -163,21 +167,15 @@ class FakeDartDevelopmentService extends Fake implements dds.DartDevelopmentServ
Uri? get uri => null;
}
class FakeDartDevelopmentServiceException implements dds.DartDevelopmentServiceException {
class FakeDartDevelopmentServiceException implements DartDevelopmentServiceException {
FakeDartDevelopmentServiceException({this.message = defaultMessage});
@override
final int errorCode = dds.DartDevelopmentServiceException.existingDdsInstanceError;
final int errorCode = DartDevelopmentServiceException.existingDdsInstanceError;
@override
final String message;
static const String defaultMessage = 'A DDS instance is already connected at http://localhost:8181';
@override
Map<String, Object?> toJson() => <String, Object?>{
'error_code': errorCode,
'message': message,
};
}
class TestFlutterDevice extends FlutterDevice {
@ -272,13 +270,10 @@ 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? ipv6 = false,
bool allowExistingDdsInstance = false,
}) async { }
@override
@ -317,16 +312,13 @@ class FakeDelegateFlutterDevice extends FlutterDevice {
Future<void> connect({
ReloadSources? reloadSources,
Restart? restart,
bool enableDds = true,
bool cacheStartupProfile = false,
bool disableServiceAuthCodes = false,
bool ipv6 = false,
CompileExpression? compileExpression,
GetSkSLMethod? getSkSLMethod,
FlutterProject? flutterProject,
int? hostVmServicePort,
int? ddsPort,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
required DebuggingOptions debuggingOptions,
int? hostVmServicePort,
bool? ipv6 = false,
bool allowExistingDdsInstance = false,
}) async { }
@ -435,7 +427,7 @@ class FakeDevice extends Fake implements Device {
String get name => 'FakeDevice';
@override
late DartDevelopmentService dds;
late DartDevelopmentService dds = FakeDartDevelopmentService();
@override
Future<void> dispose() async {

View File

@ -4,12 +4,10 @@
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;
@ -65,8 +63,8 @@ void main() {
stayResident: false,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
target: 'main.dart',
analytics: fakeAnalytics,
devtoolsHandler: createNoOpHandler,
analytics: globals.analytics,
);
}, overrides: <Type, Generator>{
Analytics: () => FakeAnalytics(),
@ -90,7 +88,6 @@ void main() {
final Future<int?> result = residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
);
final Future<DebugConnectionInfo> connectionInfo = futureConnectionInfo.future;
@ -122,7 +119,7 @@ void main() {
);
flutterDevice.generator = residentCompiler;
expect(await residentRunner.run(enableDevTools: true), 0);
expect(await residentRunner.run(), 0);
expect(residentCompiler.didSuppressErrors, true);
expect(fakeVmServiceHost?.hasRemainingExpectations, false);
}));
@ -216,7 +213,7 @@ void main() {
);
flutterDevice.generator = residentCompiler;
expect(await residentRunner.run(enableDevTools: true), 0);
expect(await residentRunner.run(), 0);
expect(residentCompiler.didSuppressErrors, false);
expect(fakeVmServiceHost?.hasRemainingExpectations, false);
}));
@ -279,7 +276,6 @@ void main() {
final Future<int?> result = residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
);
final Future<DebugConnectionInfo> connectionInfo = futureConnectionInfo.future;
@ -301,7 +297,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
flutterDevice.reportError = vm_service.RPCError('something bad happened', 666, '');
@ -343,7 +338,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
@ -389,7 +383,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
flutterDevice.reportError = vm_service.RPCError('something bad happened', kIsolateReloadBarred, '');
@ -433,13 +426,15 @@ void main() {
],
stayResident: false,
target: 'main.dart',
debuggingOptions: DebuggingOptions.enabled(const BuildInfo(
BuildMode.debug, '', treeShakeIcons: false, extraFrontEndOptions: <String>[
'--enable-experiment=non-nullable',
],
packageConfigPath: '.dart_tool/package_config.json'
)),
devtoolsHandler: createNoOpHandler,
debuggingOptions: DebuggingOptions.enabled(
const BuildInfo(
BuildMode.debug, '', treeShakeIcons: false, extraFrontEndOptions: <String>[
'--enable-experiment=non-nullable',
],
packageConfigPath: '.dart_tool/package_config.json',
),
enableDevTools: false,
),
analytics: fakeAnalytics,
);
final Completer<DebugConnectionInfo> futureConnectionInfo = Completer<DebugConnectionInfo>.sync();
@ -447,7 +442,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
flutterDevice.reportError = vm_service.RPCError('something bad happened', 666, '');
@ -512,7 +506,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
flutterDevice.report = UpdateFSReport(success: true);
@ -570,7 +563,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
flutterDevice.report = UpdateFSReport(success: true, invalidatedSourcesCount: 1);
@ -634,7 +626,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
flutterDevice.report = UpdateFSReport(success: true, invalidatedSourcesCount: 1);
@ -694,7 +685,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
@ -785,7 +775,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
@ -847,7 +836,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
final OperationResult result = await residentRunner.restart(fullRestart: true);
@ -937,7 +925,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
final OperationResult result = await residentRunner.restart(fullRestart: true);
@ -1058,7 +1045,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await residentRunner.restart(fullRestart: true);
@ -1078,7 +1064,6 @@ void main() {
unawaited(residentRunner.attach(
appStartedCompleter: futureAppStart,
connectionInfoCompleter: futureConnectionInfo,
enableDevTools: true,
));
await futureAppStart.future;
flutterDevice.reportError = vm_service.RPCError('something bad happened', 666, '');
@ -1521,7 +1506,7 @@ flutter:
flutterDevice,
],
stayResident: false,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo', enableDevTools: false),
target: 'main.dart',
devtoolsHandler: createNoOpHandler,
);
@ -1571,7 +1556,7 @@ flutter:
analytics: fakeAnalytics,
);
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(fakeVmServiceHost?.hasRemainingExpectations, false);
expect(await globals.fs.file('foo').readAsString(), testUri.toString());
@ -1602,7 +1587,7 @@ flutter:
);
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill')).readAsString(), 'ABC');
}));
@ -1633,7 +1618,7 @@ flutter:
);
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(await globals.fs.file(globals.fs.path.join(
'build', '187ef4436122d1cc2f40dc2b92f0eba0.cache.dill')).readAsString(), 'ABC');
@ -1665,7 +1650,7 @@ flutter:
);
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(await globals.fs.file(globals.fs.path.join(
'build', 'cache.dill')).readAsString(), 'ABC');
@ -1689,7 +1674,7 @@ flutter:
);
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(await globals.fs.file(globals.fs.path.join(
'build', 'cache.dill.track.dill')).readAsString(), 'ABC');
@ -1714,7 +1699,7 @@ flutter:
);
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(globals.fs.file(globals.fs.path.join('build', 'cache.dill')), isNot(exists));
}));
@ -1743,7 +1728,7 @@ flutter:
);
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill.track.dill')).readAsString(), 'ABC');
}));
@ -1786,7 +1771,7 @@ flutter:
analytics: fakeAnalytics,
);
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(testLogger.errorText, contains('Failed to write vmservice-out-file at foo'));
expect(fakeVmServiceHost?.hasRemainingExpectations, false);
@ -1805,11 +1790,11 @@ flutter:
],
stayResident: false,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'),
target: 'main.dart',
devtoolsHandler: createNoOpHandler,
target: 'main.dart',
);
await residentRunner.run(enableDevTools: true);
await residentRunner.run();
expect(await globals.fs.file('foo').readAsString(), testUri.toString());
expect(fakeVmServiceHost?.hasRemainingExpectations, false);
@ -1975,61 +1960,19 @@ flutter:
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Handle existing VM service clients DDS error', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice()
..dds = DartDevelopmentService();
ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List<String> cachedUserTags = const <String>[], 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<Uri>.value(testUri),
);
bool caught = false;
final Completer<void>done = Completer<void>();
runZonedGuarded(() {
flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete());
}, (Object e, StackTrace st) {
expect(e, isA<ToolExit>());
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: <Type, Generator>{
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: <VmServiceExpectation>[]).vmService,
}));
testUsingContext('Uses existing DDS URI from exception field', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice()
..dds = DartDevelopmentService();
ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List<String> cachedUserTags = const <String>[], dds.UriConverter? uriConverter}) {
throw dds.DartDevelopmentServiceException.existingDdsInstance(
..dds = DartDevelopmentService(logger: testLogger);
ddsLauncherCallback = (Uri uri,
{bool enableDevTools = false,
bool enableAuthCodes = true,
bool ipv6 = false, Uri? serviceUri,
List<String> cachedUserTags = const <String>[],
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) {
throw DartDevelopmentServiceException.existingDdsInstance(
'Existing DDS at http://localhost/existingDdsInMessage.',
ddsUri: Uri.parse('http://localhost/existingDdsInField'),
);
@ -2040,7 +1983,10 @@ flutter:
);
final Completer<void> done = Completer<void>();
unawaited(runZonedGuarded(
() => flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete()),
() => flutterDevice.connect(
allowExistingDdsInstance: true,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
).then((_) => done.complete()),
(_, __) => done.complete(),
));
await done.future;
@ -2052,41 +1998,7 @@ flutter:
CompileExpression? compileExpression,
GetSkSLMethod? getSkSLMethod,
FlutterProject? flutterProject,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
io.CompressionOptions? compression,
Device? device,
required Logger logger,
}) async => FakeVmServiceHost(requests: <VmServiceExpectation>[]).vmService,
}));
testUsingContext('Falls back to existing DDS URI from exception message', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice()
..dds = DartDevelopmentService();
ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List<String> cachedUserTags = const <String>[], dds.UriConverter? uriConverter}) {
throw dds.DartDevelopmentServiceException.existingDdsInstance(
'Existing DDS at http://localhost/existingDdsInMessage.',
);
};
final TestFlutterDevice flutterDevice = TestFlutterDevice(
device,
vmServiceUris: Stream<Uri>.value(testUri),
);
final Completer<void>done = Completer<void>();
unawaited(runZonedGuarded(
() => flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete()),
(_, __) => done.complete(),
));
await done.future;
expect(device.dds.uri, Uri.parse('http://localhost/existingDdsInMessage'));
}, overrides: <Type, Generator>{
VMServiceConnector: () => (Uri httpUri, {
ReloadSources? reloadSources,
Restart? restart,
CompileExpression? compileExpression,
GetSkSLMethod? getSkSLMethod,
FlutterProject? flutterProject,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
io.CompressionOptions? compression,
Device? device,
required Logger logger,
@ -2096,23 +2008,34 @@ flutter:
testUsingContext('Host VM service ipv6 defaults', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice()
..dds = DartDevelopmentService();
..dds = DartDevelopmentService(logger: testLogger);
final Completer<void>done = Completer<void>();
ddsLauncherCallback = (Uri uri, {bool enableAuthCodes = true, bool ipv6 = false, Uri? serviceUri, List<String> cachedUserTags = const <String>[], dds.UriConverter? uriConverter}) async {
ddsLauncherCallback = (Uri uri,
{bool enableDevTools = false,
bool enableAuthCodes = true,
bool ipv6 = false, Uri? serviceUri,
List<String> cachedUserTags = const <String>[],
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) 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 FakeDartDevelopmentService();
return fakeDartDevelopmentServiceInstance;
};
final TestFlutterDevice flutterDevice = TestFlutterDevice(
device,
vmServiceUris: Stream<Uri>.value(testUri),
);
await flutterDevice.connect(allowExistingDdsInstance: true, ipv6: true, disableServiceAuthCodes: true);
await flutterDevice.connect(
allowExistingDdsInstance: true,
debuggingOptions: DebuggingOptions.enabled(
BuildInfo.debug, disableServiceAuthCodes: true, ipv6: true,
)
);
await done.future;
}, overrides: <Type, Generator>{
VMServiceConnector: () => (Uri httpUri, {
@ -2128,67 +2051,25 @@ flutter:
}) async => FakeVmServiceHost(requests: <VmServiceExpectation>[]).vmService,
}));
testUsingContext('Context includes URI converter', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice()
..dds = DartDevelopmentService();
final Completer<void>done = Completer<void>();
ddsLauncherCallback = (
Uri uri, {
bool enableAuthCodes = false,
bool ipv6 = false,
Uri? serviceUri,
List<String> cachedUserTags = const <String>[],
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<Uri>.value(testUri),
);
await flutterDevice.connect(allowExistingDdsInstance: true, ipv6: true, disableServiceAuthCodes: true);
await done.future;
}, overrides: <Type, Generator>{
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: <VmServiceExpectation>[]).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();
..dds = DartDevelopmentService(logger: testLogger);
ddsLauncherCallback = (
Uri uri, {
bool enableDevTools = false,
bool enableAuthCodes = false,
bool ipv6 = false,
Uri? serviceUri,
List<String> cachedUserTags = const <String>[],
dds.UriConverter? uriConverter,
String? google3WorkspaceRoot,
Uri? devToolsServerAddress,
}) {
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(
@ -2198,7 +2079,10 @@ flutter:
bool caught = false;
final Completer<void>done = Completer<void>();
runZonedGuarded(() {
flutterDevice.connect(allowExistingDdsInstance: true).then((_) => done.complete());
flutterDevice.connect(
allowExistingDdsInstance: true,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, enableDevTools: false),
).then((_) => done.complete());
}, (Object e, StackTrace st) {
expect(e, isA<StateError>());
expect((e as StateError).message, contains('No URI'));
@ -2236,6 +2120,7 @@ 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(
<FlutterDevice>[

View File

@ -50,7 +50,6 @@ void main() {
mockFlutterDevice,
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -81,7 +80,6 @@ void main() {
mockFlutterDevice,
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -107,7 +105,6 @@ void main() {
mockFlutterDevice,
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -132,7 +129,6 @@ void main() {
mockFlutterDevice,
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -162,7 +158,6 @@ void main() {
mockFlutterDevice,
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),

View File

@ -162,7 +162,6 @@ void main() {
flutterProject:
FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -195,7 +194,6 @@ void main() {
FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions:
DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -215,7 +213,6 @@ void main() {
flutterProject:
FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -229,7 +226,6 @@ void main() {
flutterProject:
FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
ipv6: true,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -362,13 +358,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);
@ -389,13 +385,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);
@ -591,12 +587,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());
@ -1012,7 +1008,7 @@ void main() {
testUsingContext('cleanup of resources is safe to call multiple times',
() async {
final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
mockDevice.dds = DartDevelopmentService();
mockDevice.dds = DartDevelopmentService(logger: test_fakes.FakeLogger());
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations,
]);
@ -1115,12 +1111,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<DebugConnectionInfo> connectionInfoCompleter =
@ -1164,12 +1160,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<DebugConnectionInfo> connectionInfoCompleter =
@ -1206,13 +1202,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.
@ -1410,7 +1406,6 @@ 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()),
@ -1719,13 +1714,11 @@ 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

View File

@ -191,6 +191,7 @@ 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;

View File

@ -7,6 +7,7 @@ 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';
@ -25,6 +26,7 @@ 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',
@ -1308,11 +1310,13 @@ 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;
@ -1332,6 +1336,9 @@ class FakeDevice extends Fake implements Device {
@override
String get name => 'Fake Device';
@override
DartDevelopmentService dds = DartDevelopmentService(logger: FakeLogger());
@override
Future<void> takeScreenshot(File file) async {
if (!supportsScreenshot) {
@ -1339,7 +1346,6 @@ class FakeDevice extends Fake implements Device {
}
file.writeAsBytesSync(<int>[1, 2, 3, 4]);
}
}
TerminalHandler setUpTerminalHandler(List<FakeVmServiceRequest> requests, {

View File

@ -9,6 +9,8 @@ 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<FakeDeviceJsonData> fakeDevices = <FakeDeviceJsonData>[
@ -129,6 +131,7 @@ class FakeDevice extends Device {
platformType: type,
category: Category.mobile,
ephemeral: ephemeral,
logger: FakeLogger(),
);
final bool _isSupported;

View File

@ -741,6 +741,12 @@ 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<List<int>> {
@override
Future<Object?> addStream(Stream<List<int>> stream) async => throw const SocketException('Bad pipe');