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 {
'assets/flutter_assets/isolate_snapshot_data',
'assets/flutter_assets/kernel_blob.bin',
'assets/flutter_assets/vm_snapshot_data',
'lib/armeabi-v7a/libflutter.so',
// Debug mode intentionally includes `x86` and `x86_64`.
'lib/x86/libflutter.so',
'lib/x86_64/libflutter.so',
......@@ -79,7 +78,6 @@ Future<void> main() async {
'assets/flutter_assets/isolate_snapshot_data',
'assets/flutter_assets/kernel_blob.bin',
'assets/flutter_assets/vm_snapshot_data',
'lib/armeabi-v7a/libflutter.so',
// Debug mode intentionally includes `x86` and `x86_64`.
'lib/x86/libflutter.so',
'lib/x86_64/libflutter.so',
......
......@@ -57,6 +57,6 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.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:design:26.1.0'
implementation 'com.android.support:appcompat-v7:28.0.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.
# 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)
......
// 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 {
LogsCommand(),
MakeHostAppEditableCommand(),
PackagesCommand(),
PrecacheCommand(),
PrecacheCommand(verboseHelp: verboseHelp),
RunCommand(verboseHelp: verboseHelp),
ScreenshotCommand(),
ShellCompletionCommand(),
......
......@@ -149,7 +149,7 @@ Future<void> checkGradleDependencies() async {
<String>[gradlew, 'dependencies'],
throwOnError: true,
workingDirectory: flutterProject.android.hostAppGradleRoot.path,
environment: _gradleEnv,
environment: gradleEnv,
);
androidSdk.reinitialize();
progress.stop();
......@@ -239,13 +239,13 @@ Future<GradleProject> _readGradleProject({bool isLibrary = false}) async {
<String>[gradlew, if (isLibrary) 'properties' else 'app:properties'],
throwOnError: true,
workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv,
environment: gradleEnv,
);
final RunResult tasksRunResult = await processUtils.run(
<String>[gradlew, if (isLibrary) 'tasks' else 'app:tasks', '--all', '--console=auto'],
throwOnError: true,
workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv,
environment: gradleEnv,
);
project = GradleProject.fromAppProperties(propertiesRunResult.stdout, tasksRunResult.stdout);
} catch (exception) {
......@@ -324,7 +324,7 @@ Future<String> _initializeGradle(FlutterProject project) async {
await processUtils.run(
<String>[gradle, '-v'],
throwOnError: true,
environment: _gradleEnv,
environment: gradleEnv,
);
} on ProcessException catch (e) {
final String error = e.toString();
......@@ -640,7 +640,7 @@ Future<void> buildGradleAar({
command,
workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
environment: _gradleEnv,
environment: gradleEnv,
mapFunction: (String line) {
// Always print the full line in verbose mode.
if (logger.isVerbose) {
......@@ -678,7 +678,7 @@ Future<void> _buildGradleProjectV1(FlutterProject project) async {
<String>[fs.file(gradlew).absolute.path, 'build'],
workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
environment: _gradleEnv,
environment: gradleEnv,
);
status.stop();
flutterUsage.sendTiming('build', 'gradle-v1', Duration(milliseconds: sw.elapsedMilliseconds));
......@@ -809,7 +809,7 @@ Future<void> _buildGradleProjectV2(
command,
workingDirectory: flutterProject.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
environment: _gradleEnv,
environment: gradleEnv,
// TODO(mklim): if AndroidX warnings are no longer required, this
// mapFunction and all its associated variabled can be replaced with just
// `filter: ndkMessagefilter`.
......@@ -961,7 +961,8 @@ File findBundleFile(GradleProject project, BuildInfo buildInfo) {
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);
if (javaPath != null) {
// Use java bundled with Android Studio.
......
This diff is collapsed.
......@@ -9,7 +9,7 @@ import '../base/os.dart';
import '../build_info.dart';
import '../project.dart';
import '../reporting/reporting.dart';
import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult;
import '../runner/flutter_command.dart' show FlutterCommandResult;
import 'build.dart';
class BuildAarCommand extends BuildSubCommand {
......@@ -52,12 +52,6 @@ class BuildAarCommand extends BuildSubCommand {
return usage;
}
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.android,
};
@override
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'
......
......@@ -10,7 +10,7 @@ import '../build_info.dart';
import '../globals.dart';
import '../project.dart';
import '../reporting/reporting.dart';
import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult;
import '../runner/flutter_command.dart' show FlutterCommandResult;
import 'build.dart';
class BuildApkCommand extends BuildSubCommand {
......@@ -69,12 +69,6 @@ class BuildApkCommand extends BuildSubCommand {
return usage;
}
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.android,
};
@override
Future<FlutterCommandResult> runCommand() async {
final BuildInfo buildInfo = getBuildInfo();
......
......@@ -37,7 +37,7 @@ class DoctorCommand extends FlutterCommand {
// This is required because we use gen_snapshot to check if the host
// machine can execute the provided artifacts. See `_genSnapshotRuns`
// in `doctor.dart`.
DevelopmentArtifact.android,
DevelopmentArtifact.androidGenSnapshot,
};
}
......
......@@ -10,13 +10,23 @@ import '../runner/flutter_command.dart';
import '../version.dart';
class PrecacheCommand extends FlutterCommand {
PrecacheCommand() {
PrecacheCommand({bool verboseHelp = false}) {
argParser.addFlag('all-platforms', abbr: 'a', negatable: false,
help: 'Precache artifacts for all host platforms.');
argParser.addFlag('force', abbr: 'f', negatable: false,
help: 'Force downloading of artifacts.');
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,
help: 'Precache artifacts for iOS development.');
argParser.addFlag('web', negatable: true, defaultsTo: false,
......@@ -58,6 +68,10 @@ class PrecacheCommand extends FlutterCommand {
if (argResults[artifact.name]) {
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'];
if (forceUpdate || !cache.isUpToDate()) {
......
......@@ -10,6 +10,7 @@ import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../cache.dart';
import '../dart/pub.dart';
......@@ -130,6 +131,7 @@ class UpgradeCommandRunner {
],
workingDirectory: Cache.flutterRoot,
allowReentrantFlutter: true,
environment: platform.environment,
);
if (code != 0) {
throwToolExit(null, exitCode: code);
......@@ -248,6 +250,7 @@ class UpgradeCommandRunner {
],
workingDirectory: Cache.flutterRoot,
allowReentrantFlutter: true,
environment: platform.environment,
);
if (code != 0) {
throwToolExit(null, exitCode: code);
......
......@@ -676,7 +676,7 @@ DevelopmentArtifact _artifactFromTargetPlatform(TargetPlatform targetPlatform) {
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
return DevelopmentArtifact.android;
return DevelopmentArtifact.androidGenSnapshot;
case TargetPlatform.web_javascript:
return DevelopmentArtifact.web;
case TargetPlatform.ios:
......
......@@ -47,9 +47,9 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
{{/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: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.espresso:espresso-core:3.0.2'
{{/androidX}}
......
......@@ -8,8 +8,11 @@ import 'package:file_testing/file_testing.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.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/io.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart' show InternetAddress, SocketException;
......@@ -136,18 +139,30 @@ void main() {
when(artifact1.isUpToDate()).thenReturn(true);
when(artifact2.isUpToDate()).thenReturn(false);
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
await cache.updateAll(<DevelopmentArtifact>{});
verifyNever(artifact1.update(<DevelopmentArtifact>{}));
verify(artifact2.update(<DevelopmentArtifact>{}));
await cache.updateAll(<DevelopmentArtifact>{
null,
});
verifyNever(artifact1.update());
verify(artifact2.update());
});
testUsingContext('getter dyLdLibEntry concatenates the output of each artifact\'s dyLdLibEntry getter', () async {
final CachedArtifact artifact1 = MockCachedArtifact();
final CachedArtifact artifact2 = MockCachedArtifact();
final CachedArtifact artifact3 = MockCachedArtifact();
when(artifact1.dyLdLibPath).thenReturn('/path/to/alpha:/path/to/beta');
when(artifact2.dyLdLibPath).thenReturn('/path/to/gamma:/path/to/delta:/path/to/epsilon');
when(artifact3.dyLdLibPath).thenReturn(''); // Empty output
final IosUsbArtifacts artifact1 = MockIosUsbArtifacts();
final IosUsbArtifacts artifact2 = MockIosUsbArtifacts();
final IosUsbArtifacts artifact3 = MockIosUsbArtifacts();
when(artifact1.environment)
.thenReturn(<String, String>{
'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]);
expect(cache.dyLdLibEntry.key, 'DYLD_LIBRARY_PATH');
expect(
cache.dyLdLibEntry.value,
......@@ -163,18 +178,20 @@ void main() {
when(artifact2.isUpToDate()).thenReturn(false);
final MockInternetAddress address = MockInternetAddress();
when(address.host).thenReturn('storage.googleapis.com');
when(artifact1.update(<DevelopmentArtifact>{})).thenThrow(SocketException(
when(artifact1.update()).thenThrow(SocketException(
'Connection reset by peer',
address: address,
));
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
try {
await cache.updateAll(<DevelopmentArtifact>{});
await cache.updateAll(<DevelopmentArtifact>{
null,
});
fail('Mock thrown exception expected');
} catch (e) {
verify(artifact1.update(<DevelopmentArtifact>{}));
verify(artifact1.update());
// Don't continue when retrieval fails.
verifyNever(artifact2.update(<DevelopmentArtifact>{}));
verifyNever(artifact2.update());
expect(
testLogger.errorText,
contains('https://flutter.dev/community/china'),
......@@ -226,6 +243,7 @@ void main() {
binaryDirs: <List<String>>[
<String>['bin_dir', 'unused_url_path'],
],
requiredArtifacts: DevelopmentArtifact.universal,
);
await artifact.updateInner();
final Directory dir = memoryFileSystem.systemTempDirectory
......@@ -244,25 +262,53 @@ void main() {
});
});
testUsingContext('throws tool exit on fs exception', () async {
final FakeCachedArtifact fakeCachedArtifact = FakeCachedArtifact(
cache: MockCache(),
requiredArtifacts: <DevelopmentArtifact>{
DevelopmentArtifact.android,
}
);
final Directory mockDirectory = MockDirectory();
when(fakeCachedArtifact.cache.getArtifactDirectory(any))
.thenReturn(mockDirectory);
when(mockDirectory.existsSync()).thenReturn(false);
when(mockDirectory.createSync(recursive: true))
.thenThrow(const FileSystemException());
expect(() => fakeCachedArtifact.update(<DevelopmentArtifact>{
DevelopmentArtifact.android,
}), throwsA(isInstanceOf<ToolExit>()));
group('AndroidMavenArtifacts', () {
MemoryFileSystem memoryFileSystem;
MockProcessManager processManager;
MockCache mockCache;
setUp(() {
memoryFileSystem = MemoryFileSystem();
processManager = MockProcessManager();
mockCache = MockCache();
});
test('development artifact', () async {
final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts();
expect(mavenArtifacts.developmentArtifact, DevelopmentArtifact.androidMaven);
});
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>{
FileSystem: () => MemoryFileSystem(),
Cache: ()=> mockCache,
FileSystem: () => memoryFileSystem,
ProcessManager: () => processManager,
});
});
}
......@@ -270,7 +316,7 @@ class FakeCachedArtifact extends EngineCachedArtifact {
FakeCachedArtifact({
String stampName = 'STAMP',
@required Cache cache,
Set<DevelopmentArtifact> requiredArtifacts = const <DevelopmentArtifact>{},
DevelopmentArtifact requiredArtifacts,
this.binaryDirs = const <List<String>>[],
this.licenseDirs = const <String>[],
this.packageDirs = const <String>[],
......@@ -290,12 +336,14 @@ class FakeCachedArtifact extends EngineCachedArtifact {
List<String> getPackageDirs() => packageDirs;
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockFileSystem extends Mock implements FileSystem {}
class MockFile extends Mock implements File {}
class MockDirectory extends Mock implements Directory {}
class MockRandomAccessFile extends Mock implements RandomAccessFile {}
class MockCachedArtifact extends Mock implements CachedArtifact {}
class MockIosUsbArtifacts extends Mock implements IosUsbArtifacts {}
class MockInternetAddress extends Mock implements InternetAddress {}
class MockCache extends Mock implements Cache {}
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
......@@ -27,12 +27,24 @@ void main() {
final PrecacheCommand command = PrecacheCommand();
applyMocksToCommand(command);
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>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
DevelopmentArtifact.android,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
DevelopmentArtifact.web,
DevelopmentArtifact.macOS,
DevelopmentArtifact.linux,
......@@ -44,6 +56,54 @@ void main() {
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();
when(flutterVersion.isMaster).thenReturn(false);
......@@ -53,18 +113,31 @@ void main() {
final PrecacheCommand command = PrecacheCommand();
applyMocksToCommand(command);
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>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
DevelopmentArtifact.android,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
}));
}, overrides: <Type, Generator>{
Cache: () => cache,
FlutterVersion: () => flutterVersion,
});
testUsingContext('Downloads artifacts when --force is provided', () async {
when(cache.isUpToDate()).thenReturn(true);
// Release lock between test cases.
......@@ -75,7 +148,9 @@ void main() {
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
DevelopmentArtifact.android,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
}));
}, overrides: <Type, Generator>{
Cache: () => cache,
......
......@@ -138,7 +138,7 @@ void main() {
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.android,
DevelopmentArtifact.androidGenSnapshot,
}));
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
......@@ -162,7 +162,7 @@ void main() {
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
DevelopmentArtifact.android,
DevelopmentArtifact.androidGenSnapshot,
}));
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
......
......@@ -5,12 +5,14 @@
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.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/cache.dart';
import 'package:flutter_tools/src/commands/upgrade.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';
import '../../src/common.dart';
......@@ -22,6 +24,7 @@ void main() {
FakeUpgradeCommandRunner fakeCommandRunner;
UpgradeCommandRunner realCommandRunner;
MockProcessManager processManager;
FakePlatform fakePlatform;
final MockFlutterVersion flutterVersion = MockFlutterVersion();
const GitTagVersion gitTagVersion = GitTagVersion(1, 2, 3, 4, 5, 'asd');
when(flutterVersion.channel).thenReturn('dev');
......@@ -43,9 +46,13 @@ void main() {
return Future<Process>.value(createMockProcess());
});
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(
false,
false,
......@@ -53,6 +60,8 @@ void main() {
flutterVersion,
);
expect(result, throwsA(isInstanceOf<ToolExit>()));
}, overrides: <Type, Generator>{
Platform: () => fakePlatform,
});
testUsingContext('does not throw on unknown tag, official branch, force', () async {
......@@ -65,9 +74,10 @@ void main() {
expect(await result, null);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
test('throws tool exit with uncommitted changes', () async {
testUsingContext('throws tool exit with uncommitted changes', () async {
fakeCommandRunner.willHaveUncomittedChanges = true;
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
false,
......@@ -76,6 +86,8 @@ void main() {
flutterVersion,
);
expect(result, throwsA(isA<ToolExit>()));
}, overrides: <Type, Generator>{
Platform: () => fakePlatform,
});
testUsingContext('does not throw tool exit with uncommitted changes and force', () async {
......@@ -90,6 +102,7 @@ void main() {
expect(await result, null);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('Doesn\'t throw on known tag, dev branch, no force', () async {
......@@ -102,6 +115,7 @@ void main() {
expect(await result, null);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('verifyUpstreamConfigured', () async {
......@@ -116,6 +130,57 @@ void main() {
await realCommandRunner.verifyUpstreamConfigured();
}, overrides: <Type, Generator>{
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