mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
359 lines
14 KiB
Dart
359 lines
14 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:file/memory.dart';
|
|
import 'package:flutter_tools/src/android/gradle_utils.dart';
|
|
import 'package:flutter_tools/src/base/file_system.dart';
|
|
import 'package:flutter_tools/src/base/os.dart';
|
|
import 'package:flutter_tools/src/cache.dart';
|
|
import 'package:flutter_tools/src/project.dart';
|
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
|
import 'package:mockito/mockito.dart';
|
|
import 'package:process/process.dart';
|
|
|
|
import '../../src/common.dart';
|
|
import '../../src/context.dart';
|
|
|
|
void main() {
|
|
group('injectGradleWrapperIfNeeded', () {
|
|
MemoryFileSystem memoryFileSystem;
|
|
Directory tempDir;
|
|
Directory gradleWrapperDirectory;
|
|
|
|
setUp(() {
|
|
memoryFileSystem = MemoryFileSystem();
|
|
tempDir = memoryFileSystem.systemTempDirectory.createTempSync('flutter_artifacts_test.');
|
|
gradleWrapperDirectory = memoryFileSystem.directory(
|
|
memoryFileSystem.path.join(tempDir.path, 'bin', 'cache', 'artifacts', 'gradle_wrapper'));
|
|
gradleWrapperDirectory.createSync(recursive: true);
|
|
gradleWrapperDirectory
|
|
.childFile('gradlew')
|
|
.writeAsStringSync('irrelevant');
|
|
gradleWrapperDirectory
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.createSync(recursive: true);
|
|
gradleWrapperDirectory
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.childFile('gradle-wrapper.jar')
|
|
.writeAsStringSync('irrelevant');
|
|
});
|
|
|
|
testUsingContext('injects the wrapper when all files are missing', () {
|
|
final Directory sampleAppAndroid = globals.fs.directory('/sample-app/android');
|
|
sampleAppAndroid.createSync(recursive: true);
|
|
|
|
gradleUtils.injectGradleWrapperIfNeeded(sampleAppAndroid);
|
|
|
|
expect(sampleAppAndroid.childFile('gradlew').existsSync(), isTrue);
|
|
|
|
expect(sampleAppAndroid
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.childFile('gradle-wrapper.jar')
|
|
.existsSync(), isTrue);
|
|
|
|
expect(sampleAppAndroid
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.childFile('gradle-wrapper.properties')
|
|
.existsSync(), isTrue);
|
|
|
|
expect(sampleAppAndroid
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.childFile('gradle-wrapper.properties')
|
|
.readAsStringSync(),
|
|
'distributionBase=GRADLE_USER_HOME\n'
|
|
'distributionPath=wrapper/dists\n'
|
|
'zipStoreBase=GRADLE_USER_HOME\n'
|
|
'zipStorePath=wrapper/dists\n'
|
|
'distributionUrl=https\\://services.gradle.org/distributions/gradle-5.6.2-all.zip\n');
|
|
}, overrides: <Type, Generator>{
|
|
Cache: () => Cache(rootOverride: tempDir),
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
|
|
testUsingContext('injects the wrapper when some files are missing', () {
|
|
final Directory sampleAppAndroid = globals.fs.directory('/sample-app/android');
|
|
sampleAppAndroid.createSync(recursive: true);
|
|
|
|
// There's an existing gradlew
|
|
sampleAppAndroid.childFile('gradlew').writeAsStringSync('existing gradlew');
|
|
|
|
gradleUtils.injectGradleWrapperIfNeeded(sampleAppAndroid);
|
|
|
|
expect(sampleAppAndroid.childFile('gradlew').existsSync(), isTrue);
|
|
expect(sampleAppAndroid.childFile('gradlew').readAsStringSync(),
|
|
equals('existing gradlew'));
|
|
|
|
expect(sampleAppAndroid
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.childFile('gradle-wrapper.jar')
|
|
.existsSync(), isTrue);
|
|
|
|
expect(sampleAppAndroid
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.childFile('gradle-wrapper.properties')
|
|
.existsSync(), isTrue);
|
|
|
|
expect(sampleAppAndroid
|
|
.childDirectory('gradle')
|
|
.childDirectory('wrapper')
|
|
.childFile('gradle-wrapper.properties')
|
|
.readAsStringSync(),
|
|
'distributionBase=GRADLE_USER_HOME\n'
|
|
'distributionPath=wrapper/dists\n'
|
|
'zipStoreBase=GRADLE_USER_HOME\n'
|
|
'zipStorePath=wrapper/dists\n'
|
|
'distributionUrl=https\\://services.gradle.org/distributions/gradle-5.6.2-all.zip\n');
|
|
}, overrides: <Type, Generator>{
|
|
Cache: () => Cache(rootOverride: tempDir),
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
});
|
|
|
|
|
|
group('migrateToR8', () {
|
|
MemoryFileSystem memoryFileSystem;
|
|
|
|
setUp(() {
|
|
memoryFileSystem = MemoryFileSystem();
|
|
});
|
|
|
|
testUsingContext('throws ToolExit if gradle.properties doesn\'t exist', () {
|
|
final Directory sampleAppAndroid = globals.fs.directory('/sample-app/android');
|
|
sampleAppAndroid.createSync(recursive: true);
|
|
|
|
expect(() {
|
|
gradleUtils.migrateToR8(sampleAppAndroid);
|
|
}, throwsToolExit(message: 'Expected file ${sampleAppAndroid.path}'));
|
|
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
|
|
testUsingContext('throws ToolExit if it cannot write gradle.properties', () {
|
|
final MockDirectory sampleAppAndroid = MockDirectory();
|
|
final MockFile gradleProperties = MockFile();
|
|
|
|
when(gradleProperties.path).thenReturn('foo/gradle.properties');
|
|
when(gradleProperties.existsSync()).thenReturn(true);
|
|
when(gradleProperties.readAsStringSync()).thenReturn('');
|
|
when(gradleProperties.writeAsStringSync('android.enableR8=true\n', mode: FileMode.append))
|
|
.thenThrow(const FileSystemException());
|
|
|
|
when(sampleAppAndroid.childFile('gradle.properties'))
|
|
.thenReturn(gradleProperties);
|
|
|
|
expect(() {
|
|
gradleUtils.migrateToR8(sampleAppAndroid);
|
|
},
|
|
throwsToolExit(message:
|
|
'The tool failed to add `android.enableR8=true` to foo/gradle.properties. '
|
|
'Please update the file manually and try this command again.'));
|
|
});
|
|
|
|
testUsingContext('does not update gradle.properties if it already uses R8', () {
|
|
final Directory sampleAppAndroid = globals.fs.directory('/sample-app/android');
|
|
sampleAppAndroid.createSync(recursive: true);
|
|
sampleAppAndroid.childFile('gradle.properties')
|
|
.writeAsStringSync('android.enableR8=true');
|
|
|
|
gradleUtils.migrateToR8(sampleAppAndroid);
|
|
|
|
expect(testLogger.traceText,
|
|
contains('gradle.properties already sets `android.enableR8`'));
|
|
expect(sampleAppAndroid.childFile('gradle.properties').readAsStringSync(),
|
|
equals('android.enableR8=true'));
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
|
|
testUsingContext('sets android.enableR8=true', () {
|
|
final Directory sampleAppAndroid = globals.fs.directory('/sample-app/android');
|
|
sampleAppAndroid.createSync(recursive: true);
|
|
sampleAppAndroid.childFile('gradle.properties')
|
|
.writeAsStringSync('org.gradle.jvmargs=-Xmx1536M\n');
|
|
|
|
gradleUtils.migrateToR8(sampleAppAndroid);
|
|
|
|
expect(testLogger.traceText, contains('set `android.enableR8=true` in gradle.properties'));
|
|
expect(
|
|
sampleAppAndroid.childFile('gradle.properties').readAsStringSync(),
|
|
equals(
|
|
'org.gradle.jvmargs=-Xmx1536M\n'
|
|
'android.enableR8=true\n'
|
|
),
|
|
);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
|
|
testUsingContext('appends android.enableR8=true to the new line', () {
|
|
final Directory sampleAppAndroid = globals.fs.directory('/sample-app/android');
|
|
sampleAppAndroid.createSync(recursive: true);
|
|
sampleAppAndroid.childFile('gradle.properties')
|
|
.writeAsStringSync('org.gradle.jvmargs=-Xmx1536M');
|
|
|
|
gradleUtils.migrateToR8(sampleAppAndroid);
|
|
|
|
expect(testLogger.traceText, contains('set `android.enableR8=true` in gradle.properties'));
|
|
expect(
|
|
sampleAppAndroid.childFile('gradle.properties').readAsStringSync(),
|
|
equals(
|
|
'org.gradle.jvmargs=-Xmx1536M\n'
|
|
'android.enableR8=true\n'
|
|
),
|
|
);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any()
|
|
});
|
|
});
|
|
|
|
group('GradleUtils.getExecutable', () {
|
|
final String gradlewFilename = globals.platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
|
|
|
MemoryFileSystem memoryFileSystem;
|
|
OperatingSystemUtils operatingSystemUtils;
|
|
MockGradleUtils gradleUtils;
|
|
|
|
setUp(() {
|
|
memoryFileSystem = MemoryFileSystem();
|
|
operatingSystemUtils = MockOperatingSystemUtils();
|
|
gradleUtils = MockGradleUtils();
|
|
});
|
|
|
|
testUsingContext('returns the gradlew path', () {
|
|
final Directory androidDirectory = globals.fs.directory('/android')..createSync();
|
|
androidDirectory.childFile('gradlew')..createSync();
|
|
androidDirectory.childFile('gradlew.bat')..createSync();
|
|
androidDirectory.childFile('gradle.properties').createSync();
|
|
|
|
when(gradleUtils.injectGradleWrapperIfNeeded(any)).thenReturn(null);
|
|
when(gradleUtils.migrateToR8(any)).thenReturn(null);
|
|
|
|
expect(
|
|
GradleUtils().getExecutable(FlutterProject.current()),
|
|
androidDirectory.childFile(gradlewFilename).path,
|
|
);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
OperatingSystemUtils: () => operatingSystemUtils,
|
|
GradleUtils: () => gradleUtils,
|
|
});
|
|
|
|
testUsingContext('gives execute permission to gradle', () {
|
|
final FlutterProject flutterProject = MockFlutterProject();
|
|
final AndroidProject androidProject = MockAndroidProject();
|
|
when(flutterProject.android).thenReturn(androidProject);
|
|
|
|
final FileStat gradleStat = MockFileStat();
|
|
when(gradleStat.mode).thenReturn(444);
|
|
|
|
final File gradlew = MockFile();
|
|
when(gradlew.path).thenReturn('gradlew');
|
|
when(gradlew.absolute).thenReturn(gradlew);
|
|
when(gradlew.statSync()).thenReturn(gradleStat);
|
|
when(gradlew.existsSync()).thenReturn(true);
|
|
|
|
final Directory androidDirectory = MockDirectory();
|
|
when(androidDirectory.childFile(gradlewFilename)).thenReturn(gradlew);
|
|
when(androidProject.hostAppGradleRoot).thenReturn(androidDirectory);
|
|
|
|
when(gradleUtils.injectGradleWrapperIfNeeded(any)).thenReturn(null);
|
|
when(gradleUtils.migrateToR8(any)).thenReturn(null);
|
|
|
|
GradleUtils().getExecutable(flutterProject);
|
|
|
|
verify(operatingSystemUtils.makeExecutable(gradlew)).called(1);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
OperatingSystemUtils: () => operatingSystemUtils,
|
|
GradleUtils: () => gradleUtils,
|
|
});
|
|
|
|
testUsingContext('gives execute permission to gradle even when not all permission flags are set', () {
|
|
final FlutterProject flutterProject = MockFlutterProject();
|
|
final AndroidProject androidProject = MockAndroidProject();
|
|
when(flutterProject.android).thenReturn(androidProject);
|
|
|
|
final FileStat gradleStat = MockFileStat();
|
|
when(gradleStat.mode).thenReturn(400);
|
|
|
|
final File gradlew = MockFile();
|
|
when(gradlew.path).thenReturn('gradlew');
|
|
when(gradlew.absolute).thenReturn(gradlew);
|
|
when(gradlew.statSync()).thenReturn(gradleStat);
|
|
when(gradlew.existsSync()).thenReturn(true);
|
|
|
|
final Directory androidDirectory = MockDirectory();
|
|
when(androidDirectory.childFile(gradlewFilename)).thenReturn(gradlew);
|
|
when(androidProject.hostAppGradleRoot).thenReturn(androidDirectory);
|
|
|
|
when(gradleUtils.injectGradleWrapperIfNeeded(any)).thenReturn(null);
|
|
when(gradleUtils.migrateToR8(any)).thenReturn(null);
|
|
|
|
GradleUtils().getExecutable(flutterProject);
|
|
|
|
verify(operatingSystemUtils.makeExecutable(gradlew)).called(1);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
OperatingSystemUtils: () => operatingSystemUtils,
|
|
GradleUtils: () => gradleUtils,
|
|
});
|
|
|
|
testUsingContext('doesn\'t give execute permission to gradle if not needed', () {
|
|
final FlutterProject flutterProject = MockFlutterProject();
|
|
final AndroidProject androidProject = MockAndroidProject();
|
|
when(flutterProject.android).thenReturn(androidProject);
|
|
|
|
final FileStat gradleStat = MockFileStat();
|
|
when(gradleStat.mode).thenReturn(0x49 /* a+x */);
|
|
|
|
final File gradlew = MockFile();
|
|
when(gradlew.path).thenReturn('gradlew');
|
|
when(gradlew.absolute).thenReturn(gradlew);
|
|
when(gradlew.statSync()).thenReturn(gradleStat);
|
|
when(gradlew.existsSync()).thenReturn(true);
|
|
|
|
final Directory androidDirectory = MockDirectory();
|
|
when(androidDirectory.childFile(gradlewFilename)).thenReturn(gradlew);
|
|
when(androidProject.hostAppGradleRoot).thenReturn(androidDirectory);
|
|
|
|
when(gradleUtils.injectGradleWrapperIfNeeded(any)).thenReturn(null);
|
|
when(gradleUtils.migrateToR8(any)).thenReturn(null);
|
|
|
|
GradleUtils().getExecutable(flutterProject);
|
|
|
|
verifyNever(operatingSystemUtils.makeExecutable(gradlew));
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => memoryFileSystem,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
OperatingSystemUtils: () => operatingSystemUtils,
|
|
GradleUtils: () => gradleUtils,
|
|
});
|
|
});
|
|
}
|
|
|
|
class MockAndroidProject extends Mock implements AndroidProject {}
|
|
class MockDirectory extends Mock implements Directory {}
|
|
class MockFile extends Mock implements File {}
|
|
class MockFileStat extends Mock implements FileStat {}
|
|
class MockFlutterProject extends Mock implements FlutterProject {}
|
|
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
|
|
class MockGradleUtils extends Mock implements GradleUtils {}
|