gradle_plugin_light_apk_test.dart 10.7 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:flutter_devicelab/framework/apk_utils.dart';
import 'package:flutter_devicelab/framework/framework.dart';
9
import 'package:flutter_devicelab/framework/task_result.dart';
10
import 'package:flutter_devicelab/framework/utils.dart';
11
import 'package:path/path.dart' as path;
12 13 14 15 16 17

Future<void> main() async {
  await task(() async {
    try {
      await runPluginProjectTest((FlutterPluginProject pluginProject) async {
        section('APK content for task assembleDebug with target platform = android-arm');
18 19 20 21 22 23 24

        await inDirectory(pluginProject.exampleAndroidPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--debug',
25
              '--target-platform=android-arm',
26 27 28
            ],
          );
        });
29

30
        Iterable<String> apkFiles = await getFilesInApk(pluginProject.debugApkPath);
31

32
        checkCollectionContains<String>(<String>[
33
          ...flutterAssets,
34 35
          ...debugAssets,
          ...baseApkFiles,
36 37 38 39 40 41
          'lib/armeabi-v7a/libflutter.so',
          // Debug mode intentionally includes `x86` and `x86_64`.
          'lib/x86/libflutter.so',
          'lib/x86_64/libflutter.so',
        ], apkFiles);

42
        checkCollectionDoesNotContain<String>(<String>[
43
          'lib/arm64-v8a/libapp.so',
44 45 46 47 48 49 50
          'lib/armeabi-v7a/libapp.so',
          'lib/x86/libapp.so',
          'lib/x86_64/libapp.so',
        ], apkFiles);

        section('APK content for task assembleDebug with target platform = android-x86');
        // This is used by `flutter run`
51 52 53 54 55 56
        await inDirectory(pluginProject.exampleAndroidPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--debug',
57
              '--target-platform=android-x86',
58 59 60
            ],
          );
        });
61

62
        apkFiles = await getFilesInApk(pluginProject.debugApkPath);
63

64
        checkCollectionContains<String>(<String>[
65
          ...flutterAssets,
66 67
          ...debugAssets,
          ...baseApkFiles,
68 69 70 71
          // Debug mode intentionally includes `x86` and `x86_64`.
          'lib/x86/libflutter.so',
          'lib/x86_64/libflutter.so',
        ], apkFiles);
72

73
        checkCollectionDoesNotContain<String>(<String>[
74 75 76 77 78 79 80
          'lib/armeabi-v7a/libapp.so',
          'lib/x86/libapp.so',
          'lib/x86_64/libapp.so',
        ], apkFiles);

        section('APK content for task assembleDebug with target platform = android-x64');
        // This is used by `flutter run`
81 82 83 84 85 86 87

        await inDirectory(pluginProject.exampleAndroidPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--debug',
88
              '--target-platform=android-x64',
89 90 91
            ],
          );
        });
92

93
        apkFiles = await getFilesInApk(pluginProject.debugApkPath);
94

95
        checkCollectionContains<String>(<String>[
96
          ...flutterAssets,
97 98
          ...debugAssets,
          ...baseApkFiles,
99 100 101 102 103
          // Debug mode intentionally includes `x86` and `x86_64`.
          'lib/x86/libflutter.so',
          'lib/x86_64/libflutter.so',
        ], apkFiles);

104
        checkCollectionDoesNotContain<String>(<String>[
105 106 107 108 109 110
          'lib/armeabi-v7a/libapp.so',
          'lib/x86/libapp.so',
          'lib/x86_64/libapp.so',
        ], apkFiles);

        section('APK content for task assembleRelease with target platform = android-arm');
111 112 113 114 115 116 117

        await inDirectory(pluginProject.exampleAndroidPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--release',
118
              '--target-platform=android-arm',
119 120 121
            ],
          );
        });
122

123
        apkFiles = await getFilesInApk(pluginProject.releaseApkPath);
124

125
        checkCollectionContains<String>(<String>[
126
          ...flutterAssets,
127
          ...baseApkFiles,
128 129 130 131
          'lib/armeabi-v7a/libflutter.so',
          'lib/armeabi-v7a/libapp.so',
        ], apkFiles);

132
        checkCollectionDoesNotContain<String>(<String>[
133
          ...debugAssets,
134 135 136 137 138
          'lib/arm64-v8a/libflutter.so',
          'lib/arm64-v8a/libapp.so',
        ], apkFiles);

        section('APK content for task assembleRelease with target platform = android-arm64');
139 140 141 142 143 144 145

        await inDirectory(pluginProject.exampleAndroidPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--release',
146
              '--target-platform=android-arm64',
147 148 149
            ],
          );
        });
150

151
        apkFiles = await getFilesInApk(pluginProject.releaseApkPath);
152

153
        checkCollectionContains<String>(<String>[
154
          ...flutterAssets,
155
          ...baseApkFiles,
156 157 158 159
          'lib/arm64-v8a/libflutter.so',
          'lib/arm64-v8a/libapp.so',
        ], apkFiles);

