[tool] Support --flavor option for flutter install. (#114048)

* Alphabetize setup calls

* Add --flavor as an option for install

* Add verbose logging in install command

* Test that flavors build succeeds with proper flavor and fails with bogus one.

* Remove unused import

* The import was used...

* SQUASH

* Add flavor install test

* Rename test

* Add flavors install integration tests

* correct error message

* remove unused imports

* Delete copy test

* update test target

* Refactor mechanism to read buildInfo

* Remove unused import

* Set affected test targets to bringup: true

Co-authored-by: a-wallen <stephenwallen@google.com>
This commit is contained in:
Alex Wallen 2022-11-08 14:53:23 -08:00 committed by GitHub
parent 1725a26e29
commit 7020f59ace
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 89 additions and 28 deletions

View file

@ -1687,6 +1687,7 @@ targets:
task_name: fast_scroll_large_images__memory
- name: Linux_android flavors_test
bringup: true
recipe: devicelab/devicelab_drone
presubmit: false
timeout: 60
@ -3371,6 +3372,7 @@ targets:
task_name: route_test_ios
- name: Mac_ios flavors_test_ios
bringup: true
recipe: devicelab/devicelab_drone
presubmit: false
timeout: 60
@ -4537,7 +4539,7 @@ targets:
properties:
tags: >
["devicelab", "android", "windows"]
task_name: flavors_test_win
task_name: flavors_test
- name: Windows_android flutter_gallery_win__compile
recipe: devicelab/devicelab_drone

View file

@ -5,6 +5,7 @@
import 'package:flutter_devicelab/framework/devices.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/task_result.dart';
import 'package:flutter_devicelab/framework/utils.dart';
import 'package:flutter_devicelab/tasks/integration_tests.dart';
Future<void> main() async {
@ -12,6 +13,30 @@ Future<void> main() async {
await task(() async {
await createFlavorsTest().call();
await createIntegrationTestFlavorsTest().call();
// test install and uninstall of flavors app
await inDirectory('${flutterDirectory.path}/dev/integration_tests/flavors', () async {
await flutter(
'install',
options: <String>['--flavor', 'paid'],
);
await flutter(
'install',
options: <String>['--flavor', 'paid', '--uninstall-only'],
);
final StringBuffer stderr = StringBuffer();
await evalFlutter(
'install',
canFail: true,
stderr: stderr,
options: <String>['--flavor', 'bogus'],
);
final String stderrString = stderr.toString();
if (!stderrString.contains('The Xcode project defines schemes: free, paid')) {
print(stderrString);
return TaskResult.failure('Should not succeed with bogus flavor');
}
});
return TaskResult.success(null);
});

View file

@ -5,6 +5,7 @@
import 'package:flutter_devicelab/framework/devices.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/task_result.dart';
import 'package:flutter_devicelab/framework/utils.dart';
import 'package:flutter_devicelab/tasks/integration_tests.dart';
Future<void> main() async {
@ -12,6 +13,30 @@ Future<void> main() async {
await task(() async {
await createFlavorsTest().call();
await createIntegrationTestFlavorsTest().call();
// test install and uninstall of flavors app
await inDirectory('${flutterDirectory.path}/dev/integration_tests/flavors', () async {
await flutter(
'install',
options: <String>['--flavor', 'paid'],
);
await flutter(
'install',
options: <String>['--flavor', 'paid', '--uninstall-only'],
);
final StringBuffer stderr = StringBuffer();
await evalFlutter(
'install',
canFail: true,
stderr: stderr,
options: <String>['--flavor', 'bogus'],
);
final String stderrString = stderr.toString();
if (!stderrString.contains('install failed, bogus flavor not found')) {
print(stderrString);
return TaskResult.failure('Should not succeed with bogus flavor');
}
});
return TaskResult.success(null);
});

View file

@ -1,18 +0,0 @@
// 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 'package:flutter_devicelab/framework/devices.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/task_result.dart';
import 'package:flutter_devicelab/tasks/integration_tests.dart';
Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.android;
await task(() async {
await createFlavorsTest().call();
await createIntegrationTestFlavorsTest().call();
return TaskResult.success(null);
});
}

View file

@ -200,7 +200,9 @@ List<FlutterCommand> generateCommands({
artifacts: globals.artifacts!,
processManager: globals.processManager,
),
InstallCommand(),
InstallCommand(
verboseHelp: verboseHelp,
),
LogsCommand(),
MakeHostAppEditableCommand(),
PackagesCommand(),

View file

@ -12,11 +12,15 @@ import '../globals.dart' as globals;
import '../runner/flutter_command.dart';
class InstallCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
InstallCommand() {
InstallCommand({
required bool verboseHelp,
}) {
addBuildModeFlags(verboseHelp: verboseHelp);
requiresPubspecYaml();
usesDeviceUserOption();
usesDeviceTimeoutOption();
usesApplicationBinaryOption();
usesDeviceTimeoutOption();
usesDeviceUserOption();
usesFlavorOption();
argParser.addFlag('uninstall-only',
help: 'Uninstall the app if already on the device. Skip install.',
);
@ -60,6 +64,7 @@ class InstallCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts
final ApplicationPackage? package = await applicationPackages?.getPackageForPlatform(
await targetDevice.targetPlatform,
applicationBinary: _applicationBinary,
buildInfo: await getBuildInfo(),
);
if (package == null) {
throwToolExit('Could not find or build package');

View file

@ -32,7 +32,7 @@ void main() {
});
testUsingContext('returns 0 when Android is connected and ready for an install', () async {
final InstallCommand command = InstallCommand();
final InstallCommand command = InstallCommand(verboseHelp: false);
command.applicationPackages = FakeApplicationPackageFactory(FakeAndroidApk());
final FakeAndroidDevice device = FakeAndroidDevice();
@ -46,7 +46,7 @@ void main() {
});
testUsingContext('returns 1 when targeted device is not Android with --device-user', () async {
final InstallCommand command = InstallCommand();
final InstallCommand command = InstallCommand(verboseHelp: false);
command.applicationPackages = FakeApplicationPackageFactory(FakeAndroidApk());
final FakeIOSDevice device = FakeIOSDevice();
@ -61,7 +61,7 @@ void main() {
});
testUsingContext('returns 0 when iOS is connected and ready for an install', () async {
final InstallCommand command = InstallCommand();
final InstallCommand command = InstallCommand(verboseHelp: false);
command.applicationPackages = FakeApplicationPackageFactory(FakeIOSApp());
final FakeIOSDevice device = FakeIOSDevice();
@ -75,7 +75,7 @@ void main() {
});
testUsingContext('fails when prebuilt binary not found', () async {
final InstallCommand command = InstallCommand();
final InstallCommand command = InstallCommand(verboseHelp: false);
command.applicationPackages = FakeApplicationPackageFactory(FakeAndroidApk());
final FakeAndroidDevice device = FakeAndroidDevice();
@ -90,7 +90,7 @@ void main() {
});
testUsingContext('succeeds using prebuilt binary', () async {
final InstallCommand command = InstallCommand();
final InstallCommand command = InstallCommand(verboseHelp: false);
command.applicationPackages = FakeApplicationPackageFactory(FakeAndroidApk());
final FakeAndroidDevice device = FakeAndroidDevice();
@ -103,6 +103,24 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Passes flavor to application package.', () async {
const String flavor = 'free';
final InstallCommand command = InstallCommand(verboseHelp: false);
final FakeApplicationPackageFactory fakeAppFactory = FakeApplicationPackageFactory(FakeIOSApp());
command.applicationPackages = fakeAppFactory;
final FakeIOSDevice device = FakeIOSDevice();
testDeviceManager.addDevice(device);
await createTestCommandRunner(command).run(<String>['install', '--flavor', flavor]);
expect(fakeAppFactory.buildInfo, isNotNull);
expect(fakeAppFactory.buildInfo!.flavor, flavor);
}, overrides: <Type, Generator>{
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
});
}
@ -110,9 +128,11 @@ class FakeApplicationPackageFactory extends Fake implements ApplicationPackageFa
FakeApplicationPackageFactory(this.app);
final ApplicationPackage app;
BuildInfo? buildInfo;
@override
Future<ApplicationPackage> getPackageForPlatform(TargetPlatform platform, {BuildInfo? buildInfo, File? applicationBinary}) async {
this.buildInfo = buildInfo;
return app;
}
}