Unverified Commit 8a1bf5b8 authored by Emmanuel Garcia's avatar Emmanuel Garcia Committed by GitHub

Reland #39157 (#39798)

parent df4bf453
...@@ -52,7 +52,6 @@ Future<void> main() async { ...@@ -52,7 +52,6 @@ Future<void> main() async {
'assets/flutter_assets/isolate_snapshot_data', 'assets/flutter_assets/isolate_snapshot_data',
'assets/flutter_assets/kernel_blob.bin', 'assets/flutter_assets/kernel_blob.bin',
'assets/flutter_assets/vm_snapshot_data', 'assets/flutter_assets/vm_snapshot_data',
'lib/armeabi-v7a/libflutter.so',
// Debug mode intentionally includes `x86` and `x86_64`. // Debug mode intentionally includes `x86` and `x86_64`.
'lib/x86/libflutter.so', 'lib/x86/libflutter.so',
'lib/x86_64/libflutter.so', 'lib/x86_64/libflutter.so',
...@@ -79,7 +78,6 @@ Future<void> main() async { ...@@ -79,7 +78,6 @@ Future<void> main() async {
'assets/flutter_assets/isolate_snapshot_data', 'assets/flutter_assets/isolate_snapshot_data',
'assets/flutter_assets/kernel_blob.bin', 'assets/flutter_assets/kernel_blob.bin',
'assets/flutter_assets/vm_snapshot_data', 'assets/flutter_assets/vm_snapshot_data',
'lib/armeabi-v7a/libflutter.so',
// Debug mode intentionally includes `x86` and `x86_64`. // Debug mode intentionally includes `x86` and `x86_64`.
'lib/x86/libflutter.so', 'lib/x86/libflutter.so',
'lib/x86_64/libflutter.so', 'lib/x86_64/libflutter.so',
......
...@@ -57,6 +57,6 @@ dependencies { ...@@ -57,6 +57,6 @@ dependencies {
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:26.1.0' implementation 'com.android.support:design:28.0.0'
} }
# Prevents `Fragment and FragmentActivity not found`.
# TODO(blasten): Remove once we bring the Maven dependencies.
-dontwarn io.flutter.embedding.**
# Build the ephemeral app in a module project. # Build the ephemeral app in a module project.
# Prevents: Warning: library class <plugin-package> depends on program class io.flutter.plugin.** # Prevents: Warning: library class <plugin-package> depends on program class io.flutter.plugin.**
# This is due to plugins (libraries) depending on the embedding (the program jar) # This is due to plugins (libraries) depending on the embedding (the program jar)
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
// This script is used to warm the Gradle cache by downloading the Flutter dependencies
// used during the build. This script is invoked when `flutter precache` is run.
//
// Command:
// gradle -b <flutter-sdk>packages/flutter_tools/gradle/resolve_dependencies.gradle
// resolveDependencies
//
// This way, Gradle can run with the `--offline` flag later on to eliminate any
// network request during the build process.
//
// This includes:
// 1. The embedding
// 2. libflutter.so
import java.nio.file.Paths
repositories {
google()
jcenter()
maven {
url "http://download.flutter.io"
}
}
File flutterRoot = projectDir.parentFile.parentFile.parentFile
assert flutterRoot.isDirectory()
String engineVersion = Paths.get(flutterRoot.absolutePath, "bin", "internal", "engine.version")
.toFile().text.trim()
configurations {
flutterRelease.extendsFrom releaseImplementation
flutterDebug.extendsFrom debugImplementation
flutterProfile.extendsFrom debugImplementation
}
dependencies {
flutterRelease "io.flutter:flutter_embedding_release:1.0.0-$engineVersion"
flutterRelease "io.flutter:armeabi_v7a_release:1.0.0-$engineVersion"
flutterRelease "io.flutter:arm64_v8a_release:1.0.0-$engineVersion"
flutterProfile "io.flutter:flutter_embedding_profile:1.0.0-$engineVersion"
flutterProfile "io.flutter:armeabi_v7a_profile:1.0.0-$engineVersion"
flutterProfile "io.flutter:arm64_v8a_profile:1.0.0-$engineVersion"
flutterDebug "io.flutter:flutter_embedding_debug:1.0.0-$engineVersion"
flutterDebug "io.flutter:armeabi_v7a_debug:1.0.0-$engineVersion"
flutterDebug "io.flutter:arm64_v8a_debug:1.0.0-$engineVersion"
flutterDebug "io.flutter:x86_debug:1.0.0-$engineVersion"
flutterDebug "io.flutter:x86_64_debug:1.0.0-$engineVersion"
}
task resolveDependencies {
configurations.each { configuration ->
if (configuration.name.startsWith("flutter")) {
configuration.resolve()
}
}
}
...@@ -84,7 +84,7 @@ Future<void> main(List<String> args) async { ...@@ -84,7 +84,7 @@ Future<void> main(List<String> args) async {
LogsCommand(), LogsCommand(),
MakeHostAppEditableCommand(), MakeHostAppEditableCommand(),
PackagesCommand(), PackagesCommand(),
PrecacheCommand(), PrecacheCommand(verboseHelp: verboseHelp),
RunCommand(verboseHelp: verboseHelp), RunCommand(verboseHelp: verboseHelp),
ScreenshotCommand(), ScreenshotCommand(),
ShellCompletionCommand(), ShellCompletionCommand(),
......
...@@ -149,7 +149,7 @@ Future<void> checkGradleDependencies() async { ...@@ -149,7 +149,7 @@ Future<void> checkGradleDependencies() async {
<String>[gradlew, 'dependencies'], <String>[gradlew, 'dependencies'],
throwOnError: true, throwOnError: true,
workingDirectory: flutterProject.android.hostAppGradleRoot.path, workingDirectory: flutterProject.android.hostAppGradleRoot.path,
environment: _gradleEnv, environment: gradleEnv,
); );
androidSdk.reinitialize(); androidSdk.reinitialize();
progress.stop(); progress.stop();
...@@ -239,13 +239,13 @@ Future<GradleProject> _readGradleProject({bool isLibrary = false}) async { ...@@ -239,13 +239,13 @@ Future<GradleProject> _readGradleProject({bool isLibrary = false}) async {
<String>[gradlew, if (isLibrary) 'properties' else 'app:properties'], <String>[gradlew, if (isLibrary) 'properties' else 'app:properties'],
throwOnError: true, throwOnError: true,
workingDirectory: hostAppGradleRoot.path, workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv, environment: gradleEnv,
); );
final RunResult tasksRunResult = await processUtils.run( final RunResult tasksRunResult = await processUtils.run(
<String>[gradlew, if (isLibrary) 'tasks' else 'app:tasks', '--all', '--console=auto'], <String>[gradlew, if (isLibrary) 'tasks' else 'app:tasks', '--all', '--console=auto'],
throwOnError: true, throwOnError: true,
workingDirectory: hostAppGradleRoot.path, workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv, environment: gradleEnv,
); );
project = GradleProject.fromAppProperties(propertiesRunResult.stdout, tasksRunResult.stdout); project = GradleProject.fromAppProperties(propertiesRunResult.stdout, tasksRunResult.stdout);
} catch (exception) { } catch (exception) {
...@@ -324,7 +324,7 @@ Future<String> _initializeGradle(FlutterProject project) async { ...@@ -324,7 +324,7 @@ Future<String> _initializeGradle(FlutterProject project) async {
await processUtils.run( await processUtils.run(
<String>[gradle, '-v'], <String>[gradle, '-v'],
throwOnError: true, throwOnError: true,
environment: _gradleEnv, environment: gradleEnv,
); );
} on ProcessException catch (e) { } on ProcessException catch (e) {
final String error = e.toString(); final String error = e.toString();
...@@ -640,7 +640,7 @@ Future<void> buildGradleAar({ ...@@ -640,7 +640,7 @@ Future<void> buildGradleAar({
command, command,
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: _gradleEnv, environment: gradleEnv,
mapFunction: (String line) { mapFunction: (String line) {
// Always print the full line in verbose mode. // Always print the full line in verbose mode.
if (logger.isVerbose) { if (logger.isVerbose) {
...@@ -678,7 +678,7 @@ Future<void> _buildGradleProjectV1(FlutterProject project) async { ...@@ -678,7 +678,7 @@ Future<void> _buildGradleProjectV1(FlutterProject project) async {
<String>[fs.file(gradlew).absolute.path, 'build'], <String>[fs.file(gradlew).absolute.path, 'build'],
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: _gradleEnv, environment: gradleEnv,
); );
status.stop(); status.stop();
flutterUsage.sendTiming('build', 'gradle-v1', Duration(milliseconds: sw.elapsedMilliseconds)); flutterUsage.sendTiming('build', 'gradle-v1', Duration(milliseconds: sw.elapsedMilliseconds));
...@@ -809,7 +809,7 @@ Future<void> _buildGradleProjectV2( ...@@ -809,7 +809,7 @@ Future<void> _buildGradleProjectV2(
command, command,
workingDirectory: flutterProject.android.hostAppGradleRoot.path, workingDirectory: flutterProject.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: _gradleEnv, environment: gradleEnv,
// TODO(mklim): if AndroidX warnings are no longer required, this // TODO(mklim): if AndroidX warnings are no longer required, this
// mapFunction and all its associated variabled can be replaced with just // mapFunction and all its associated variabled can be replaced with just
// `filter: ndkMessagefilter`. // `filter: ndkMessagefilter`.
...@@ -961,7 +961,8 @@ File findBundleFile(GradleProject project, BuildInfo buildInfo) { ...@@ -961,7 +961,8 @@ File findBundleFile(GradleProject project, BuildInfo buildInfo) {
return null; return null;
} }
Map<String, String> get _gradleEnv { /// The environment variables needed to run Gradle.
Map<String, String> get gradleEnv {
final Map<String, String> env = Map<String, String>.from(platform.environment); final Map<String, String> env = Map<String, String>.from(platform.environment);
if (javaPath != null) { if (javaPath != null) {
// Use java bundled with Android Studio. // Use java bundled with Android Studio.
......
This diff is collapsed.
...@@ -9,7 +9,7 @@ import '../base/os.dart'; ...@@ -9,7 +9,7 @@ import '../base/os.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult; import '../runner/flutter_command.dart' show FlutterCommandResult;
import 'build.dart'; import 'build.dart';
class BuildAarCommand extends BuildSubCommand { class BuildAarCommand extends BuildSubCommand {
...@@ -52,12 +52,6 @@ class BuildAarCommand extends BuildSubCommand { ...@@ -52,12 +52,6 @@ class BuildAarCommand extends BuildSubCommand {
return usage; return usage;
} }
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.android,
};
@override @override
final String description = 'Build a repository containing an AAR and a POM file.\n\n' final String description = 'Build a repository containing an AAR and a POM file.\n\n'
'The POM file is used to include the dependencies that the AAR was compiled against.\n\n' 'The POM file is used to include the dependencies that the AAR was compiled against.\n\n'
......
...@@ -10,7 +10,7 @@ import '../build_info.dart'; ...@@ -10,7 +10,7 @@ import '../build_info.dart';
import '../globals.dart'; import '../globals.dart';
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult; import '../runner/flutter_command.dart' show FlutterCommandResult;
import 'build.dart'; import 'build.dart';
class BuildApkCommand extends BuildSubCommand { class BuildApkCommand extends BuildSubCommand {
...@@ -69,12 +69,6 @@ class BuildApkCommand extends BuildSubCommand { ...@@ -69,12 +69,6 @@ class BuildApkCommand extends BuildSubCommand {
return usage; return usage;
} }
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.android,
};
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
final BuildInfo buildInfo = getBuildInfo(); final BuildInfo buildInfo = getBuildInfo();
......
...@@ -37,7 +37,7 @@ class DoctorCommand extends FlutterCommand { ...@@ -37,7 +37,7 @@ class DoctorCommand extends FlutterCommand {
// This is required because we use gen_snapshot to check if the host // This is required because we use gen_snapshot to check if the host
// machine can execute the provided artifacts. See `_genSnapshotRuns` // machine can execute the provided artifacts. See `_genSnapshotRuns`
// in `doctor.dart`. // in `doctor.dart`.
DevelopmentArtifact.android, DevelopmentArtifact.androidGenSnapshot,
}; };
} }
......
...@@ -10,13 +10,23 @@ import '../runner/flutter_command.dart'; ...@@ -10,13 +10,23 @@ import '../runner/flutter_command.dart';
import '../version.dart'; import '../version.dart';
class PrecacheCommand extends FlutterCommand { class PrecacheCommand extends FlutterCommand {
PrecacheCommand() { PrecacheCommand({bool verboseHelp = false}) {
argParser.addFlag('all-platforms', abbr: 'a', negatable: false, argParser.addFlag('all-platforms', abbr: 'a', negatable: false,
help: 'Precache artifacts for all host platforms.'); help: 'Precache artifacts for all host platforms.');
argParser.addFlag('force', abbr: 'f', negatable: false, argParser.addFlag('force', abbr: 'f', negatable: false,
help: 'Force downloading of artifacts.'); help: 'Force downloading of artifacts.');
argParser.addFlag('android', negatable: true, defaultsTo: true, argParser.addFlag('android', negatable: true, defaultsTo: true,
help: 'Precache artifacts for Android development.'); help: 'Precache artifacts for Android development.',
hide: verboseHelp);
argParser.addFlag('android_gen_snapshot', negatable: true, defaultsTo: true,
help: 'Precache gen_snapshot for Android development.',
hide: !verboseHelp);
argParser.addFlag('android_maven', negatable: true, defaultsTo: true,
help: 'Precache Gradle dependencies for Android development.',
hide: !verboseHelp);
argParser.addFlag('android_internal_build', negatable: true, defaultsTo: false,
help: 'Precache dependencies for internal Android development.',
hide: !verboseHelp);
argParser.addFlag('ios', negatable: true, defaultsTo: true, argParser.addFlag('ios', negatable: true, defaultsTo: true,
help: 'Precache artifacts for iOS development.'); help: 'Precache artifacts for iOS development.');
argParser.addFlag('web', negatable: true, defaultsTo: false, argParser.addFlag('web', negatable: true, defaultsTo: false,
...@@ -58,6 +68,10 @@ class PrecacheCommand extends FlutterCommand { ...@@ -58,6 +68,10 @@ class PrecacheCommand extends FlutterCommand {
if (argResults[artifact.name]) { if (argResults[artifact.name]) {
requiredArtifacts.add(artifact); requiredArtifacts.add(artifact);
} }
// The `android` flag expands to android_gen_snapshot, android_maven, android_internal_build.
if (artifact.name.startsWith('android_') && argResults['android']) {
requiredArtifacts.add(artifact);
}
} }
final bool forceUpdate = argResults['force']; final bool forceUpdate = argResults['force'];
if (forceUpdate || !cache.isUpToDate()) { if (forceUpdate || !cache.isUpToDate()) {
......
...@@ -10,6 +10,7 @@ import '../base/common.dart'; ...@@ -10,6 +10,7 @@ import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../cache.dart'; import '../cache.dart';
import '../dart/pub.dart'; import '../dart/pub.dart';
...@@ -130,6 +131,7 @@ class UpgradeCommandRunner { ...@@ -130,6 +131,7 @@ class UpgradeCommandRunner {
], ],
workingDirectory: Cache.flutterRoot, workingDirectory: Cache.flutterRoot,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: platform.environment,
); );
if (code != 0) { if (code != 0) {
throwToolExit(null, exitCode: code); throwToolExit(null, exitCode: code);
...@@ -248,6 +250,7 @@ class UpgradeCommandRunner { ...@@ -248,6 +250,7 @@ class UpgradeCommandRunner {
], ],
workingDirectory: Cache.flutterRoot, workingDirectory: Cache.flutterRoot,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: platform.environment,
); );
if (code != 0) { if (code != 0) {
throwToolExit(null, exitCode: code); throwToolExit(null, exitCode: code);
......
...@@ -676,7 +676,7 @@ DevelopmentArtifact _artifactFromTargetPlatform(TargetPlatform targetPlatform) { ...@@ -676,7 +676,7 @@ DevelopmentArtifact _artifactFromTargetPlatform(TargetPlatform targetPlatform) {
case TargetPlatform.android_arm64: case TargetPlatform.android_arm64:
case TargetPlatform.android_x64: case TargetPlatform.android_x64:
case TargetPlatform.android_x86: case TargetPlatform.android_x86:
return DevelopmentArtifact.android; return DevelopmentArtifact.androidGenSnapshot;
case TargetPlatform.web_javascript: case TargetPlatform.web_javascript:
return DevelopmentArtifact.web; return DevelopmentArtifact.web;
case TargetPlatform.ios: case TargetPlatform.ios:
......
...@@ -47,9 +47,9 @@ dependencies { ...@@ -47,9 +47,9 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
{{/androidX}} {{/androidX}}
{{^androidX}} {{^androidX}}
implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.2' implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.android.support:design:27.1.1' implementation 'com.android.support:design:28.0.0'
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
{{/androidX}} {{/androidX}}
......
...@@ -8,8 +8,11 @@ import 'package:file_testing/file_testing.dart'; ...@@ -8,8 +8,11 @@ import 'package:file_testing/file_testing.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:process/process.dart';
import 'package:flutter_tools/src/android/gradle.dart';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart' show InternetAddress, SocketException; import 'package:flutter_tools/src/base/io.dart' show InternetAddress, SocketException;
...@@ -136,18 +139,30 @@ void main() { ...@@ -136,18 +139,30 @@ void main() {
when(artifact1.isUpToDate()).thenReturn(true); when(artifact1.isUpToDate()).thenReturn(true);
when(artifact2.isUpToDate()).thenReturn(false); when(artifact2.isUpToDate()).thenReturn(false);
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]); final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
await cache.updateAll(<DevelopmentArtifact>{}); await cache.updateAll(<DevelopmentArtifact>{
verifyNever(artifact1.update(<DevelopmentArtifact>{})); null,
verify(artifact2.update(<DevelopmentArtifact>{})); });
verifyNever(artifact1.update());
verify(artifact2.update());
}); });
testUsingContext('getter dyLdLibEntry concatenates the output of each artifact\'s dyLdLibEntry getter', () async { testUsingContext('getter dyLdLibEntry concatenates the output of each artifact\'s dyLdLibEntry getter', () async {
final CachedArtifact artifact1 = MockCachedArtifact(); final IosUsbArtifacts artifact1 = MockIosUsbArtifacts();
final CachedArtifact artifact2 = MockCachedArtifact(); final IosUsbArtifacts artifact2 = MockIosUsbArtifacts();
final CachedArtifact artifact3 = MockCachedArtifact(); final IosUsbArtifacts artifact3 = MockIosUsbArtifacts();
when(artifact1.dyLdLibPath).thenReturn('/path/to/alpha:/path/to/beta'); when(artifact1.environment)
when(artifact2.dyLdLibPath).thenReturn('/path/to/gamma:/path/to/delta:/path/to/epsilon'); .thenReturn(<String, String>{
when(artifact3.dyLdLibPath).thenReturn(''); // Empty output 'DYLD_LIBRARY_PATH': '/path/to/alpha:/path/to/beta',
});
when(artifact2.environment)
.thenReturn(<String, String>{
'DYLD_LIBRARY_PATH': '/path/to/gamma:/path/to/delta:/path/to/epsilon',
});
when(artifact3.environment)
.thenReturn(<String, String>{
'DYLD_LIBRARY_PATH': '',
});
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2, artifact3]); final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2, artifact3]);
expect(cache.dyLdLibEntry.key, 'DYLD_LIBRARY_PATH'); expect(cache.dyLdLibEntry.key, 'DYLD_LIBRARY_PATH');
expect( expect(
cache.dyLdLibEntry.value, cache.dyLdLibEntry.value,
...@@ -163,18 +178,20 @@ void main() { ...@@ -163,18 +178,20 @@ void main() {
when(artifact2.isUpToDate()).thenReturn(false); when(artifact2.isUpToDate()).thenReturn(false);
final MockInternetAddress address = MockInternetAddress(); final MockInternetAddress address = MockInternetAddress();
when(address.host).thenReturn('storage.googleapis.com'); when(address.host).thenReturn('storage.googleapis.com');
when(artifact1.update(<DevelopmentArtifact>{})).thenThrow(SocketException( when(artifact1.update()).thenThrow(SocketException(
'Connection reset by peer', 'Connection reset by peer',
address: address, address: address,
)); ));
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]); final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
try { try {
await cache.updateAll(<DevelopmentArtifact>{}); await cache.updateAll(<DevelopmentArtifact>{
null,
});
fail('Mock thrown exception expected'); fail('Mock thrown exception expected');
} catch (e) { } catch (e) {
verify(artifact1.update(<DevelopmentArtifact>{})); verify(artifact1.update());
// Don't continue when retrieval fails. // Don't continue when retrieval fails.
verifyNever(artifact2.update(<DevelopmentArtifact>{})); verifyNever(artifact2.update());
expect( expect(
testLogger.errorText, testLogger.errorText,
contains('https://flutter.dev/community/china'), contains('https://flutter.dev/community/china'),
...@@ -226,6 +243,7 @@ void main() { ...@@ -226,6 +243,7 @@ void main() {
binaryDirs: <List<String>>[ binaryDirs: <List<String>>[
<String>['bin_dir', 'unused_url_path'], <String>['bin_dir', 'unused_url_path'],
], ],
requiredArtifacts: DevelopmentArtifact.universal,
); );
await artifact.updateInner(); await artifact.updateInner();
final Directory dir = memoryFileSystem.systemTempDirectory final Directory dir = memoryFileSystem.systemTempDirectory
...@@ -244,25 +262,53 @@ void main() { ...@@ -244,25 +262,53 @@ void main() {
}); });
}); });
testUsingContext('throws tool exit on fs exception', () async { group('AndroidMavenArtifacts', () {
final FakeCachedArtifact fakeCachedArtifact = FakeCachedArtifact( MemoryFileSystem memoryFileSystem;
cache: MockCache(), MockProcessManager processManager;
requiredArtifacts: <DevelopmentArtifact>{ MockCache mockCache;
DevelopmentArtifact.android,
} setUp(() {
); memoryFileSystem = MemoryFileSystem();
final Directory mockDirectory = MockDirectory(); processManager = MockProcessManager();
when(fakeCachedArtifact.cache.getArtifactDirectory(any)) mockCache = MockCache();
.thenReturn(mockDirectory); });
when(mockDirectory.existsSync()).thenReturn(false);
when(mockDirectory.createSync(recursive: true)) test('development artifact', () async {
.thenThrow(const FileSystemException()); final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts();
expect(mavenArtifacts.developmentArtifact, DevelopmentArtifact.androidMaven);
expect(() => fakeCachedArtifact.update(<DevelopmentArtifact>{ });
DevelopmentArtifact.android,
}), throwsA(isInstanceOf<ToolExit>())); testUsingContext('update', () async {
final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts();
expect(mavenArtifacts.isUpToDate(), isFalse);
final Directory gradleWrapperDir = fs.systemTempDirectory.createTempSync('gradle_wrapper.');
when(mockCache.getArtifactDirectory('gradle_wrapper')).thenReturn(gradleWrapperDir);
fs.directory(gradleWrapperDir.childDirectory('gradle').childDirectory('wrapper'))
.createSync(recursive: true);
fs.file(fs.path.join(gradleWrapperDir.path, 'gradlew')).writeAsStringSync('irrelevant');
fs.file(fs.path.join(gradleWrapperDir.path, 'gradlew.bat')).writeAsStringSync('irrelevant');
when(processManager.run(any, environment: captureAnyNamed('environment')))
.thenAnswer((Invocation invocation) {
final List<String> args = invocation.positionalArguments[0];
expect(args.length, 6);
expect(args[1], '-b');
expect(args[2].endsWith('resolve_dependencies.gradle'), isTrue);
expect(args[5], 'resolveDependencies');
expect(invocation.namedArguments[#environment], gradleEnv);
return Future<ProcessResult>.value(ProcessResult(0, 0, '', ''));
});
await mavenArtifacts.update();
expect(mavenArtifacts.isUpToDate(), isFalse);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(), Cache: ()=> mockCache,
FileSystem: () => memoryFileSystem,
ProcessManager: () => processManager,
});
}); });
} }
...@@ -270,7 +316,7 @@ class FakeCachedArtifact extends EngineCachedArtifact { ...@@ -270,7 +316,7 @@ class FakeCachedArtifact extends EngineCachedArtifact {
FakeCachedArtifact({ FakeCachedArtifact({
String stampName = 'STAMP', String stampName = 'STAMP',
@required Cache cache, @required Cache cache,
Set<DevelopmentArtifact> requiredArtifacts = const <DevelopmentArtifact>{}, DevelopmentArtifact requiredArtifacts,
this.binaryDirs = const <List<String>>[], this.binaryDirs = const <List<String>>[],
this.licenseDirs = const <String>[], this.licenseDirs = const <String>[],
this.packageDirs = const <String>[], this.packageDirs = const <String>[],
...@@ -290,12 +336,14 @@ class FakeCachedArtifact extends EngineCachedArtifact { ...@@ -290,12 +336,14 @@ class FakeCachedArtifact extends EngineCachedArtifact {
List<String> getPackageDirs() => packageDirs; List<String> getPackageDirs() => packageDirs;
} }
class MockProcessManager extends Mock implements ProcessManager {}
class MockFileSystem extends Mock implements FileSystem {} class MockFileSystem extends Mock implements FileSystem {}
class MockFile extends Mock implements File {} class MockFile extends Mock implements File {}
class MockDirectory extends Mock implements Directory {} class MockDirectory extends Mock implements Directory {}
class MockRandomAccessFile extends Mock implements RandomAccessFile {} class MockRandomAccessFile extends Mock implements RandomAccessFile {}
class MockCachedArtifact extends Mock implements CachedArtifact {} class MockCachedArtifact extends Mock implements CachedArtifact {}
class MockIosUsbArtifacts extends Mock implements IosUsbArtifacts {}
class MockInternetAddress extends Mock implements InternetAddress {} class MockInternetAddress extends Mock implements InternetAddress {}
class MockCache extends Mock implements Cache {} class MockCache extends Mock implements Cache {}
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {} class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
...@@ -27,12 +27,24 @@ void main() { ...@@ -27,12 +27,24 @@ void main() {
final PrecacheCommand command = PrecacheCommand(); final PrecacheCommand command = PrecacheCommand();
applyMocksToCommand(command); applyMocksToCommand(command);
await createTestCommandRunner(command).run( await createTestCommandRunner(command).run(
const <String>['precache', '--ios', '--android', '--web', '--macos', '--linux', '--windows', '--fuchsia', '--flutter_runner'] const <String>[
'precache',
'--ios',
'--android',
'--web',
'--macos',
'--linux',
'--windows',
'--fuchsia',
'--flutter_runner',
]
); );
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{ expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal, DevelopmentArtifact.universal,
DevelopmentArtifact.iOS, DevelopmentArtifact.iOS,
DevelopmentArtifact.android, DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
DevelopmentArtifact.web, DevelopmentArtifact.web,
DevelopmentArtifact.macOS, DevelopmentArtifact.macOS,
DevelopmentArtifact.linux, DevelopmentArtifact.linux,
...@@ -44,6 +56,54 @@ void main() { ...@@ -44,6 +56,54 @@ void main() {
Cache: () => cache, Cache: () => cache,
}); });
testUsingContext('Expands android artifacts when the android flag is used', () async {
// Release lock between test cases.
Cache.releaseLockEarly();
final PrecacheCommand command = PrecacheCommand();
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
'--no-ios',
'--android',
]
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
}));
}, overrides: <Type, Generator>{
Cache: () => cache,
});
testUsingContext('Adds artifact flags to requested android artifacts', () async {
// Release lock between test cases.
Cache.releaseLockEarly();
final PrecacheCommand command = PrecacheCommand();
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
'--no-ios',
'--android_gen_snapshot',
'--android_maven',
'--android_internal_build',
]
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
}));
}, overrides: <Type, Generator>{
Cache: () => cache,
});
final MockFlutterVersion flutterVersion = MockFlutterVersion(); final MockFlutterVersion flutterVersion = MockFlutterVersion();
when(flutterVersion.isMaster).thenReturn(false); when(flutterVersion.isMaster).thenReturn(false);
...@@ -53,18 +113,31 @@ void main() { ...@@ -53,18 +113,31 @@ void main() {
final PrecacheCommand command = PrecacheCommand(); final PrecacheCommand command = PrecacheCommand();
applyMocksToCommand(command); applyMocksToCommand(command);
await createTestCommandRunner(command).run( await createTestCommandRunner(command).run(
const <String>['precache', '--ios', '--android', '--web', '--macos', '--linux', '--windows', '--fuchsia', '--flutter_runner'] const <String>[
'precache',
'--ios',
'--android_gen_snapshot',
'--android_maven',
'--android_internal_build',
'--web',
'--macos',
'--linux',
'--windows',
'--fuchsia',
'--flutter_runner',
]
); );
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{ expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal, DevelopmentArtifact.universal,
DevelopmentArtifact.iOS, DevelopmentArtifact.iOS,
DevelopmentArtifact.android, DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
})); }));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Cache: () => cache, Cache: () => cache,
FlutterVersion: () => flutterVersion, FlutterVersion: () => flutterVersion,
}); });
testUsingContext('Downloads artifacts when --force is provided', () async { testUsingContext('Downloads artifacts when --force is provided', () async {
when(cache.isUpToDate()).thenReturn(true); when(cache.isUpToDate()).thenReturn(true);
// Release lock between test cases. // Release lock between test cases.
...@@ -75,7 +148,9 @@ void main() { ...@@ -75,7 +148,9 @@ void main() {
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{ expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal, DevelopmentArtifact.universal,
DevelopmentArtifact.iOS, DevelopmentArtifact.iOS,
DevelopmentArtifact.android, DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
})); }));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Cache: () => cache, Cache: () => cache,
......
...@@ -138,7 +138,7 @@ void main() { ...@@ -138,7 +138,7 @@ void main() {
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{ expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal, DevelopmentArtifact.universal,
DevelopmentArtifact.android, DevelopmentArtifact.androidGenSnapshot,
})); }));
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
...@@ -162,7 +162,7 @@ void main() { ...@@ -162,7 +162,7 @@ void main() {
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{ expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal, DevelopmentArtifact.universal,
DevelopmentArtifact.iOS, DevelopmentArtifact.iOS,
DevelopmentArtifact.android, DevelopmentArtifact.androidGenSnapshot,
})); }));
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
......
...@@ -5,12 +5,14 @@ ...@@ -5,12 +5,14 @@
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/upgrade.dart'; import 'package:flutter_tools/src/commands/upgrade.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart'; import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/version.dart'; import 'package:flutter_tools/src/version.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../../src/common.dart'; import '../../src/common.dart';
...@@ -22,6 +24,7 @@ void main() { ...@@ -22,6 +24,7 @@ void main() {
FakeUpgradeCommandRunner fakeCommandRunner; FakeUpgradeCommandRunner fakeCommandRunner;
UpgradeCommandRunner realCommandRunner; UpgradeCommandRunner realCommandRunner;
MockProcessManager processManager; MockProcessManager processManager;
FakePlatform fakePlatform;
final MockFlutterVersion flutterVersion = MockFlutterVersion(); final MockFlutterVersion flutterVersion = MockFlutterVersion();
const GitTagVersion gitTagVersion = GitTagVersion(1, 2, 3, 4, 5, 'asd'); const GitTagVersion gitTagVersion = GitTagVersion(1, 2, 3, 4, 5, 'asd');
when(flutterVersion.channel).thenReturn('dev'); when(flutterVersion.channel).thenReturn('dev');
...@@ -43,9 +46,13 @@ void main() { ...@@ -43,9 +46,13 @@ void main() {
return Future<Process>.value(createMockProcess()); return Future<Process>.value(createMockProcess());
}); });
fakeCommandRunner.willHaveUncomittedChanges = false; fakeCommandRunner.willHaveUncomittedChanges = false;
fakePlatform = FakePlatform()..environment = <String, String>{
'ENV1': 'irrelevant',
'ENV2': 'irrelevant',
};
}); });
test('throws on unknown tag, official branch, noforce', () async { testUsingContext('throws on unknown tag, official branch, noforce', () async {
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand( final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
false, false,
false, false,
...@@ -53,6 +60,8 @@ void main() { ...@@ -53,6 +60,8 @@ void main() {
flutterVersion, flutterVersion,
); );
expect(result, throwsA(isInstanceOf<ToolExit>())); expect(result, throwsA(isInstanceOf<ToolExit>()));
}, overrides: <Type, Generator>{
Platform: () => fakePlatform,
}); });
testUsingContext('does not throw on unknown tag, official branch, force', () async { testUsingContext('does not throw on unknown tag, official branch, force', () async {
...@@ -65,9 +74,10 @@ void main() { ...@@ -65,9 +74,10 @@ void main() {
expect(await result, null); expect(await result, null);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => processManager, ProcessManager: () => processManager,
Platform: () => fakePlatform,
}); });
test('throws tool exit with uncommitted changes', () async { testUsingContext('throws tool exit with uncommitted changes', () async {
fakeCommandRunner.willHaveUncomittedChanges = true; fakeCommandRunner.willHaveUncomittedChanges = true;
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand( final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
false, false,
...@@ -76,6 +86,8 @@ void main() { ...@@ -76,6 +86,8 @@ void main() {
flutterVersion, flutterVersion,
); );
expect(result, throwsA(isA<ToolExit>())); expect(result, throwsA(isA<ToolExit>()));
}, overrides: <Type, Generator>{
Platform: () => fakePlatform,
}); });
testUsingContext('does not throw tool exit with uncommitted changes and force', () async { testUsingContext('does not throw tool exit with uncommitted changes and force', () async {
...@@ -90,6 +102,7 @@ void main() { ...@@ -90,6 +102,7 @@ void main() {
expect(await result, null); expect(await result, null);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => processManager, ProcessManager: () => processManager,
Platform: () => fakePlatform,
}); });
testUsingContext('Doesn\'t throw on known tag, dev branch, no force', () async { testUsingContext('Doesn\'t throw on known tag, dev branch, no force', () async {
...@@ -102,6 +115,7 @@ void main() { ...@@ -102,6 +115,7 @@ void main() {
expect(await result, null); expect(await result, null);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => processManager, ProcessManager: () => processManager,
Platform: () => fakePlatform,
}); });
testUsingContext('verifyUpstreamConfigured', () async { testUsingContext('verifyUpstreamConfigured', () async {
...@@ -116,6 +130,57 @@ void main() { ...@@ -116,6 +130,57 @@ void main() {
await realCommandRunner.verifyUpstreamConfigured(); await realCommandRunner.verifyUpstreamConfigured();
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => processManager, ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('flutterUpgradeContinue passes env variables to child process', () async {
await realCommandRunner.flutterUpgradeContinue();
final VerificationResult result = verify(processManager.start(
<String>[
fs.path.join('bin', 'flutter'),
'upgrade',
'--continue',
'--no-version-check',
],
environment: captureAnyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
));
expect(result.captured.first, fakePlatform.environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('precacheArtifacts passes env variables to child process', () async {
final List<String> precacheCommand = <String>[
fs.path.join('bin', 'flutter'),
'--no-color',
'--no-version-check',
'precache',
];
when(processManager.start(
precacheCommand,
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) async {
return Future<Process>.value(createMockProcess());
});
await realCommandRunner.precacheArtifacts();
final VerificationResult result = verify(processManager.start(
precacheCommand,
environment: captureAnyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
));
expect(result.captured.first, fakePlatform.environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment