gradle_plugin_light_apk_test.dart 10.9 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 11 12 13 14 15 16
import 'package:flutter_devicelab/framework/utils.dart';

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

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

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

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

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

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

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

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

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

      await runPluginProjectTest((FlutterPluginProject pluginProject) async {
        section('APK content for task assembleDebug with target platform = android-x64');
        // This is used by `flutter run`
84 85 86 87 88 89 90 91 92 93 94

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

        final Iterable<String> apkFiles = await getFilesInApk(pluginProject.debugApkPath);
97

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

107
        checkCollectionDoesNotContain<String>(<String>[
108 109 110 111 112 113 114 115
          'lib/armeabi-v7a/libapp.so',
          'lib/x86/libapp.so',
          'lib/x86_64/libapp.so',
        ], apkFiles);
      });

      await runPluginProjectTest((FlutterPluginProject pluginProject) async {
        section('APK content for task assembleRelease with target platform = android-arm');
116 117 118 119 120 121 122 123 124 125 126

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

128
        final Iterable<String> apkFiles = await getFilesInApk(pluginProject.releaseApkPath);
129

130
        checkCollectionContains<String>(<String>[
131
          ...flutterAssets,
132
          ...baseApkFiles,
133 134 135 136
          'lib/armeabi-v7a/libflutter.so',
          'lib/armeabi-v7a/libapp.so',
        ], apkFiles);

137
        checkCollectionDoesNotContain<String>(<String>[
138
          ...debugAssets,
139 140 141 142 143 144 145
          'lib/arm64-v8a/libflutter.so',
          'lib/arm64-v8a/libapp.so',
        ], apkFiles);
      });

      await runPluginProjectTest((FlutterPluginProject pluginProject) async {
        section('APK content for task assembleRelease with target platform = android-arm64');
146 147 148 149 150 151 152 153 154 155 156

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

158
        final Iterable<String> apkFiles = await getFilesInApk(pluginProject.releaseApkPath);
159

160
        checkCollectionContains<String>(<String>[
161
          ...flutterAssets,
162
          ...baseApkFiles,
163 164 165 166
          'lib/arm64-v8a/libflutter.so',
          'lib/arm64-v8a/libapp.so',
        ], apkFiles);

167
        checkCollectionDoesNotContain<String>(<String>[
168
          ...debugAssets,
169 170 171 172 173 174 175
          'lib/armeabi-v7a/libflutter.so',
          'lib/armeabi-v7a/libapp.so',
        ], apkFiles);
      });

      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleDebug');
176 177 178 179 180 181 182 183 184
        await inDirectory(project.rootPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--debug',
            ],
          );
        });
185
        final String errorMessage = validateSnapshotDependency(project, 'kernel_blob.bin');
186 187 188 189 190 191 192
        if (errorMessage != null) {
          throw TaskResult.failure(errorMessage);
        }
      });

      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleProfile');
193 194 195 196 197 198 199 200 201
        await inDirectory(project.rootPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--profile',
            ],
          );
        });
202 203 204 205 206 207 208 209 210 211 212 213 214 215
      });

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

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

216 217 218 219 220 221 222 223 224 225 226
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleLocal (plugin with custom build type)');
        await project.addCustomBuildType('local', initWith: 'debug');
        await project.addGlobalBuildType('local', initWith: 'debug');
        section('Add plugin');
        await project.addPlugin('path_provider');
        await project.getPackages();

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

227 228
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleFreeDebug (product flavor)');
229
        await project.addProductFlavors(<String>['free']);
230 231 232 233 234 235
        await project.runGradleTask('assembleFreeDebug');
      });

      await runProjectTest((FlutterProject project) async {
        section('gradlew on build script with error');
        await project.introduceError();
236 237 238 239 240 241 242
        final ProcessResult result = await inDirectory(project.rootPath, () {
          return executeFlutter('build', options: <String>[
            'apk',
            '--release',
          ]);
        });

243 244 245
        if (result.exitCode == 0)
          throw failure(
              'Gradle did not exit with error as expected', result);
246
        final String output = '${result.stdout}\n${result.stderr}';
247 248 249 250 251 252 253 254 255 256 257
        if (output.contains('GradleException') ||
            output.contains('Failed to notify') ||
            output.contains('at org.gradle'))
          throw failure(
              'Gradle output should not contain stacktrace', result);
        if (!output.contains('Build failed') || !output.contains('builTypes'))
          throw failure(
              'Gradle output should contain a readable error message',
              result);
      });

258 259 260
      await runProjectTest((FlutterProject project) async {
        section('gradlew assembleDebug forwards stderr');
        await project.introducePubspecError();
261 262 263 264 265 266
        final ProcessResult result = await inDirectory(project.rootPath, () {
          return executeFlutter('build', options: <String>[
            'apk',
            '--release',
          ]);
        });
267 268 269 270 271 272 273 274
        if (result.exitCode == 0)
          throw failure(
              'Gradle did not exit with error as expected', result);
        final String output = '${result.stdout}\n${result.stderr}';
        if (!output.contains('No file or variants found for asset: lib/gallery/example_code.dart.'))
          throw failure(output, result);
      });

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

      await runPluginProjectTest((FlutterPluginProject pluginProject) async {
        section('gradlew assembleDebug on plugin example');
300 301 302 303 304 305 306 307 308
        await inDirectory(pluginProject.exampleAndroidPath, () {
          return flutter(
            'build',
            options: <String>[
              'apk',
              '--debug',
            ],
          );
        });
309
        if (!File(pluginProject.debugApkPath).existsSync())
310 311 312 313 314 315 316 317 318 319 320 321
          throw TaskResult.failure(
              'Gradle did not produce an apk file at the expected place');
      });

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