160
        checkCollectionDoesNotContain<String>(<String>[
161
          ...debugAssets,
162 163 164 165 166 167 168
          'lib/armeabi-v7a/libflutter.so',
          'lib/armeabi-v7a/libapp.so',
        ], apkFiles);
      });

      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleDebug');
169 170 171 172 173 174 175 176 177
        await inDirectory(project.rootPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--debug',
            ],
          );
        });
178
        final String? errorMessage = validateSnapshotDependency(project, 'kernel_blob.bin');
179 180 181 182 183
        if (errorMessage != null) {
          throw TaskResult.failure(errorMessage);
        }

        section('gradlew assembleProfile');
184 185 186 187 188 189 190 191 192
        await inDirectory(project.rootPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--profile',
            ],
          );
        });
193 194 195 196 197 198

        section('gradlew assembleLocal (custom debug build)');
        await project.addCustomBuildType('local', initWith: 'debug');
        await project.runGradleTask('assembleLocal');
      });

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleLocal with plugin (custom debug build)');

        final Directory tempDir = Directory.systemTemp.createTempSync('flutter_plugin.');
        final Directory pluginDir = Directory(path.join(tempDir.path, 'plugin_under_test'));

        section('Create plugin');
        await inDirectory(tempDir, () async {
          await flutter(
            'create',
            options: <String>[
              '--org',
              'io.flutter.devicelab.plugin',
              '--template=plugin',
              '--platforms=android,ios',
              pluginDir.path,
            ],
          );
        });

        section('Configure');
220 221
        project.addPlugin('plugin_under_test',
            value: '$platformLineSep    path: ${pluginDir.path}');
222 223 224 225 226 227 228
        await project.addCustomBuildType('local', initWith: 'debug');
        await project.getPackages();

        section('Build APK');
        await project.runGradleTask('assembleLocal');
      });

229 230 231 232 233 234
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleBeta (custom release build)');
        await project.addCustomBuildType('beta', initWith: 'release');
        await project.runGradleTask('assembleBeta');
      });

235 236 237 238
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleLocal (plugin with custom build type)');
        await project.addCustomBuildType('local', initWith: 'debug');
        section('Add plugin');
239
        project.addPlugin('path_provider');
240 241 242 243 244
        await project.getPackages();

        await project.runGradleTask('assembleLocal');
      });

245 246
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleFreeDebug (product flavor)');
247
        await project.addProductFlavors(<String>['free']);
248 249 250 251 252 253
        await project.runGradleTask('assembleFreeDebug');
      });

      await runProjectTest((FlutterProject project) async {
        section('gradlew on build script with error');
        await project.introduceError();
254
        ProcessResult result = await inDirectory(project.rootPath, () {
255 256 257 258 259 260
          return executeFlutter('build', options: <String>[
            'apk',
            '--release',
          ]);
        });

261
        if (result.exitCode == 0) {
262 263
          throw failure(
              'Gradle did not exit with error as expected', result);
264
        }
265
        String output = '${result.stdout}\n${result.stderr}';
266 267
        if (output.contains('GradleException') ||
            output.contains('Failed to notify') ||
268
            output.contains('at org.gradle')) {
269 270
          throw failure(
              'Gradle output should not contain stacktrace', result);
271 272
        }
        if (!output.contains('Build failed')) {
273 274 275
          throw failure(
              'Gradle output should contain a readable error message',
              result);
276
        }
277

278 279
        section('flutter build apk on build script with error');
        await project.introduceError();
280
        result = await inDirectory(project.rootPath, () {
281 282 283 284 285
          return executeFlutter('build', options: <String>[
            'apk',
            '--release',
          ]);
        });
286
        if (result.exitCode == 0) {
287 288
          throw failure(
              'flutter build apk should fail when Gradle does', result);
289
        }
290
        output = '${result.stdout}\n${result.stderr}';
291
        if (!output.contains('Build failed')) {
292 293 294
          throw failure(
              'flutter build apk output should contain a readable Gradle error message',
              result);
295 296
        }
        if (hasMultipleOccurrences(output, 'Build failed')) {
297 298 299
          throw failure(
              'flutter build apk should not invoke Gradle repeatedly on error',
              result);
300
        }
301 302
      });

303 304 305 306 307 308 309 310
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleDebug forwards stderr');
        await project.introducePubspecError();
        final ProcessResult result = await inDirectory(project.rootPath, () {
          return executeFlutter('build', options: <String>[
            'apk',
            '--release',
          ]);
311
        });
312
        if (result.exitCode == 0) {
313 314
          throw failure(
              'Gradle did not exit with error as expected', result);
315
        }
316
        final String output = '${result.stdout}\n${result.stderr}';
317
        if (!output.contains('No file or variants found for asset: lib/gallery/example_code.dart.')) {
318
          throw failure(output, result);
319
        }
320 321 322 323 324 325 326 327 328 329
      });

      return TaskResult.success(null);
    } on TaskResult catch (taskResult) {
      return taskResult;
    } catch (e) {
      return TaskResult.failure(e.toString());
    }
  });
}