mirror of
https://github.com/flutter/flutter
synced 2024-07-16 10:29:14 +00:00
Add a --print-dtd
flag to print the DTD address served by DevTools server (#144272)
This commit is contained in:
parent
dbdcead932
commit
31f4f2b6c0
|
@ -3,7 +3,6 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
import 'runner.dart' as runner;
|
||||
import 'src/artifacts.dart';
|
||||
import 'src/base/context.dart';
|
||||
import 'src/base/io.dart';
|
||||
import 'src/base/logger.dart';
|
||||
|
@ -110,7 +109,7 @@ Future<void> main(List<String> args) async {
|
|||
// devtools source code.
|
||||
DevtoolsLauncher: () => DevtoolsServerLauncher(
|
||||
processManager: globals.processManager,
|
||||
dartExecutable: globals.artifacts!.getArtifactPath(Artifact.engineDartBinary),
|
||||
artifacts: globals.artifacts!,
|
||||
logger: globals.logger,
|
||||
botDetector: globals.botDetector,
|
||||
),
|
||||
|
|
|
@ -218,7 +218,7 @@ Future<T> runInContext<T>(
|
|||
),
|
||||
DevtoolsLauncher: () => DevtoolsServerLauncher(
|
||||
processManager: globals.processManager,
|
||||
dartExecutable: globals.artifacts!.getArtifactPath(Artifact.engineDartBinary),
|
||||
artifacts: globals.artifacts!,
|
||||
logger: globals.logger,
|
||||
botDetector: globals.botDetector,
|
||||
),
|
||||
|
|
|
@ -2,13 +2,12 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:process/process.dart';
|
||||
|
||||
import 'artifacts.dart';
|
||||
import 'base/bot_detector.dart';
|
||||
import 'base/common.dart';
|
||||
import 'base/io.dart' as io;
|
||||
|
@ -16,21 +15,22 @@ import 'base/logger.dart';
|
|||
import 'convert.dart';
|
||||
import 'resident_runner.dart';
|
||||
|
||||
/// An implementation of the devtools launcher that uses `pub global activate` to
|
||||
/// start a server instance.
|
||||
/// An implementation of the devtools launcher that uses `dart devtools` to
|
||||
/// start a DevTools server instance.
|
||||
class DevtoolsServerLauncher extends DevtoolsLauncher {
|
||||
DevtoolsServerLauncher({
|
||||
required ProcessManager processManager,
|
||||
required String dartExecutable,
|
||||
required Logger logger,
|
||||
required BotDetector botDetector,
|
||||
required Artifacts artifacts,
|
||||
}) : _processManager = processManager,
|
||||
_dartExecutable = dartExecutable,
|
||||
_logger = logger,
|
||||
_botDetector = botDetector;
|
||||
_botDetector = botDetector,
|
||||
_artifacts = artifacts;
|
||||
|
||||
final ProcessManager _processManager;
|
||||
final String _dartExecutable;
|
||||
final Artifacts _artifacts;
|
||||
late final String _dartExecutable = _artifacts.getArtifactPath(Artifact.engineDartBinary);
|
||||
final Logger _logger;
|
||||
final BotDetector _botDetector;
|
||||
final Completer<void> _processStartCompleter = Completer<void>();
|
||||
|
@ -42,6 +42,8 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
|
|||
|
||||
static final RegExp _serveDevToolsPattern =
|
||||
RegExp(r'Serving DevTools at ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+?)\.?$');
|
||||
static final RegExp _serveDtdPattern =
|
||||
RegExp(r'Serving the Dart Tooling Daemon at (ws:\/\/[a-zA-Z0-9:/=_\-\.\[\]]+?)\.?$');
|
||||
|
||||
@override
|
||||
Future<void> get processStart => _processStartCompleter.future;
|
||||
|
@ -55,21 +57,28 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
|
|||
_dartExecutable,
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
if (printDtdUri) '--print-dtd',
|
||||
if (vmServiceUri != null) '--vm-uri=$vmServiceUri',
|
||||
...?additionalArguments,
|
||||
]);
|
||||
_processStartCompleter.complete();
|
||||
final Completer<Uri> completer = Completer<Uri>();
|
||||
|
||||
final Completer<Uri> devToolsCompleter = Completer<Uri>();
|
||||
_devToolsProcess!.stdout
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.listen((String line) {
|
||||
final Match? match = _serveDevToolsPattern.firstMatch(line);
|
||||
if (match != null) {
|
||||
final String url = match[1]!;
|
||||
completer.complete(Uri.parse(url));
|
||||
}
|
||||
});
|
||||
final Match? dtdMatch = _serveDtdPattern.firstMatch(line);
|
||||
if (dtdMatch != null) {
|
||||
final String uri = dtdMatch[1]!;
|
||||
dtdUri = Uri.parse(uri);
|
||||
}
|
||||
final Match? devToolsMatch = _serveDevToolsPattern.firstMatch(line);
|
||||
if (devToolsMatch != null) {
|
||||
final String url = devToolsMatch[1]!;
|
||||
devToolsCompleter.complete(Uri.parse(url));
|
||||
}
|
||||
});
|
||||
_devToolsProcess!.stderr
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
|
@ -84,7 +93,11 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
|
|||
}
|
||||
);
|
||||
|
||||
devToolsUrl = await completer.future;
|
||||
// We do not need to wait for a [Completer] holding the DTD URI because
|
||||
// the DTD URI will be output to stdout before the DevTools URI. Awaiting
|
||||
// a [Completer] for the DevTools URI ensures both values will be
|
||||
// populated before returning.
|
||||
devToolsUrl = await devToolsCompleter.future;
|
||||
} on Exception catch (e, st) {
|
||||
_logger.printError('Failed to launch DevTools: $e', stackTrace: st);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,19 @@ abstract class ResidentDevtoolsHandler {
|
|||
/// The current devtools server, or null if one is not running.
|
||||
DevToolsServerAddress? get activeDevToolsServer;
|
||||
|
||||
/// The Dart Tooling Daemon (DTD) URI for the DTD instance being hosted by
|
||||
/// DevTools server.
|
||||
///
|
||||
/// This will be null if the DevTools server is not served through Flutter
|
||||
/// tools (e.g. if it is served from an IDE).
|
||||
Uri? get dtdUri;
|
||||
|
||||
/// Whether to print the Dart Tooling Daemon URI.
|
||||
///
|
||||
/// This will always return false when there is not a DTD instance being
|
||||
/// served from the DevTools server.
|
||||
bool get printDtdUri;
|
||||
|
||||
/// Whether it's ok to announce the [activeDevToolsServer].
|
||||
///
|
||||
/// This should only return true once all the devices have been notified
|
||||
|
@ -63,6 +76,12 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
|
|||
return _devToolsLauncher?.activeDevToolsServer;
|
||||
}
|
||||
|
||||
@override
|
||||
Uri? get dtdUri => _devToolsLauncher?.dtdUri;
|
||||
|
||||
@override
|
||||
bool get printDtdUri => _devToolsLauncher?.printDtdUri ?? false;
|
||||
|
||||
@override
|
||||
bool get readyToAnnounce => _readyToAnnounce;
|
||||
bool _readyToAnnounce = false;
|
||||
|
@ -337,6 +356,12 @@ class NoOpDevtoolsHandler implements ResidentDevtoolsHandler {
|
|||
wasShutdown = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@override
|
||||
Uri? get dtdUri => null;
|
||||
|
||||
@override
|
||||
bool get printDtdUri => false;
|
||||
}
|
||||
|
||||
/// Convert a [URI] with query parameters into a display format instead
|
||||
|
|
|
@ -1526,6 +1526,12 @@ abstract class ResidentRunner extends ResidentHandlers {
|
|||
);
|
||||
}
|
||||
if (includeDevtools) {
|
||||
if (_residentDevtoolsHandler!.printDtdUri) {
|
||||
final Uri? dtdUri = residentDevtoolsHandler!.dtdUri;
|
||||
if (dtdUri != null) {
|
||||
globals.printStatus('The Dart Tooling Daemon is available at: $dtdUri\n');
|
||||
}
|
||||
}
|
||||
final Uri? uri = devToolsServerAddress!.uri?.replace(
|
||||
queryParameters: <String, dynamic>{'uri': '${device.vmService!.httpAddress}'},
|
||||
);
|
||||
|
@ -1945,6 +1951,26 @@ abstract class DevtoolsLauncher {
|
|||
}
|
||||
}
|
||||
|
||||
/// The Dart Tooling Daemon (DTD) URI for the DTD instance being hosted by
|
||||
/// DevTools server.
|
||||
///
|
||||
/// This will be null if the DevTools server is not served through Flutter
|
||||
/// tools (e.g. if it is served from an IDE).
|
||||
Uri? get dtdUri => _dtdUri;
|
||||
Uri? _dtdUri;
|
||||
@protected
|
||||
set dtdUri(Uri? value) => _dtdUri = value;
|
||||
|
||||
/// Whether to print the Dart Tooling Daemon URI.
|
||||
///
|
||||
/// This will always return false when there is not a DTD instance being
|
||||
/// served from the DevTools server.
|
||||
bool get printDtdUri => _printDtdUri ?? false;
|
||||
bool? _printDtdUri;
|
||||
set printDtdUri(bool value) {
|
||||
_printDtdUri = value;
|
||||
}
|
||||
|
||||
/// The URL of the current DevTools server.
|
||||
///
|
||||
/// Returns null if [ready] is not complete.
|
||||
|
|
|
@ -17,6 +17,7 @@ import '../base/utils.dart';
|
|||
import '../cache.dart';
|
||||
import '../convert.dart';
|
||||
import '../globals.dart' as globals;
|
||||
import '../resident_runner.dart';
|
||||
import '../tester/flutter_tester.dart';
|
||||
import '../version.dart';
|
||||
import '../web/web_device.dart';
|
||||
|
@ -35,6 +36,7 @@ abstract final class FlutterGlobalOptions {
|
|||
static const String kMachineFlag = 'machine';
|
||||
static const String kPackagesOption = 'packages';
|
||||
static const String kPrefixedErrorsFlag = 'prefixed-errors';
|
||||
static const String kPrintDtd = 'print-dtd';
|
||||
static const String kQuietFlag = 'quiet';
|
||||
static const String kShowTestDeviceFlag = 'show-test-device';
|
||||
static const String kShowWebServerDeviceFlag = 'show-web-server-device';
|
||||
|
@ -116,6 +118,12 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||
argParser.addOption(FlutterGlobalOptions.kPackagesOption,
|
||||
hide: !verboseHelp,
|
||||
help: 'Path to your "package_config.json" file.');
|
||||
argParser.addFlag(
|
||||
FlutterGlobalOptions.kPrintDtd,
|
||||
negatable: false,
|
||||
help: 'Print the address of the Dart Tooling Daemon, if one is hosted by the Flutter CLI.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
if (verboseHelp) {
|
||||
argParser.addSeparator('Local build selection options (not normally required):');
|
||||
}
|
||||
|
@ -357,6 +365,10 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||
if (machineFlag && topLevelResults.command?.name != 'analyze') {
|
||||
throwToolExit('The "--machine" flag is only valid with the "--version" flag or the "analyze --suggestions" command.', exitCode: 2);
|
||||
}
|
||||
|
||||
final bool shouldPrintDtdUri = topLevelResults[FlutterGlobalOptions.kPrintDtd] as bool? ?? false;
|
||||
DevtoolsLauncher.instance!.printDtdUri = shouldPrintDtdUri;
|
||||
|
||||
await super.runCommand(topLevelResults);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -824,7 +824,7 @@ void main() {
|
|||
expect(result['host'], '127.0.0.1');
|
||||
expect(result['port'], 1234);
|
||||
}, overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => FakeDevtoolsLauncher(DevToolsServerAddress('127.0.0.1', 1234)),
|
||||
DevtoolsLauncher: () => FakeDevtoolsLauncher(serverAddress: DevToolsServerAddress('127.0.0.1', 1234)),
|
||||
});
|
||||
|
||||
testUsingContext('devtools.serve command should return null fields if null returned', () async {
|
||||
|
@ -840,7 +840,7 @@ void main() {
|
|||
expect(result['host'], null);
|
||||
expect(result['port'], null);
|
||||
}, overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => FakeDevtoolsLauncher(null),
|
||||
DevtoolsLauncher: () => FakeDevtoolsLauncher(),
|
||||
});
|
||||
|
||||
testUsingContext('proxy.connect tries to connect to an ipv4 address and proxies the connection correctly', () async {
|
||||
|
@ -1286,18 +1286,6 @@ class FakeDeviceLogReader implements DeviceLogReader {
|
|||
|
||||
}
|
||||
|
||||
class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher {
|
||||
FakeDevtoolsLauncher(this._serverAddress);
|
||||
|
||||
final DevToolsServerAddress? _serverAddress;
|
||||
|
||||
@override
|
||||
Future<DevToolsServerAddress?> serve() async => _serverAddress;
|
||||
|
||||
@override
|
||||
Future<void> close() async {}
|
||||
}
|
||||
|
||||
class FakeApplicationPackageFactory implements ApplicationPackageFactory {
|
||||
TargetPlatform? platformRequested;
|
||||
File? applicationBinaryRequested;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
|
@ -15,52 +16,87 @@ import '../src/fake_process_manager.dart';
|
|||
import '../src/fakes.dart';
|
||||
|
||||
void main() {
|
||||
late BufferLogger logger;
|
||||
|
||||
Cache.flutterRoot = '';
|
||||
|
||||
setUp(() {
|
||||
logger = BufferLogger.test();
|
||||
});
|
||||
(BufferLogger, Artifacts) getTestState() => (BufferLogger.test(), Artifacts.test());
|
||||
|
||||
testWithoutContext('DevtoolsLauncher launches DevTools from the SDK and saves the URI', () async {
|
||||
final (BufferLogger logger, Artifacts artifacts) = getTestState();
|
||||
final Completer<void> completer = Completer<void>();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
dartExecutable: 'dart',
|
||||
artifacts: artifacts,
|
||||
logger: logger,
|
||||
botDetector: const FakeBotDetector(false),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'dart',
|
||||
'Artifact.engineDartBinary',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
],
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100\n',
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100.\n',
|
||||
completer: completer,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(launcher.dtdUri, isNull);
|
||||
expect(launcher.printDtdUri, false);
|
||||
final DevToolsServerAddress? address = await launcher.serve();
|
||||
expect(address?.host, '127.0.0.1');
|
||||
expect(address?.port, 9100);
|
||||
expect(launcher.dtdUri, isNull);
|
||||
expect(launcher.printDtdUri, false);
|
||||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher does not launch a new DevTools instance if one is already active', () async {
|
||||
testWithoutContext('DevtoolsLauncher saves the Dart Tooling Daemon uri', () async {
|
||||
final (BufferLogger logger, Artifacts artifacts) = getTestState();
|
||||
final Completer<void> completer = Completer<void>();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
dartExecutable: 'dart',
|
||||
artifacts: artifacts,
|
||||
logger: logger,
|
||||
botDetector: const FakeBotDetector(false),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'dart',
|
||||
'Artifact.engineDartBinary',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
'--print-dtd',
|
||||
],
|
||||
stdout: '''
|
||||
Serving the Dart Tooling Daemon at ws://127.0.0.1:53449/
|
||||
Serving DevTools at http://127.0.0.1:9100.
|
||||
''',
|
||||
completer: completer,
|
||||
),
|
||||
]),
|
||||
)..printDtdUri = true;
|
||||
|
||||
expect(launcher.dtdUri, isNull);
|
||||
expect(launcher.printDtdUri, true);
|
||||
final DevToolsServerAddress? address = await launcher.serve();
|
||||
expect(address?.host, '127.0.0.1');
|
||||
expect(address?.port, 9100);
|
||||
expect(launcher.dtdUri?.toString(), 'ws://127.0.0.1:53449/');
|
||||
expect(launcher.printDtdUri, true);
|
||||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher does not launch a new DevTools instance if one is already active', () async {
|
||||
final (BufferLogger logger, Artifacts artifacts) = getTestState();
|
||||
final Completer<void> completer = Completer<void>();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
artifacts: artifacts,
|
||||
logger: logger,
|
||||
botDetector: const FakeBotDetector(false),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'Artifact.engineDartBinary',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
],
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100\n',
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100.\n',
|
||||
completer: completer,
|
||||
),
|
||||
]),
|
||||
|
@ -70,27 +106,28 @@ void main() {
|
|||
expect(address?.host, '127.0.0.1');
|
||||
expect(address?.port, 9100);
|
||||
|
||||
// Call `serve` again and verify that the already running server is returned.
|
||||
// Call `serve` again and verify that the already-running server is returned.
|
||||
address = await launcher.serve();
|
||||
expect(address?.host, '127.0.0.1');
|
||||
expect(address?.port, 9100);
|
||||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher can launch devtools with a memory profile', () async {
|
||||
final (BufferLogger logger, Artifacts artifacts) = getTestState();
|
||||
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'dart',
|
||||
'Artifact.engineDartBinary',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
'--vm-uri=localhost:8181/abcdefg',
|
||||
'--profile-memory=foo',
|
||||
],
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100\n',
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100.\n',
|
||||
),
|
||||
]);
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
dartExecutable: 'dart',
|
||||
artifacts: artifacts,
|
||||
logger: logger,
|
||||
botDetector: const FakeBotDetector(false),
|
||||
processManager: processManager,
|
||||
|
@ -103,14 +140,15 @@ void main() {
|
|||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher prints error if exception is thrown during launch', () async {
|
||||
final (BufferLogger logger, Artifacts artifacts) = getTestState();
|
||||
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
|
||||
dartExecutable: 'dart',
|
||||
artifacts: artifacts,
|
||||
logger: logger,
|
||||
botDetector: const FakeBotDetector(false),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'dart',
|
||||
'Artifact.engineDartBinary',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
'--vm-uri=http://127.0.0.1:1234/abcdefg',
|
||||
|
@ -126,19 +164,20 @@ void main() {
|
|||
});
|
||||
|
||||
testWithoutContext('DevtoolsLauncher handles failure of DevTools process on a bot', () async {
|
||||
final (BufferLogger logger, Artifacts artifacts) = getTestState();
|
||||
final Completer<void> completer = Completer<void>();
|
||||
final DevtoolsServerLauncher launcher = DevtoolsServerLauncher(
|
||||
dartExecutable: 'dart',
|
||||
artifacts: artifacts,
|
||||
logger: logger,
|
||||
botDetector: const FakeBotDetector(true),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: const <String>[
|
||||
'dart',
|
||||
'Artifact.engineDartBinary',
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
],
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100\n',
|
||||
stdout: 'Serving DevTools at http://127.0.0.1:9100.\n',
|
||||
completer: completer,
|
||||
exitCode: 255,
|
||||
),
|
||||
|
|
|
@ -28,7 +28,6 @@ import '../../src/context.dart';
|
|||
import '../../src/fake_vm_services.dart';
|
||||
import '../../src/fakes.dart';
|
||||
|
||||
|
||||
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
|
||||
id: '1',
|
||||
pauseEvent: vm_service.Event(
|
||||
|
@ -565,22 +564,3 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
|
|||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher {
|
||||
bool closed = false;
|
||||
final Completer<void> _processStarted = Completer<void>();
|
||||
|
||||
@override
|
||||
Future<void> launch(Uri vmServiceUri, {List<String>? additionalArguments}) {
|
||||
_processStarted.complete();
|
||||
return Completer<void>().future;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> get processStart => _processStarted.future;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/dds.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
|
@ -61,6 +62,8 @@ final FakeVmServiceRequest listViews = FakeVmServiceRequest(
|
|||
void main() {
|
||||
Cache.flutterRoot = '';
|
||||
|
||||
(BufferLogger, Artifacts) getTestState() => (BufferLogger.test(), Artifacts.test());
|
||||
|
||||
testWithoutContext('Does not serve devtools if launcher is null', () async {
|
||||
final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler(
|
||||
null,
|
||||
|
@ -86,10 +89,11 @@ void main() {
|
|||
});
|
||||
|
||||
testWithoutContext('Can use devtools with existing devtools URI', () async {
|
||||
final (BufferLogger logger, Artifacts artifacts) = getTestState();
|
||||
final DevtoolsServerLauncher launcher = DevtoolsServerLauncher(
|
||||
processManager: FakeProcessManager.empty(),
|
||||
dartExecutable: 'dart',
|
||||
logger: BufferLogger.test(),
|
||||
artifacts: artifacts,
|
||||
logger: logger,
|
||||
botDetector: const FakeBotDetector(false),
|
||||
);
|
||||
final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler(
|
||||
|
@ -429,22 +433,6 @@ void main() {
|
|||
});
|
||||
}
|
||||
|
||||
class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher {
|
||||
@override
|
||||
DevToolsServerAddress? activeDevToolsServer;
|
||||
|
||||
@override
|
||||
Uri? devToolsUrl;
|
||||
|
||||
@override
|
||||
Future<DevToolsServerAddress?> serve() async => null;
|
||||
|
||||
@override
|
||||
Future<void> get ready => readyCompleter.future;
|
||||
|
||||
Completer<void> readyCompleter = Completer<void>()..complete();
|
||||
}
|
||||
|
||||
class FakeResidentRunner extends Fake implements ResidentRunner {
|
||||
@override
|
||||
bool supportsServiceProtocol = true;
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:flutter_tools/src/base/terminal.dart';
|
|||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
import 'package:flutter_tools/src/resident_runner.dart';
|
||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
|
||||
import 'package:flutter_tools/src/version.dart';
|
||||
|
@ -175,116 +176,134 @@ void main() {
|
|||
Analytics: () => fakeAnalytics,
|
||||
});
|
||||
|
||||
testUsingContext("Doesn't crash on invalid .packages file", () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
fileSystem.file('pubspec.yaml').createSync();
|
||||
fileSystem.file('.packages')
|
||||
..createSync()
|
||||
..writeAsStringSync('Not a valid package');
|
||||
group('${FlutterGlobalOptions.kPrintDtd} flag', () {
|
||||
testUsingContext('sets DevtoolsLauncher.printDtdUri to false when not present', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
await runner.run(<String>[]);
|
||||
expect(DevtoolsLauncher.instance!.printDtdUri, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => FakeDevtoolsLauncher()..dtdUri = Uri(),
|
||||
});
|
||||
|
||||
await runner.run(<String>['dummy']);
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Platform: () => platform,
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
});
|
||||
|
||||
group('getRepoPackages', () {
|
||||
late String? oldFlutterRoot;
|
||||
|
||||
setUp(() {
|
||||
oldFlutterRoot = Cache.flutterRoot;
|
||||
Cache.flutterRoot = _kFlutterRoot;
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'examples'))
|
||||
.createSync(recursive: true);
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'packages'))
|
||||
.createSync(recursive: true);
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'aatool'))
|
||||
.createSync(recursive: true);
|
||||
|
||||
fileSystem.file(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'pubspec.yaml'))
|
||||
.createSync();
|
||||
fileSystem.file(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'aatool', 'pubspec.yaml'))
|
||||
.createSync();
|
||||
testUsingContext('sets DevtoolsLauncher.printDtdUri to true when present', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
await runner.run(<String>['--${FlutterGlobalOptions.kPrintDtd}']);
|
||||
expect(DevtoolsLauncher.instance!.printDtdUri, true);
|
||||
}, overrides: <Type, Generator>{
|
||||
DevtoolsLauncher: () => FakeDevtoolsLauncher()..dtdUri = Uri(),
|
||||
});
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
Cache.flutterRoot = oldFlutterRoot;
|
||||
});
|
||||
|
||||
testUsingContext('', () {
|
||||
testUsingContext("Doesn't crash on invalid .packages file", () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final List<String> packagePaths = runner.getRepoPackages()
|
||||
.map((Directory d) => d.path).toList();
|
||||
expect(packagePaths, <String>[
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'aatool')).path,
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools')).path,
|
||||
]);
|
||||
fileSystem.file('pubspec.yaml').createSync();
|
||||
fileSystem.file('.packages')
|
||||
..createSync()
|
||||
..writeAsStringSync('Not a valid package');
|
||||
|
||||
await runner.run(<String>['dummy']);
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Platform: () => platform,
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
});
|
||||
|
||||
group('getRepoPackages', () {
|
||||
late String? oldFlutterRoot;
|
||||
|
||||
setUp(() {
|
||||
oldFlutterRoot = Cache.flutterRoot;
|
||||
Cache.flutterRoot = _kFlutterRoot;
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'examples'))
|
||||
.createSync(recursive: true);
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'packages'))
|
||||
.createSync(recursive: true);
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'aatool'))
|
||||
.createSync(recursive: true);
|
||||
|
||||
fileSystem.file(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'pubspec.yaml'))
|
||||
.createSync();
|
||||
fileSystem.file(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'aatool', 'pubspec.yaml'))
|
||||
.createSync();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
Cache.flutterRoot = oldFlutterRoot;
|
||||
});
|
||||
|
||||
testUsingContext('', () {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final List<String> packagePaths = runner.getRepoPackages()
|
||||
.map((Directory d) => d.path).toList();
|
||||
expect(packagePaths, <String>[
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools', 'aatool')).path,
|
||||
fileSystem.directory(fileSystem.path.join(_kFlutterRoot, 'dev', 'tools')).path,
|
||||
]);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Platform: () => platform,
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
});
|
||||
});
|
||||
|
||||
group('wrapping', () {
|
||||
testUsingContext('checks that output wrapping is turned on when writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: true),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('checks that output wrapping is turned off when not writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: false),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('checks that output wrapping is turned off when set on the command line and writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['--no-wrap', 'fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: true),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('checks that output wrapping is turned on when set on the command line, but not writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['--wrap', 'fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: false),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
});
|
||||
});
|
||||
|
||||
group('wrapping', () {
|
||||
testUsingContext('checks that output wrapping is turned on when writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: true),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('checks that output wrapping is turned off when not writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: false),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('checks that output wrapping is turned off when set on the command line and writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['--no-wrap', 'fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: true),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('checks that output wrapping is turned on when set on the command line, but not writing to a terminal', () async {
|
||||
final FlutterCommandRunner runner = createTestCommandRunner(DummyFlutterCommand()) as FlutterCommandRunner;
|
||||
final FakeFlutterCommand fakeCommand = FakeFlutterCommand();
|
||||
runner.addCommand(fakeCommand);
|
||||
await runner.run(<String>['--wrap', 'fake']);
|
||||
expect(fakeCommand.preferences.wrapText, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Stdio: () => FakeStdio(hasFakeTerminal: false),
|
||||
OutputPreferences: () => OutputPreferences.test(),
|
||||
}, initializeFlutterRoot: false);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import 'package:flutter_tools/src/convert.dart';
|
|||
import 'package:flutter_tools/src/features.dart';
|
||||
import 'package:flutter_tools/src/ios/plist_parser.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:flutter_tools/src/resident_runner.dart';
|
||||
import 'package:flutter_tools/src/version.dart';
|
||||
import 'package:test/fake.dart';
|
||||
|
||||
|
@ -686,3 +687,48 @@ class FakeJava extends Fake implements Java {
|
|||
return _canRun;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher {
|
||||
FakeDevtoolsLauncher({DevToolsServerAddress? serverAddress})
|
||||
: _serverAddress = serverAddress;
|
||||
|
||||
@override
|
||||
Future<void> get processStart => _processStarted.future;
|
||||
|
||||
final Completer<void> _processStarted = Completer<void>();
|
||||
|
||||
@override
|
||||
Future<void> get ready => readyCompleter.future;
|
||||
|
||||
Completer<void> readyCompleter = Completer<void>()..complete();
|
||||
|
||||
@override
|
||||
DevToolsServerAddress? activeDevToolsServer;
|
||||
|
||||
@override
|
||||
Uri? devToolsUrl;
|
||||
|
||||
@override
|
||||
Uri? dtdUri;
|
||||
|
||||
@override
|
||||
bool printDtdUri = false;
|
||||
|
||||
final DevToolsServerAddress? _serverAddress;
|
||||
|
||||
@override
|
||||
Future<DevToolsServerAddress?> serve() async => _serverAddress;
|
||||
|
||||
@override
|
||||
Future<void> launch(Uri vmServiceUri, {List<String>? additionalArguments}) {
|
||||
_processStarted.complete();
|
||||
return Completer<void>().future;
|
||||
}
|
||||
|
||||
bool closed = false;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue