mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
293 lines
8.2 KiB
Dart
293 lines
8.2 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// 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:process/process.dart';
|
|
|
|
import '../application_package.dart';
|
|
import '../artifacts.dart';
|
|
import '../base/file_system.dart';
|
|
import '../base/io.dart';
|
|
import '../base/logger.dart';
|
|
import '../base/os.dart';
|
|
import '../build_info.dart';
|
|
import '../bundle.dart';
|
|
import '../bundle_builder.dart';
|
|
import '../desktop_device.dart';
|
|
import '../devfs.dart';
|
|
import '../device.dart';
|
|
import '../device_port_forwarder.dart';
|
|
import '../project.dart';
|
|
import '../protocol_discovery.dart';
|
|
import '../version.dart';
|
|
|
|
class FlutterTesterApp extends ApplicationPackage {
|
|
factory FlutterTesterApp.fromCurrentDirectory(FileSystem fileSystem) {
|
|
return FlutterTesterApp._(fileSystem.currentDirectory);
|
|
}
|
|
|
|
FlutterTesterApp._(Directory directory)
|
|
: _directory = directory,
|
|
super(id: directory.path);
|
|
|
|
final Directory _directory;
|
|
|
|
@override
|
|
String get name => _directory.basename;
|
|
}
|
|
|
|
/// The device interface for running on the flutter_tester shell.
|
|
///
|
|
/// Normally this is only used as the runner for `flutter test`, but it can
|
|
/// also be used as a regular device when `--show-test-device` is provided
|
|
/// to the flutter command.
|
|
class FlutterTesterDevice extends Device {
|
|
FlutterTesterDevice(super.deviceId, {
|
|
required ProcessManager processManager,
|
|
required FlutterVersion flutterVersion,
|
|
required Logger logger,
|
|
required FileSystem fileSystem,
|
|
required Artifacts artifacts,
|
|
required OperatingSystemUtils operatingSystemUtils,
|
|
}) : _processManager = processManager,
|
|
_flutterVersion = flutterVersion,
|
|
_logger = logger,
|
|
_fileSystem = fileSystem,
|
|
_artifacts = artifacts,
|
|
_operatingSystemUtils = operatingSystemUtils,
|
|
super(
|
|
platformType: null,
|
|
category: null,
|
|
ephemeral: false,
|
|
);
|
|
|
|
final ProcessManager _processManager;
|
|
final FlutterVersion _flutterVersion;
|
|
final Logger _logger;
|
|
final FileSystem _fileSystem;
|
|
final Artifacts _artifacts;
|
|
final OperatingSystemUtils _operatingSystemUtils;
|
|
|
|
Process? _process;
|
|
final DevicePortForwarder _portForwarder = const NoOpDevicePortForwarder();
|
|
|
|
@override
|
|
Future<bool> get isLocalEmulator async => false;
|
|
|
|
@override
|
|
Future<String?> get emulatorId async => null;
|
|
|
|
@override
|
|
String get name => 'Flutter test device';
|
|
|
|
@override
|
|
DevicePortForwarder get portForwarder => _portForwarder;
|
|
|
|
@override
|
|
Future<String> get sdkNameAndVersion async {
|
|
final FlutterVersion flutterVersion = _flutterVersion;
|
|
return 'Flutter ${flutterVersion.frameworkRevisionShort}';
|
|
}
|
|
|
|
@override
|
|
bool supportsRuntimeMode(BuildMode buildMode) => buildMode == BuildMode.debug;
|
|
|
|
@override
|
|
Future<TargetPlatform> get targetPlatform async => TargetPlatform.tester;
|
|
|
|
@override
|
|
void clearLogs() { }
|
|
|
|
final DesktopLogReader _logReader = DesktopLogReader();
|
|
|
|
@override
|
|
DeviceLogReader getLogReader({
|
|
ApplicationPackage? app,
|
|
bool includePastLogs = false,
|
|
}) {
|
|
return _logReader;
|
|
}
|
|
|
|
@override
|
|
Future<bool> installApp(
|
|
ApplicationPackage app, {
|
|
String? userIdentifier,
|
|
}) async => true;
|
|
|
|
@override
|
|
Future<bool> isAppInstalled(
|
|
ApplicationPackage app, {
|
|
String? userIdentifier,
|
|
}) async => false;
|
|
|
|
@override
|
|
Future<bool> isLatestBuildInstalled(ApplicationPackage app) async => false;
|
|
|
|
@override
|
|
bool isSupported() => true;
|
|
|
|
@override
|
|
Future<LaunchResult> startApp(
|
|
ApplicationPackage? package, {
|
|
String? mainPath,
|
|
String? route,
|
|
required DebuggingOptions debuggingOptions,
|
|
Map<String, Object?> platformArgs = const <String, Object>{},
|
|
bool prebuiltApplication = false,
|
|
bool ipv6 = false,
|
|
String? userIdentifier,
|
|
}) async {
|
|
final BuildInfo buildInfo = debuggingOptions.buildInfo;
|
|
if (!buildInfo.isDebug) {
|
|
_logger.printError('This device only supports debug mode.');
|
|
return LaunchResult.failed();
|
|
}
|
|
|
|
final Directory assetDirectory = _fileSystem.systemTempDirectory
|
|
.createTempSync('flutter_tester.');
|
|
final String applicationKernelFilePath = getKernelPathForTransformerOptions(
|
|
_fileSystem.path.join(assetDirectory.path, 'flutter-tester-app.dill'),
|
|
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
|
);
|
|
|
|
// Build assets and perform initial compilation.
|
|
await BundleBuilder().build(
|
|
buildInfo: buildInfo,
|
|
mainPath: mainPath,
|
|
applicationKernelFilePath: applicationKernelFilePath,
|
|
platform: getTargetPlatformForName(getNameForHostPlatform(_operatingSystemUtils.hostPlatform)),
|
|
assetDirPath: assetDirectory.path,
|
|
);
|
|
|
|
final List<String> command = <String>[
|
|
_artifacts.getArtifactPath(Artifact.flutterTester),
|
|
'--run-forever',
|
|
'--non-interactive',
|
|
if (debuggingOptions.enableDartProfiling)
|
|
'--enable-dart-profiling',
|
|
'--packages=${debuggingOptions.buildInfo.packagesPath}',
|
|
'--flutter-assets-dir=${assetDirectory.path}',
|
|
if (debuggingOptions.startPaused)
|
|
'--start-paused',
|
|
if (debuggingOptions.disableServiceAuthCodes)
|
|
'--disable-service-auth-codes',
|
|
if (debuggingOptions.hostVmServicePort != null)
|
|
'--vm-service-port=${debuggingOptions.hostVmServicePort}',
|
|
applicationKernelFilePath,
|
|
];
|
|
|
|
ProtocolDiscovery? vmServiceDiscovery;
|
|
try {
|
|
_logger.printTrace(command.join(' '));
|
|
_process = await _processManager.start(command,
|
|
environment: <String, String>{
|
|
'FLUTTER_TEST': 'true',
|
|
},
|
|
);
|
|
if (!debuggingOptions.debuggingEnabled) {
|
|
return LaunchResult.succeeded();
|
|
}
|
|
|
|
vmServiceDiscovery = ProtocolDiscovery.vmService(
|
|
getLogReader(),
|
|
hostPort: debuggingOptions.hostVmServicePort,
|
|
devicePort: debuggingOptions.deviceVmServicePort,
|
|
ipv6: ipv6,
|
|
logger: _logger,
|
|
);
|
|
_logReader.initializeProcess(_process!);
|
|
|
|
final Uri? vmServiceUri = await vmServiceDiscovery.uri;
|
|
if (vmServiceUri != null) {
|
|
return LaunchResult.succeeded(vmServiceUri: vmServiceUri);
|
|
}
|
|
_logger.printError(
|
|
'Failed to launch $package: '
|
|
'The log reader failed unexpectedly.',
|
|
);
|
|
} on Exception catch (error) {
|
|
_logger.printError('Failed to launch $package: $error');
|
|
} finally {
|
|
await vmServiceDiscovery?.cancel();
|
|
}
|
|
return LaunchResult.failed();
|
|
}
|
|
|
|
@override
|
|
Future<bool> stopApp(
|
|
ApplicationPackage? app, {
|
|
String? userIdentifier,
|
|
}) async {
|
|
_process?.kill();
|
|
_process = null;
|
|
return true;
|
|
}
|
|
|
|
@override
|
|
Future<bool> uninstallApp(
|
|
ApplicationPackage app, {
|
|
String? userIdentifier,
|
|
}) async => true;
|
|
|
|
@override
|
|
bool isSupportedForProject(FlutterProject flutterProject) => true;
|
|
|
|
@override
|
|
DevFSWriter createDevFSWriter(
|
|
ApplicationPackage? app,
|
|
String? userIdentifier,
|
|
) {
|
|
return LocalDevFSWriter(
|
|
fileSystem: _fileSystem,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<void> dispose() async {
|
|
_logReader.dispose();
|
|
await _portForwarder.dispose();
|
|
}
|
|
}
|
|
|
|
class FlutterTesterDevices extends PollingDeviceDiscovery {
|
|
FlutterTesterDevices({
|
|
required FileSystem fileSystem,
|
|
required Artifacts artifacts,
|
|
required ProcessManager processManager,
|
|
required Logger logger,
|
|
required FlutterVersion flutterVersion,
|
|
required OperatingSystemUtils operatingSystemUtils,
|
|
}) : _testerDevice = FlutterTesterDevice(
|
|
kTesterDeviceId,
|
|
fileSystem: fileSystem,
|
|
artifacts: artifacts,
|
|
processManager: processManager,
|
|
logger: logger,
|
|
flutterVersion: flutterVersion,
|
|
operatingSystemUtils: operatingSystemUtils,
|
|
),
|
|
super('Flutter tester');
|
|
|
|
static const String kTesterDeviceId = 'flutter-tester';
|
|
|
|
static bool showFlutterTesterDevice = false;
|
|
|
|
final FlutterTesterDevice _testerDevice;
|
|
|
|
@override
|
|
bool get canListAnything => true;
|
|
|
|
@override
|
|
bool get supportsPlatform => true;
|
|
|
|
@override
|
|
Future<List<Device>> pollingGetDevices({ Duration? timeout }) async {
|
|
return showFlutterTesterDevice ? <Device>[_testerDevice] : <Device>[];
|
|
}
|
|
|
|
@override
|
|
List<String> get wellKnownIds => const <String>[kTesterDeviceId];
|
|
}
|