1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:io' show File, Platform;
6import 'dart:typed_data';
7
8import 'package:collection/collection.dart';
9import 'package:flutter_devicelab/framework/devices.dart';
10import 'package:flutter_devicelab/framework/framework.dart';
11import 'package:flutter_devicelab/framework/task_result.dart';
12import 'package:flutter_devicelab/framework/utils.dart';
13import 'package:flutter_devicelab/tasks/integration_tests.dart';
14import 'package:path/path.dart' as path;
15import 'package:standard_message_codec/standard_message_codec.dart';
16
17Future<void> main() async {
18 deviceOperatingSystem = DeviceOperatingSystem.android;
19 await task(() async {
20 await createFlavorsTest().call();
21 await createIntegrationTestFlavorsTest().call();
22
23 final String projectPath = '${flutterDirectory.path}/dev/integration_tests/flavors';
24 final TaskResult installTestsResult = await inDirectory(projectPath, () async {
25 final List<TaskResult> testResults = <TaskResult>[
26 await _testInstallDebugPaidFlavor(projectPath),
27 await _testInstallBogusFlavor(),
28 ];
29
30 final TaskResult? firstInstallFailure = testResults.firstWhereOrNull(
31 (TaskResult element) => element.failed,
32 );
33
34 return firstInstallFailure ?? TaskResult.success(null);
35 });
36
37 await _testFlavorsWhenBuildStartsWithGradle(projectPath);
38
39 return installTestsResult;
40 });
41}
42
43// Ensures installation works. Also tests asset bundling while we are at it.
44Future<TaskResult> _testInstallDebugPaidFlavor(String projectDir) async {
45 await evalFlutter('install', options: <String>['--debug', '--flavor', 'paid']);
46
47 final Uint8List assetManifestFileData =
48 File(
49 path.join(
50 projectDir,
51 'build',
52 'app',
53 'intermediates',
54 'assets',
55 'paidDebug',
56 'mergePaidDebugAssets',
57 'flutter_assets',
58 'AssetManifest.bin',
59 ),
60 ).readAsBytesSync();
61
62 final Map<Object?, Object?> assetManifest =
63 const StandardMessageCodec().decodeMessage(ByteData.sublistView(assetManifestFileData))
64 as Map<Object?, Object?>;
65
66 if (assetManifest.containsKey('assets/free/free.txt')) {
67 return TaskResult.failure(
68 'Expected the asset "assets/free/free.txt", which '
69 ' was declared with a flavor of "free" to not be included in the asset bundle '
70 ' because the --flavor was set to "paid".',
71 );
72 }
73
74 if (!assetManifest.containsKey('assets/paid/paid.txt')) {
75 return TaskResult.failure(
76 'Expected the asset "assets/paid/paid.txt", which '
77 ' was declared with a flavor of "paid" to be included in the asset bundle '
78 ' because the --flavor was set to "paid".',
79 );
80 }
81
82 await flutter('install', options: <String>['--debug', '--flavor', 'paid', '--uninstall-only']);
83
84 return TaskResult.success(null);
85}
86
87Future<TaskResult> _testInstallBogusFlavor() async {
88 final StringBuffer stderr = StringBuffer();
89 await evalFlutter(
90 'install',
91 canFail: true,
92 stderr: stderr,
93 options: <String>['--flavor', 'bogus'],
94 );
95
96 final String stderrString = stderr.toString();
97 final String expectedApkPath = path.join(
98 'build',
99 'app',
100 'outputs',
101 'flutter-apk',
102 'app-bogus-release.apk',
103 );
104 if (!stderrString.contains('"$expectedApkPath" does not exist.')) {
105 print(stderrString);
106 return TaskResult.failure('Should not succeed with bogus flavor');
107 }
108
109 return TaskResult.success(null);
110}
111
112Future<TaskResult> _testFlavorsWhenBuildStartsWithGradle(String projectDir) async {
113 final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
114 final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
115
116 final String androidDirPath = '$projectDir/android';
117 final StringBuffer stdout = StringBuffer();
118
119 // Prebuild the project to generate the Android gradle wrapper files.
120 await inDirectory(projectDir, () async {
121 await flutter('build', options: <String>['apk', '--config-only']);
122 });
123
124 await inDirectory(androidDirPath, () async {
125 await exec(gradlewExecutable, <String>['clean']);
126 await exec(gradlewExecutable, <String>[':app:assemblePaidDebug', '--info'], output: stdout);
127 });
128
129 final String stdoutString = stdout.toString();
130
131 if (!stdoutString.contains('-dFlavor=paid')) {
132 return TaskResult.failure('Expected to see -dFlavor=paid in the gradle verbose output');
133 }
134
135 final String appPath = path.join(
136 projectDir,
137 'build',
138 'app',
139 'outputs',
140 'flutter-apk',
141 'app-paid-debug.apk',
142 );
143
144 return createFlavorsTest(
145 extraOptions: <String>['--flavor', 'paid', '--use-application-binary=$appPath'],
146 ).call();
147}
148

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com