mirror of
https://github.com/flutter/flutter
synced 2024-10-12 11:12:54 +00:00
Migrate assemble and integration_test_device to null safety (#96630)
This commit is contained in:
parent
dafda50c6a
commit
219dd6ca38
|
@ -2,10 +2,10 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../artifacts.dart';
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../build_info.dart';
|
||||
|
@ -88,7 +88,7 @@ List<Target> _kDefaultTargets = <Target>[
|
|||
/// Assemble provides a low level API to interact with the flutter tool build
|
||||
/// system.
|
||||
class AssembleCommand extends FlutterCommand {
|
||||
AssembleCommand({ bool verboseHelp = false, @required BuildSystem buildSystem })
|
||||
AssembleCommand({ bool verboseHelp = false, required BuildSystem buildSystem })
|
||||
: _buildSystem = buildSystem {
|
||||
argParser.addMultiOption(
|
||||
'define',
|
||||
|
@ -161,13 +161,13 @@ class AssembleCommand extends FlutterCommand {
|
|||
|
||||
@override
|
||||
Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
|
||||
final String platform = environment.defines[kTargetPlatform];
|
||||
final String? platform = environment.defines[kTargetPlatform];
|
||||
if (platform == null) {
|
||||
return super.requiredArtifacts;
|
||||
}
|
||||
|
||||
final TargetPlatform targetPlatform = getTargetPlatformForName(platform);
|
||||
final DevelopmentArtifact artifact = artifactFromTargetPlatform(targetPlatform);
|
||||
final DevelopmentArtifact? artifact = artifactFromTargetPlatform(targetPlatform);
|
||||
if (artifact != null) {
|
||||
return <DevelopmentArtifact>{artifact};
|
||||
}
|
||||
|
@ -176,18 +176,19 @@ class AssembleCommand extends FlutterCommand {
|
|||
|
||||
/// The target(s) we are building.
|
||||
List<Target> createTargets() {
|
||||
if (argResults.rest.isEmpty) {
|
||||
final ArgResults argumentResults = argResults!;
|
||||
if (argumentResults.rest.isEmpty) {
|
||||
throwToolExit('missing target name for flutter assemble.');
|
||||
}
|
||||
final String name = argResults.rest.first;
|
||||
final String name = argumentResults.rest.first;
|
||||
final Map<String, Target> targetMap = <String, Target>{
|
||||
for (final Target target in _kDefaultTargets)
|
||||
target.name: target
|
||||
};
|
||||
final List<Target> results = <Target>[
|
||||
for (final String targetName in argResults.rest)
|
||||
for (final String targetName in argumentResults.rest)
|
||||
if (targetMap.containsKey(targetName))
|
||||
targetMap[targetName]
|
||||
targetMap[targetName]!
|
||||
];
|
||||
if (results.isEmpty) {
|
||||
throwToolExit('No target named "$name" defined.');
|
||||
|
@ -196,7 +197,7 @@ class AssembleCommand extends FlutterCommand {
|
|||
}
|
||||
|
||||
bool isDeferredComponentsTargets() {
|
||||
for (final String targetName in argResults.rest) {
|
||||
for (final String targetName in argResults!.rest) {
|
||||
if (deferredComponentsTargets.contains(targetName)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -205,7 +206,7 @@ class AssembleCommand extends FlutterCommand {
|
|||
}
|
||||
|
||||
bool isDebug() {
|
||||
for (final String targetName in argResults.rest) {
|
||||
for (final String targetName in argResults!.rest) {
|
||||
if (targetName.contains('debug')) {
|
||||
return true;
|
||||
}
|
||||
|
@ -213,13 +214,12 @@ class AssembleCommand extends FlutterCommand {
|
|||
return false;
|
||||
}
|
||||
|
||||
Environment get environment => _environment ??= createEnvironment();
|
||||
Environment _environment;
|
||||
late final Environment environment = createEnvironment();
|
||||
|
||||
/// The environmental configuration for a build invocation.
|
||||
Environment createEnvironment() {
|
||||
final FlutterProject flutterProject = FlutterProject.current();
|
||||
String output = stringArg('output');
|
||||
String? output = stringArg('output');
|
||||
if (output == null) {
|
||||
throwToolExit('--output directory is required for assemble.');
|
||||
}
|
||||
|
@ -227,6 +227,7 @@ class AssembleCommand extends FlutterCommand {
|
|||
if (globals.fs.path.isRelative(output)) {
|
||||
output = globals.fs.path.join(flutterProject.directory.path, output);
|
||||
}
|
||||
final Artifacts artifacts = globals.artifacts!;
|
||||
final Environment result = Environment(
|
||||
outputDir: globals.fs.directory(output),
|
||||
buildDir: flutterProject.directory
|
||||
|
@ -237,12 +238,12 @@ class AssembleCommand extends FlutterCommand {
|
|||
inputs: _parseDefines(stringsArg('input')),
|
||||
cacheDir: globals.cache.getRoot(),
|
||||
flutterRootDir: globals.fs.directory(Cache.flutterRoot),
|
||||
artifacts: globals.artifacts,
|
||||
artifacts: artifacts,
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
processManager: globals.processManager,
|
||||
platform: globals.platform,
|
||||
engineVersion: globals.artifacts.isLocalEngine
|
||||
engineVersion: artifacts.isLocalEngine
|
||||
? null
|
||||
: globals.flutterVersion.engineRevision,
|
||||
generateDartPluginRegistry: true,
|
||||
|
@ -261,18 +262,19 @@ class AssembleCommand extends FlutterCommand {
|
|||
final String value = chunk.substring(indexEquals + 1);
|
||||
results[key] = value;
|
||||
}
|
||||
if (argResults.wasParsed(FlutterOptions.kExtraGenSnapshotOptions)) {
|
||||
results[kExtraGenSnapshotOptions] = (argResults[FlutterOptions.kExtraGenSnapshotOptions] as List<String>).join(',');
|
||||
final ArgResults argumentResults = argResults!;
|
||||
if (argumentResults.wasParsed(FlutterOptions.kExtraGenSnapshotOptions)) {
|
||||
results[kExtraGenSnapshotOptions] = (argumentResults[FlutterOptions.kExtraGenSnapshotOptions] as List<String>).join(',');
|
||||
}
|
||||
if (argResults.wasParsed(FlutterOptions.kDartDefinesOption)) {
|
||||
results[kDartDefines] = (argResults[FlutterOptions.kDartDefinesOption] as List<String>).join(',');
|
||||
if (argumentResults.wasParsed(FlutterOptions.kDartDefinesOption)) {
|
||||
results[kDartDefines] = (argumentResults[FlutterOptions.kDartDefinesOption] as List<String>).join(',');
|
||||
}
|
||||
results[kDeferredComponents] = 'false';
|
||||
if (FlutterProject.current().manifest.deferredComponents != null && isDeferredComponentsTargets() && !isDebug()) {
|
||||
results[kDeferredComponents] = 'true';
|
||||
}
|
||||
if (argResults.wasParsed(FlutterOptions.kExtraFrontEndOptions)) {
|
||||
results[kExtraFrontEndOptions] = (argResults[FlutterOptions.kExtraFrontEndOptions] as List<String>).join(',');
|
||||
if (argumentResults.wasParsed(FlutterOptions.kExtraFrontEndOptions)) {
|
||||
results[kExtraFrontEndOptions] = (argumentResults[FlutterOptions.kExtraFrontEndOptions] as List<String>).join(',');
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -289,7 +291,7 @@ class AssembleCommand extends FlutterCommand {
|
|||
nonDeferredTargets.add(target);
|
||||
}
|
||||
}
|
||||
Target target;
|
||||
Target? target;
|
||||
List<String> decodedDefines;
|
||||
try {
|
||||
decodedDefines = decodeDartDefines(environment.defines, kDartDefines);
|
||||
|
@ -314,12 +316,13 @@ class AssembleCommand extends FlutterCommand {
|
|||
} else if (targets.isNotEmpty) {
|
||||
target = targets.single;
|
||||
}
|
||||
final ArgResults argumentResults = argResults!;
|
||||
final BuildResult result = await _buildSystem.build(
|
||||
target,
|
||||
target!,
|
||||
environment,
|
||||
buildSystemConfig: BuildSystemConfig(
|
||||
resourcePoolSize: argResults.wasParsed('resource-pool-size')
|
||||
? int.tryParse(stringArg('resource-pool-size'))
|
||||
resourcePoolSize: argumentResults.wasParsed('resource-pool-size')
|
||||
? int.tryParse(stringArg('resource-pool-size')!)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
|
@ -335,17 +338,17 @@ class AssembleCommand extends FlutterCommand {
|
|||
}
|
||||
globals.printTrace('build succeeded.');
|
||||
|
||||
if (argResults.wasParsed('build-inputs')) {
|
||||
writeListIfChanged(result.inputFiles, stringArg('build-inputs'));
|
||||
if (argumentResults.wasParsed('build-inputs')) {
|
||||
writeListIfChanged(result.inputFiles, stringArg('build-inputs')!);
|
||||
}
|
||||
if (argResults.wasParsed('build-outputs')) {
|
||||
writeListIfChanged(result.outputFiles, stringArg('build-outputs'));
|
||||
if (argumentResults.wasParsed('build-outputs')) {
|
||||
writeListIfChanged(result.outputFiles, stringArg('build-outputs')!);
|
||||
}
|
||||
if (argResults.wasParsed('performance-measurement-file')) {
|
||||
final File outFile = globals.fs.file(argResults['performance-measurement-file']);
|
||||
if (argumentResults.wasParsed('performance-measurement-file')) {
|
||||
final File outFile = globals.fs.file(argumentResults['performance-measurement-file']);
|
||||
writePerformanceData(result.performance.values, outFile);
|
||||
}
|
||||
if (argResults.wasParsed('depfile')) {
|
||||
if (argumentResults.wasParsed('depfile')) {
|
||||
final File depfileFile = globals.fs.file(stringArg('depfile'));
|
||||
final Depfile depfile = Depfile(result.inputFiles, result.outputFiles);
|
||||
final DepfileService depfileService = DepfileService(
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:stream_channel/stream_channel.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
|
@ -24,10 +21,10 @@ const String kIntegrationTestMethod = 'ext.flutter.integrationTest';
|
|||
|
||||
class IntegrationTestTestDevice implements TestDevice {
|
||||
IntegrationTestTestDevice({
|
||||
@required this.id,
|
||||
@required this.device,
|
||||
@required this.debuggingOptions,
|
||||
@required this.userIdentifier,
|
||||
required this.id,
|
||||
required this.device,
|
||||
required this.debuggingOptions,
|
||||
required this.userIdentifier,
|
||||
});
|
||||
|
||||
final int id;
|
||||
|
@ -35,7 +32,7 @@ class IntegrationTestTestDevice implements TestDevice {
|
|||
final DebuggingOptions debuggingOptions;
|
||||
final String userIdentifier;
|
||||
|
||||
ApplicationPackage _applicationPackage;
|
||||
ApplicationPackage? _applicationPackage;
|
||||
final Completer<void> _finished = Completer<void>();
|
||||
final Completer<Uri> _gotProcessObservatoryUri = Completer<Uri>();
|
||||
|
||||
|
@ -45,13 +42,16 @@ class IntegrationTestTestDevice implements TestDevice {
|
|||
@override
|
||||
Future<StreamChannel<String>> start(String entrypointPath) async {
|
||||
final TargetPlatform targetPlatform = await device.targetPlatform;
|
||||
_applicationPackage = await ApplicationPackageFactory.instance.getPackageForPlatform(
|
||||
_applicationPackage = await ApplicationPackageFactory.instance?.getPackageForPlatform(
|
||||
targetPlatform,
|
||||
buildInfo: debuggingOptions.buildInfo,
|
||||
);
|
||||
if (_applicationPackage == null) {
|
||||
throw TestDeviceException('No application found for $targetPlatform.', StackTrace.current);
|
||||
}
|
||||
|
||||
final LaunchResult launchResult = await device.startApp(
|
||||
_applicationPackage,
|
||||
_applicationPackage!,
|
||||
mainPath: entrypointPath,
|
||||
platformArgs: <String, dynamic>{},
|
||||
debuggingOptions: debuggingOptions,
|
||||
|
@ -60,17 +60,18 @@ class IntegrationTestTestDevice implements TestDevice {
|
|||
if (!launchResult.started) {
|
||||
throw TestDeviceException('Unable to start the app on the device.', StackTrace.current);
|
||||
}
|
||||
if (launchResult.observatoryUri == null) {
|
||||
final Uri? observatoryUri = launchResult.observatoryUri;
|
||||
if (observatoryUri == null) {
|
||||
throw TestDeviceException('Observatory is not available on the test device.', StackTrace.current);
|
||||
}
|
||||
|
||||
// No need to set up the log reader because the logs are captured and
|
||||
// streamed to the package:test_core runner.
|
||||
|
||||
_gotProcessObservatoryUri.complete(launchResult.observatoryUri);
|
||||
_gotProcessObservatoryUri.complete(observatoryUri);
|
||||
|
||||
globals.printTrace('test $id: Connecting to vm service');
|
||||
final FlutterVmService vmService = await connectToVmService(launchResult.observatoryUri, logger: globals.logger).timeout(
|
||||
final FlutterVmService vmService = await connectToVmService(observatoryUri, logger: globals.logger).timeout(
|
||||
const Duration(seconds: 5),
|
||||
onTimeout: () => throw TimeoutException('Connecting to the VM Service timed out.'),
|
||||
);
|
||||
|
@ -83,7 +84,7 @@ class IntegrationTestTestDevice implements TestDevice {
|
|||
await vmService.service.streamListen(vm_service.EventStreams.kExtension);
|
||||
final Stream<String> remoteMessages = vmService.service.onExtensionEvent
|
||||
.where((vm_service.Event e) => e.extensionKind == kIntegrationTestExtension)
|
||||
.map((vm_service.Event e) => e.extensionData.data[kIntegrationTestData] as String);
|
||||
.map((vm_service.Event e) => e.extensionData!.data[kIntegrationTestData] as String);
|
||||
|
||||
final StreamChannelController<String> controller = StreamChannelController<String>();
|
||||
|
||||
|
@ -113,11 +114,14 @@ class IntegrationTestTestDevice implements TestDevice {
|
|||
|
||||
@override
|
||||
Future<void> kill() async {
|
||||
if (!await device.stopApp(_applicationPackage, userIdentifier: userIdentifier)) {
|
||||
globals.printTrace('Could not stop the Integration Test app.');
|
||||
}
|
||||
if (!await device.uninstallApp(_applicationPackage, userIdentifier: userIdentifier)) {
|
||||
globals.printTrace('Could not uninstall the Integration Test app.');
|
||||
final ApplicationPackage? applicationPackage = _applicationPackage;
|
||||
if (applicationPackage != null) {
|
||||
if (!await device.stopApp(applicationPackage, userIdentifier: userIdentifier)) {
|
||||
globals.printTrace('Could not stop the Integration Test app.');
|
||||
}
|
||||
if (!await device.uninstallApp(applicationPackage, userIdentifier: userIdentifier)) {
|
||||
globals.printTrace('Could not uninstall the Integration Test app.');
|
||||
}
|
||||
}
|
||||
|
||||
await device.dispose();
|
||||
|
|
|
@ -750,21 +750,6 @@ class FakeDevice extends Fake implements Device {
|
|||
}
|
||||
}
|
||||
|
||||
class FakeApplicationPackageFactory extends Fake implements ApplicationPackageFactory {
|
||||
FakeApplicationPackageFactory(this.applicationPackage);
|
||||
|
||||
ApplicationPackage applicationPackage;
|
||||
|
||||
@override
|
||||
Future<ApplicationPackage> getPackageForPlatform(
|
||||
TargetPlatform platform, {
|
||||
BuildInfo buildInfo,
|
||||
File applicationBinary,
|
||||
}) async => applicationPackage;
|
||||
}
|
||||
|
||||
class FakeApplicationPackage extends Fake implements ApplicationPackage { }
|
||||
|
||||
class TestRunCommandWithFakeResidentRunner extends RunCommand {
|
||||
FakeResidentRunner fakeResidentRunner;
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/application_package.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart' as io;
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
|
@ -12,8 +14,10 @@ import 'package:flutter_tools/src/test/integration_test_device.dart';
|
|||
import 'package:flutter_tools/src/test/test_device.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:stream_channel/stream_channel.dart';
|
||||
import 'package:test/fake.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fake_devices.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
@ -121,12 +125,26 @@ void main() {
|
|||
]);
|
||||
});
|
||||
|
||||
testUsingContext('will not start when package missing', () async {
|
||||
await expectLater(
|
||||
testDevice.start('entrypointPath'),
|
||||
throwsA(
|
||||
isA<TestDeviceException>().having(
|
||||
(Exception e) => e.toString(),
|
||||
'description',
|
||||
contains('No application found for TargetPlatform.android_arm'),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('Can start the entrypoint', () async {
|
||||
await testDevice.start('entrypointPath');
|
||||
|
||||
expect(await testDevice.observatoryUri, observatoryUri);
|
||||
expect(testDevice.finished, doesNotComplete);
|
||||
}, overrides: <Type, Generator>{
|
||||
ApplicationPackageFactory: () => FakeApplicationPackageFactory(),
|
||||
VMServiceConnector: () => (Uri httpUri, {
|
||||
ReloadSources reloadSources,
|
||||
Restart restart,
|
||||
|
@ -145,6 +163,7 @@ void main() {
|
|||
|
||||
expect(testDevice.finished, completes);
|
||||
}, overrides: <Type, Generator>{
|
||||
ApplicationPackageFactory: () => FakeApplicationPackageFactory(),
|
||||
VMServiceConnector: () => (Uri httpUri, {
|
||||
ReloadSources reloadSources,
|
||||
Restart restart,
|
||||
|
@ -218,6 +237,7 @@ void main() {
|
|||
await fakeVmServiceHost.vmService.dispose();
|
||||
expect(await channel.stream.isEmpty, true);
|
||||
}, overrides: <Type, Generator>{
|
||||
ApplicationPackageFactory: () => FakeApplicationPackageFactory(),
|
||||
VMServiceConnector: () => (Uri httpUri, {
|
||||
ReloadSources reloadSources,
|
||||
Restart restart,
|
||||
|
@ -230,3 +250,14 @@ void main() {
|
|||
}) async => fakeVmServiceHost.vmService,
|
||||
});
|
||||
}
|
||||
|
||||
class FakeApplicationPackageFactory extends Fake implements ApplicationPackageFactory {
|
||||
@override
|
||||
Future<ApplicationPackage> getPackageForPlatform(
|
||||
TargetPlatform platform, {
|
||||
BuildInfo buildInfo,
|
||||
File applicationBinary,
|
||||
}) async => FakeApplicationPackage();
|
||||
}
|
||||
|
||||
class FakeApplicationPackage extends Fake implements ApplicationPackage { }
|
||||
|
|
Loading…
Reference in a new issue