Reland #40810: Re-enable AAR plugins when an AndroidX failure occurred (#41160)
diff --git a/packages/flutter_tools/test/general.shard/android/gradle_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
index 1c7c447..d2ff5d6 100644
--- a/packages/flutter_tools/test/general.shard/android/gradle_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
@@ -25,7 +25,6 @@
import '../../src/common.dart';
import '../../src/context.dart';
-import '../../src/mocks.dart';
import '../../src/pubspec_schema.dart';
void main() {
@@ -1150,6 +1149,153 @@
});
});
+ group('isAppUsingAndroidX', () {
+ FileSystem fs;
+
+ setUp(() {
+ fs = MemoryFileSystem();
+ });
+
+ testUsingContext('returns true when the project is using AndroidX', () async {
+ final Directory androidDirectory = fs.systemTempDirectory.createTempSync('android.');
+
+ androidDirectory
+ .childFile('gradle.properties')
+ .writeAsStringSync('android.useAndroidX=true');
+
+ expect(isAppUsingAndroidX(androidDirectory), isTrue);
+
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ });
+
+ testUsingContext('returns false when the project is not using AndroidX', () async {
+ final Directory androidDirectory = fs.systemTempDirectory.createTempSync('android.');
+
+ androidDirectory
+ .childFile('gradle.properties')
+ .writeAsStringSync('android.useAndroidX=false');
+
+ expect(isAppUsingAndroidX(androidDirectory), isFalse);
+
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ });
+
+ testUsingContext('returns false when gradle.properties does not exist', () async {
+ final Directory androidDirectory = fs.systemTempDirectory.createTempSync('android.');
+
+ expect(isAppUsingAndroidX(androidDirectory), isFalse);
+
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ });
+ });
+
+ group('buildPluginsAsAar', () {
+ FileSystem fs;
+ MockProcessManager mockProcessManager;
+ MockAndroidSdk mockAndroidSdk;
+
+ setUp(() {
+ fs = MemoryFileSystem();
+
+ mockProcessManager = MockProcessManager();
+ when(mockProcessManager.run(
+ any,
+ workingDirectory: anyNamed('workingDirectory'),
+ environment: anyNamed('environment'),
+ )).thenAnswer((_) async => ProcessResult(1, 0, '', ''));
+
+ mockAndroidSdk = MockAndroidSdk();
+ when(mockAndroidSdk.directory).thenReturn('irrelevant');
+ });
+
+ testUsingContext('calls gradle', () async {
+ final Directory androidDirectory = fs.directory('android.');
+ androidDirectory.createSync();
+ androidDirectory
+ .childFile('pubspec.yaml')
+ .writeAsStringSync('name: irrelevant');
+
+ final Directory plugin1 = fs.directory('plugin1.');
+ plugin1
+ ..createSync()
+ ..childFile('pubspec.yaml')
+ .writeAsStringSync('''
+name: irrelevant
+flutter:
+ plugin:
+ androidPackage: irrelevant
+''');
+ final Directory plugin2 = fs.directory('plugin2.');
+ plugin2
+ ..createSync()
+ ..childFile('pubspec.yaml')
+ .writeAsStringSync('''
+name: irrelevant
+flutter:
+ plugin:
+ androidPackage: irrelevant
+''');
+
+ androidDirectory
+ .childFile('.flutter-plugins')
+ .writeAsStringSync('''
+plugin1=${plugin1.path}
+plugin2=${plugin2.path}
+''');
+ final Directory buildDirectory = androidDirectory.childDirectory('build');
+ buildDirectory
+ .childDirectory('outputs')
+ .childDirectory('repo')
+ .createSync(recursive: true);
+
+ await buildPluginsAsAar(
+ FlutterProject.fromPath(androidDirectory.path),
+ const AndroidBuildInfo(BuildInfo.release),
+ buildDirectory: buildDirectory.path,
+ );
+
+ final String flutterRoot = fs.path.absolute(Cache.flutterRoot);
+ final String initScript = fs.path.join(flutterRoot, 'packages',
+ 'flutter_tools', 'gradle', 'aar_init_script.gradle');
+ verify(mockProcessManager.run(
+ <String>[
+ 'gradlew',
+ '-I=$initScript',
+ '-Pflutter-root=$flutterRoot',
+ '-Poutput-dir=${buildDirectory.path}',
+ '-Pis-plugin=true',
+ '-Ptarget-platform=android-arm,android-arm64',
+ 'assembleAarRelease',
+ ],
+ environment: anyNamed('environment'),
+ workingDirectory: plugin1.childDirectory('android').path),
+ ).called(1);
+
+ verify(mockProcessManager.run(
+ <String>[
+ 'gradlew',
+ '-I=$initScript',
+ '-Pflutter-root=$flutterRoot',
+ '-Poutput-dir=${buildDirectory.path}',
+ '-Pis-plugin=true',
+ '-Ptarget-platform=android-arm,android-arm64',
+ 'assembleAarRelease',
+ ],
+ environment: anyNamed('environment'),
+ workingDirectory: plugin2.childDirectory('android').path),
+ ).called(1);
+
+ }, overrides: <Type, Generator>{
+ AndroidSdk: () => mockAndroidSdk,
+ FileSystem: () => fs,
+ GradleUtils: () => FakeGradleUtils(),
+ ProcessManager: () => mockProcessManager,
+ });
+ });
+
group('gradle build', () {
MockAndroidSdk mockAndroidSdk;
MockAndroidStudio mockAndroidStudio;
@@ -1230,11 +1376,13 @@
fs.currentDirectory = 'path/to/project';
// Let any process start. Assert after.
- when(mockProcessManager.start(
+ when(mockProcessManager.run(
any,
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'))
- ).thenAnswer((Invocation invocation) => Future<Process>.value(MockProcess()));
+ ).thenAnswer(
+ (_) async => ProcessResult(1, 0, '', ''),
+ );
fs.directory('build/outputs/repo').createSync(recursive: true);
await buildGradleAar(
@@ -1244,11 +1392,11 @@
target: '',
);
- final List<String> actualGradlewCall = verify(mockProcessManager.start(
+ final List<String> actualGradlewCall = verify(mockProcessManager.run(
captureAny,
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
- ).captured.single;
+ ).captured.last;
expect(actualGradlewCall, contains('/path/to/project/.android/gradlew'));
expect(actualGradlewCall, contains('-PlocalEngineOut=out/android_arm'));
@@ -1279,6 +1427,14 @@
return FakePlatform.fromPlatform(const LocalPlatform())..operatingSystem = name;
}
+class FakeGradleUtils extends GradleUtils {
+ @override
+ Future<String> getExecutable(FlutterProject project) async {
+ return 'gradlew';
+ }
+}
+
+class MockAndroidSdk extends Mock implements AndroidSdk {}
class MockAndroidStudio extends Mock implements AndroidStudio {}
class MockDirectory extends Mock implements Directory {}
class MockFile extends Mock implements File {}