|
| 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 | + |
| 5 | +import 'dart:io'; |
| 6 | + |
| 7 | +import 'package:file/local.dart'; |
| 8 | +import 'task_result.dart'; |
| 9 | +import 'utils.dart'; |
| 10 | + |
| 11 | +// The following test outline shares a lot of similarities with |
| 12 | +// the one in packages/flutter_tools/test/src/android_common.dart. When making |
| 13 | +// changes here, consider making the corresponding changes to that file as well. |
| 14 | + |
| 15 | +/// The template settings.gradle content, with AGP and Kotlin versions replaced |
| 16 | +/// by an easily find/replaceable string. |
| 17 | +const String gradleSettingsFileContent = r''' |
| 18 | +pluginManagement { |
| 19 | + def flutterSdkPath = { |
| 20 | + def properties = new Properties() |
| 21 | + file("local.properties").withInputStream { properties.load(it) } |
| 22 | + def flutterSdkPath = properties.getProperty("flutter.sdk") |
| 23 | + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" |
| 24 | + return flutterSdkPath |
| 25 | + }() |
| 26 | +
|
| 27 | + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") |
| 28 | +
|
| 29 | + repositories { |
| 30 | + google() |
| 31 | + mavenCentral() |
| 32 | + gradlePluginPortal() |
| 33 | + } |
| 34 | +} |
| 35 | +
|
| 36 | +plugins { |
| 37 | + id "dev.flutter.flutter-plugin-loader" version "1.0.0" |
| 38 | + id "com.android.application" version "AGP_REPLACE_ME" apply false |
| 39 | + id "org.jetbrains.kotlin.android" version "KGP_REPLACE_ME" apply false |
| 40 | +} |
| 41 | +
|
| 42 | +include ":app" |
| 43 | +
|
| 44 | +'''; |
| 45 | + |
| 46 | +const String agpReplacementString = 'AGP_REPLACE_ME'; |
| 47 | +const String kgpReplacementString = 'KGP_REPLACE_ME'; |
| 48 | + |
| 49 | +/// The template gradle-wrapper.properties content, with the Gradle version replaced |
| 50 | +/// by an easily find/replaceable string. |
| 51 | +const String gradleWrapperPropertiesFileContent = r''' |
| 52 | +distributionBase=GRADLE_USER_HOME |
| 53 | +distributionPath=wrapper/dists |
| 54 | +zipStoreBase=GRADLE_USER_HOME |
| 55 | +zipStorePath=wrapper/dists |
| 56 | +distributionUrl=https\://services.gradle.org/distributions/gradle-GRADLE_REPLACE_ME-all.zip |
| 57 | +
|
| 58 | +'''; |
| 59 | + |
| 60 | +const String gradleReplacementString = 'GRADLE_REPLACE_ME'; |
| 61 | + |
| 62 | +/// A simple class containing a Kotlin, Gradle, and AGP version. |
| 63 | +class VersionTuple { |
| 64 | + |
| 65 | + VersionTuple({ |
| 66 | + required this.agpVersion, |
| 67 | + required this.gradleVersion, |
| 68 | + required this.kotlinVersion |
| 69 | + }); |
| 70 | + |
| 71 | + String agpVersion; |
| 72 | + String gradleVersion; |
| 73 | + String kotlinVersion; |
| 74 | + |
| 75 | + @override |
| 76 | + String toString() { |
| 77 | + return '(AGP version: $agpVersion, Gradle version: $gradleVersion, Kotlin version: $kotlinVersion)'; |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +/// For each [VersionTuple] in versionTuples: |
| 82 | +/// 1. Calls `flutter create` |
| 83 | +/// 2. Replaces the template AGP, Gradle, and Kotlin versions with those in the |
| 84 | +/// tuple. |
| 85 | +/// 3. Calls `flutter build apk`. |
| 86 | +/// Returns a failed task result if any of the `create` or `build apk` calls |
| 87 | +/// fails, returns a successful result otherwise. Cleans up in either case. |
| 88 | +Future<TaskResult> buildFlutterApkWithSpecifiedDependencyVersions({ |
| 89 | + required List<VersionTuple> versionTuples, |
| 90 | + required Directory tempDir, |
| 91 | + required LocalFileSystem localFileSystem,}) async { |
| 92 | + for (final VersionTuple versions in versionTuples) { |
| 93 | + final Directory innerTempDir = tempDir.createTempSync(versions.gradleVersion); |
| 94 | + try { |
| 95 | + // Create a new flutter project. |
| 96 | + section('Create new app with Gradle ${versions.gradleVersion}, AGP ${versions.agpVersion}, and Kotlin ${versions.kotlinVersion}'); |
| 97 | + await flutter( |
| 98 | + 'create', |
| 99 | + options: <String>[ |
| 100 | + 'dependency_checker_app', |
| 101 | + '--platforms=android', |
| 102 | + ], |
| 103 | + workingDirectory: innerTempDir.path, |
| 104 | + ); |
| 105 | + |
| 106 | + final String appPath = '${innerTempDir.absolute.path}/dependency_checker_app'; |
| 107 | + |
| 108 | + // Modify gradle version to passed in version. |
| 109 | + final File gradleWrapperProperties = localFileSystem.file(localFileSystem.path.join( |
| 110 | + appPath, 'android', 'gradle', 'wrapper', 'gradle-wrapper.properties')); |
| 111 | + final String propertyContent = gradleWrapperPropertiesFileContent.replaceFirst( |
| 112 | + gradleReplacementString, |
| 113 | + versions.gradleVersion, |
| 114 | + ); |
| 115 | + await gradleWrapperProperties.writeAsString(propertyContent, flush: true); |
| 116 | + |
| 117 | + final File gradleSettings = localFileSystem.file(localFileSystem.path.join( |
| 118 | + appPath, 'android', 'settings.gradle')); |
| 119 | + final String settingsContent = gradleSettingsFileContent |
| 120 | + .replaceFirst(agpReplacementString, versions.agpVersion) |
| 121 | + .replaceFirst(kgpReplacementString, versions.kotlinVersion); |
| 122 | + await gradleSettings.writeAsString(settingsContent, flush: true); |
| 123 | + |
| 124 | + |
| 125 | + // Ensure that gradle files exists from templates. |
| 126 | + section("Ensure 'flutter build apk' succeeds with Gradle ${versions.gradleVersion}, AGP ${versions.agpVersion}, and Kotlin ${versions.kotlinVersion}"); |
| 127 | + await flutter( |
| 128 | + 'build', |
| 129 | + options: <String>[ |
| 130 | + 'apk', |
| 131 | + '--debug', |
| 132 | + ], |
| 133 | + workingDirectory: appPath, |
| 134 | + ); |
| 135 | + } catch (e) { |
| 136 | + tempDir.deleteSync(recursive: true); |
| 137 | + return TaskResult.failure('Failed to build app with Gradle ${versions.gradleVersion}, AGP ${versions.agpVersion}, and Kotlin ${versions.kotlinVersion}, error was:\n$e'); |
| 138 | + } |
| 139 | + } |
| 140 | + tempDir.deleteSync(recursive: true); |
| 141 | + return TaskResult.success(null); |
| 142 | +} |
0 commit comments