Unverified Commit e6e14b0d authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

Have android validator suggest ANDROID_SDK_ROOT instead of deprecated ANDROID_HOME (#49846)

parent db901ce5
...@@ -3,15 +3,17 @@ ...@@ -3,15 +3,17 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../base/version.dart'; import '../base/version.dart';
import '../convert.dart'; import '../convert.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
import 'android_studio.dart' as android_studio; import 'android_studio.dart';
AndroidSdk get androidSdk => context.get<AndroidSdk>(); AndroidSdk get androidSdk => context.get<AndroidSdk>();
...@@ -549,20 +551,25 @@ class AndroidSdk { ...@@ -549,20 +551,25 @@ class AndroidSdk {
} }
/// First try Java bundled with Android Studio, then sniff JAVA_HOME, then fallback to PATH. /// First try Java bundled with Android Studio, then sniff JAVA_HOME, then fallback to PATH.
static String findJavaBinary() { static String findJavaBinary({
if (android_studio.javaPath != null) { @required AndroidStudio androidStudio,
return globals.fs.path.join(android_studio.javaPath, 'bin', 'java'); @required FileSystem fileSystem,
@required OperatingSystemUtils operatingSystemUtils,
@required Platform platform,
}) {
if (androidStudio?.javaPath != null) {
return fileSystem.path.join(androidStudio.javaPath, 'bin', 'java');
} }
final String javaHomeEnv = globals.platform.environment[_javaHomeEnvironmentVariable]; final String javaHomeEnv = platform.environment[_javaHomeEnvironmentVariable];
if (javaHomeEnv != null) { if (javaHomeEnv != null) {
// Trust JAVA_HOME. // Trust JAVA_HOME.
return globals.fs.path.join(javaHomeEnv, 'bin', 'java'); return fileSystem.path.join(javaHomeEnv, 'bin', 'java');
} }
// MacOS specific logic to avoid popping up a dialog window. // MacOS specific logic to avoid popping up a dialog window.
// See: http://stackoverflow.com/questions/14292698/how-do-i-check-if-the-java-jdk-is-installed-on-mac. // See: http://stackoverflow.com/questions/14292698/how-do-i-check-if-the-java-jdk-is-installed-on-mac.
if (globals.platform.isMacOS) { if (platform.isMacOS) {
try { try {
final String javaHomeOutput = processUtils.runSync( final String javaHomeOutput = processUtils.runSync(
<String>['/usr/libexec/java_home'], <String>['/usr/libexec/java_home'],
...@@ -573,14 +580,14 @@ class AndroidSdk { ...@@ -573,14 +580,14 @@ class AndroidSdk {
final List<String> javaHomeOutputSplit = javaHomeOutput.split('\n'); final List<String> javaHomeOutputSplit = javaHomeOutput.split('\n');
if ((javaHomeOutputSplit != null) && (javaHomeOutputSplit.isNotEmpty)) { if ((javaHomeOutputSplit != null) && (javaHomeOutputSplit.isNotEmpty)) {
final String javaHome = javaHomeOutputSplit[0].trim(); final String javaHome = javaHomeOutputSplit[0].trim();
return globals.fs.path.join(javaHome, 'bin', 'java'); return fileSystem.path.join(javaHome, 'bin', 'java');
} }
} }
} catch (_) { /* ignore */ } } catch (_) { /* ignore */ }
} }
// Fallback to PATH based lookup. // Fallback to PATH based lookup.
return globals.os.which(_javaExecutable)?.path; return operatingSystemUtils.which(_javaExecutable)?.path;
} }
Map<String, String> _sdkManagerEnv; Map<String, String> _sdkManagerEnv;
...@@ -590,7 +597,12 @@ class AndroidSdk { ...@@ -590,7 +597,12 @@ class AndroidSdk {
if (_sdkManagerEnv == null) { if (_sdkManagerEnv == null) {
// If we can locate Java, then add it to the path used to run the Android SDK manager. // If we can locate Java, then add it to the path used to run the Android SDK manager.
_sdkManagerEnv = <String, String>{}; _sdkManagerEnv = <String, String>{};
final String javaBinary = findJavaBinary(); final String javaBinary = findJavaBinary(
androidStudio: globals.androidStudio,
fileSystem: globals.fs,
operatingSystemUtils: globals.os,
platform: globals.platform,
);
if (javaBinary != null) { if (javaBinary != null) {
_sdkManagerEnv['PATH'] = globals.fs.path.dirname(javaBinary) + _sdkManagerEnv['PATH'] = globals.fs.path.dirname(javaBinary) +
globals.os.pathVarSeparator + globals.os.pathVarSeparator +
......
...@@ -4,9 +4,16 @@ ...@@ -4,9 +4,16 @@
import 'dart:async'; import 'dart:async';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../base/user_messages.dart'; import '../base/user_messages.dart';
import '../base/utils.dart'; import '../base/utils.dart';
...@@ -15,6 +22,7 @@ import '../convert.dart'; ...@@ -15,6 +22,7 @@ import '../convert.dart';
import '../doctor.dart'; import '../doctor.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
import 'android_sdk.dart'; import 'android_sdk.dart';
import 'android_studio.dart';
const int kAndroidSdkMinVersion = 28; const int kAndroidSdkMinVersion = 28;
final Version kAndroidJavaMinVersion = Version(1, 8, 0); final Version kAndroidJavaMinVersion = Version(1, 8, 0);
...@@ -50,7 +58,37 @@ class AndroidWorkflow implements Workflow { ...@@ -50,7 +58,37 @@ class AndroidWorkflow implements Workflow {
} }
class AndroidValidator extends DoctorValidator { class AndroidValidator extends DoctorValidator {
AndroidValidator() : super('Android toolchain - develop for Android devices',); AndroidValidator({
@required AndroidSdk androidSdk,
@required AndroidStudio androidStudio,
@required FileSystem fileSystem,
@required Logger logger,
@required Platform platform,
@required ProcessManager processManager,
@required UserMessages userMessages,
}) : _androidSdk = androidSdk,
_androidStudio = androidStudio,
_fileSystem = fileSystem,
_logger = logger,
_operatingSystemUtils = OperatingSystemUtils(
fileSystem: fileSystem,
logger: logger,
platform: platform,
processManager: processManager,
),
_platform = platform,
_processManager = processManager,
_userMessages = userMessages,
super('Android toolchain - develop for Android devices');
final AndroidSdk _androidSdk;
final AndroidStudio _androidStudio;
final FileSystem _fileSystem;
final Logger _logger;
final OperatingSystemUtils _operatingSystemUtils;
final Platform _platform;
final ProcessManager _processManager;
final UserMessages _userMessages;
@override @override
String get slowWarning => '${_task ?? 'This'} is taking a long time...'; String get slowWarning => '${_task ?? 'This'} is taking a long time...';
...@@ -72,32 +110,32 @@ class AndroidValidator extends DoctorValidator { ...@@ -72,32 +110,32 @@ class AndroidValidator extends DoctorValidator {
Future<bool> _checkJavaVersion(String javaBinary, List<ValidationMessage> messages) async { Future<bool> _checkJavaVersion(String javaBinary, List<ValidationMessage> messages) async {
_task = 'Checking Java status'; _task = 'Checking Java status';
try { try {
if (!globals.processManager.canRun(javaBinary)) { if (!_processManager.canRun(javaBinary)) {
messages.add(ValidationMessage.error(userMessages.androidCantRunJavaBinary(javaBinary))); messages.add(ValidationMessage.error(_userMessages.androidCantRunJavaBinary(javaBinary)));
return false; return false;
} }
String javaVersionText; String javaVersionText;
try { try {
globals.printTrace('java -version'); _logger.printTrace('java -version');
final ProcessResult result = await globals.processManager.run(<String>[javaBinary, '-version']); final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']);
if (result.exitCode == 0) { if (result.exitCode == 0) {
final List<String> versionLines = (result.stderr as String).split('\n'); final List<String> versionLines = (result.stderr as String).split('\n');
javaVersionText = versionLines.length >= 2 ? versionLines[1] : versionLines[0]; javaVersionText = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
} }
} catch (error) { } catch (error) {
globals.printTrace(error.toString()); _logger.printTrace(error.toString());
} }
if (javaVersionText == null || javaVersionText.isEmpty) { if (javaVersionText == null || javaVersionText.isEmpty) {
// Could not determine the java version. // Could not determine the java version.
messages.add(ValidationMessage.error(userMessages.androidUnknownJavaVersion)); messages.add(ValidationMessage.error(_userMessages.androidUnknownJavaVersion));
return false; return false;
} }
final Version javaVersion = Version.parse(_extractJavaVersion(javaVersionText)); final Version javaVersion = Version.parse(_extractJavaVersion(javaVersionText));
if (javaVersion < kAndroidJavaMinVersion) { if (javaVersion < kAndroidJavaMinVersion) {
messages.add(ValidationMessage.error(userMessages.androidJavaMinimumVersion(javaVersionText))); messages.add(ValidationMessage.error(_userMessages.androidJavaMinimumVersion(javaVersionText)));
return false; return false;
} }
messages.add(ValidationMessage(userMessages.androidJavaVersion(javaVersionText))); messages.add(ValidationMessage(_userMessages.androidJavaVersion(javaVersionText)));
return true; return true;
} finally { } finally {
_task = null; _task = null;
...@@ -108,72 +146,79 @@ class AndroidValidator extends DoctorValidator { ...@@ -108,72 +146,79 @@ class AndroidValidator extends DoctorValidator {
Future<ValidationResult> validate() async { Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[]; final List<ValidationMessage> messages = <ValidationMessage>[];
if (androidSdk == null) { if (_androidSdk == null) {
// No Android SDK found. // No Android SDK found.
if (globals.platform.environment.containsKey(kAndroidHome)) { if (_platform.environment.containsKey(kAndroidHome)) {
final String androidHomeDir = globals.platform.environment[kAndroidHome]; final String androidHomeDir = _platform.environment[kAndroidHome];
messages.add(ValidationMessage.error(userMessages.androidBadSdkDir(kAndroidHome, androidHomeDir))); messages.add(ValidationMessage.error(_userMessages.androidBadSdkDir(kAndroidHome, androidHomeDir)));
} else { } else {
messages.add(ValidationMessage.error(userMessages.androidMissingSdkInstructions(kAndroidHome))); // Instruct user to set [kAndroidSdkRoot] and not deprecated [kAndroidHome]
// See https://github.com/flutter/flutter/issues/39301
messages.add(ValidationMessage.error(_userMessages.androidMissingSdkInstructions(kAndroidSdkRoot)));
} }
return ValidationResult(ValidationType.missing, messages); return ValidationResult(ValidationType.missing, messages);
} }
if (androidSdk.licensesAvailable && !androidSdk.platformToolsAvailable) { if (_androidSdk.licensesAvailable && !_androidSdk.platformToolsAvailable) {
messages.add(ValidationMessage.hint(userMessages.androidSdkLicenseOnly(kAndroidHome))); messages.add(ValidationMessage.hint(_userMessages.androidSdkLicenseOnly(kAndroidHome)));
return ValidationResult(ValidationType.partial, messages); return ValidationResult(ValidationType.partial, messages);
} }
messages.add(ValidationMessage(userMessages.androidSdkLocation(androidSdk.directory))); messages.add(ValidationMessage(_userMessages.androidSdkLocation(_androidSdk.directory)));
messages.add(ValidationMessage(androidSdk.ndk == null messages.add(ValidationMessage(_androidSdk.ndk == null
? userMessages.androidMissingNdk ? _userMessages.androidMissingNdk
: userMessages.androidNdkLocation(androidSdk.ndk.directory))); : _userMessages.androidNdkLocation(_androidSdk.ndk.directory)));
String sdkVersionText; String sdkVersionText;
if (androidSdk.latestVersion != null) { if (_androidSdk.latestVersion != null) {
if (androidSdk.latestVersion.sdkLevel < 28 || androidSdk.latestVersion.buildToolsVersion < kAndroidSdkBuildToolsMinVersion) { if (_androidSdk.latestVersion.sdkLevel < 28 || _androidSdk.latestVersion.buildToolsVersion < kAndroidSdkBuildToolsMinVersion) {
messages.add(ValidationMessage.error( messages.add(ValidationMessage.error(
userMessages.androidSdkBuildToolsOutdated(androidSdk.sdkManagerPath, kAndroidSdkMinVersion, kAndroidSdkBuildToolsMinVersion.toString())), _userMessages.androidSdkBuildToolsOutdated(_androidSdk.sdkManagerPath, kAndroidSdkMinVersion, kAndroidSdkBuildToolsMinVersion.toString())),
); );
return ValidationResult(ValidationType.missing, messages); return ValidationResult(ValidationType.missing, messages);
} }
sdkVersionText = userMessages.androidStatusInfo(androidSdk.latestVersion.buildToolsVersionName); sdkVersionText = _userMessages.androidStatusInfo(_androidSdk.latestVersion.buildToolsVersionName);
messages.add(ValidationMessage(userMessages.androidSdkPlatformToolsVersion( messages.add(ValidationMessage(_userMessages.androidSdkPlatformToolsVersion(
androidSdk.latestVersion.platformName, _androidSdk.latestVersion.platformName,
androidSdk.latestVersion.buildToolsVersionName))); _androidSdk.latestVersion.buildToolsVersionName)));
} else { } else {
messages.add(ValidationMessage.error(userMessages.androidMissingSdkInstructions(kAndroidHome))); messages.add(ValidationMessage.error(_userMessages.androidMissingSdkInstructions(kAndroidHome)));
} }
if (globals.platform.environment.containsKey(kAndroidHome)) { if (_platform.environment.containsKey(kAndroidHome)) {
final String androidHomeDir = globals.platform.environment[kAndroidHome]; final String androidHomeDir = _platform.environment[kAndroidHome];
messages.add(ValidationMessage('$kAndroidHome = $androidHomeDir')); messages.add(ValidationMessage('$kAndroidHome = $androidHomeDir'));
} }
if (globals.platform.environment.containsKey(kAndroidSdkRoot)) { if (_platform.environment.containsKey(kAndroidSdkRoot)) {
final String androidSdkRoot = globals.platform.environment[kAndroidSdkRoot]; final String androidSdkRoot = _platform.environment[kAndroidSdkRoot];
messages.add(ValidationMessage('$kAndroidSdkRoot = $androidSdkRoot')); messages.add(ValidationMessage('$kAndroidSdkRoot = $androidSdkRoot'));
} }
final List<String> validationResult = androidSdk.validateSdkWellFormed(); final List<String> validationResult = _androidSdk.validateSdkWellFormed();
if (validationResult.isNotEmpty) { if (validationResult.isNotEmpty) {
// Android SDK is not functional. // Android SDK is not functional.
messages.addAll(validationResult.map<ValidationMessage>((String message) { messages.addAll(validationResult.map<ValidationMessage>((String message) {
return ValidationMessage.error(message); return ValidationMessage.error(message);
})); }));
messages.add(ValidationMessage(userMessages.androidSdkInstallHelp)); messages.add(ValidationMessage(_userMessages.androidSdkInstallHelp));
return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText); return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
} }
// Now check for the JDK. // Now check for the JDK.
final String javaBinary = AndroidSdk.findJavaBinary(); final String javaBinary = AndroidSdk.findJavaBinary(
androidStudio: _androidStudio,
fileSystem: _fileSystem,
operatingSystemUtils: _operatingSystemUtils,
platform: _platform,
);
if (javaBinary == null) { if (javaBinary == null) {
messages.add(ValidationMessage.error(userMessages.androidMissingJdk)); messages.add(ValidationMessage.error(_userMessages.androidMissingJdk));
return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText); return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
} }
messages.add(ValidationMessage(userMessages.androidJdkLocation(javaBinary))); messages.add(ValidationMessage(_userMessages.androidJdkLocation(javaBinary)));
// Check JDK version. // Check JDK version.
if (! await _checkJavaVersion(javaBinary, messages)) { if (! await _checkJavaVersion(javaBinary, messages)) {
...@@ -223,7 +268,12 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -223,7 +268,12 @@ class AndroidLicenseValidator extends DoctorValidator {
} }
Future<bool> _checkJavaVersionNoOutput() async { Future<bool> _checkJavaVersionNoOutput() async {
final String javaBinary = AndroidSdk.findJavaBinary(); final String javaBinary = AndroidSdk.findJavaBinary(
androidStudio: globals.androidStudio,
fileSystem: globals.fs,
operatingSystemUtils: globals.os,
platform: globals.platform,
);
if (javaBinary == null) { if (javaBinary == null) {
return false; return false;
} }
......
...@@ -101,7 +101,7 @@ class Cache { ...@@ -101,7 +101,7 @@ class Cache {
}) : _rootOverride = rootOverride, }) : _rootOverride = rootOverride,
_logger = logger ?? globals.logger, _logger = logger ?? globals.logger,
_fileSystem = fileSystem ?? globals.fs, _fileSystem = fileSystem ?? globals.fs,
_platform = platform ?? globals.platform , _platform = platform ?? globals.platform,
_osUtils = osUtils ?? globals.os { _osUtils = osUtils ?? globals.os {
// TODO(zra): Move to initializer list once logger and platform parameters // TODO(zra): Move to initializer list once logger and platform parameters
// are required. // are required.
......
...@@ -69,7 +69,15 @@ Future<T> runInContext<T>( ...@@ -69,7 +69,15 @@ Future<T> runInContext<T>(
AndroidLicenseValidator: () => AndroidLicenseValidator(), AndroidLicenseValidator: () => AndroidLicenseValidator(),
AndroidSdk: AndroidSdk.locateAndroidSdk, AndroidSdk: AndroidSdk.locateAndroidSdk,
AndroidStudio: AndroidStudio.latestValid, AndroidStudio: AndroidStudio.latestValid,
AndroidValidator: () => AndroidValidator(), AndroidValidator: () => AndroidValidator(
androidStudio: globals.androidStudio,
androidSdk: globals.androidSdk,
fileSystem: globals.fs,
logger: globals.logger,
platform: globals.platform,
processManager: globals.processManager,
userMessages: globals.userMessages,
),
AndroidWorkflow: () => AndroidWorkflow(), AndroidWorkflow: () => AndroidWorkflow(),
ApplicationPackageFactory: () => ApplicationPackageFactory(), ApplicationPackageFactory: () => ApplicationPackageFactory(),
Artifacts: () => CachedArtifacts( Artifacts: () => CachedArtifacts(
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import 'android/android_sdk.dart';
import 'android/android_studio.dart';
import 'artifacts.dart'; import 'artifacts.dart';
import 'base/config.dart'; import 'base/config.dart';
import 'base/context.dart'; import 'base/context.dart';
...@@ -14,6 +16,7 @@ import 'base/io.dart'; ...@@ -14,6 +16,7 @@ import 'base/io.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'base/os.dart'; import 'base/os.dart';
import 'base/terminal.dart'; import 'base/terminal.dart';
import 'base/user_messages.dart';
import 'cache.dart'; import 'cache.dart';
import 'ios/mac.dart'; import 'ios/mac.dart';
import 'macos/xcode.dart'; import 'macos/xcode.dart';
...@@ -53,9 +56,12 @@ const Platform _kLocalPlatform = LocalPlatform(); ...@@ -53,9 +56,12 @@ const Platform _kLocalPlatform = LocalPlatform();
Platform get platform => context.get<Platform>() ?? _kLocalPlatform; Platform get platform => context.get<Platform>() ?? _kLocalPlatform;
Xcode get xcode => context.get<Xcode>(); AndroidStudio get androidStudio => context.get<AndroidStudio>();
AndroidSdk get androidSdk => context.get<AndroidSdk>();
FlutterVersion get flutterVersion => context.get<FlutterVersion>(); FlutterVersion get flutterVersion => context.get<FlutterVersion>();
IMobileDevice get iMobileDevice => context.get<IMobileDevice>(); IMobileDevice get iMobileDevice => context.get<IMobileDevice>();
UserMessages get userMessages => context.get<UserMessages>();
Xcode get xcode => context.get<Xcode>();
XCDevice get xcdevice => context.get<XCDevice>(); XCDevice get xcdevice => context.get<XCDevice>();
......
...@@ -7,12 +7,14 @@ import 'dart:async'; ...@@ -7,12 +7,14 @@ import 'dart:async';
import 'package:file/memory.dart'; import 'package:file/memory.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/os.dart';
import 'package:flutter_tools/src/android/android_sdk.dart'; import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/android/android_workflow.dart'; import 'package:flutter_tools/src/android/android_workflow.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart' show AnsiTerminal, OutputPreferences;
import 'package:flutter_tools/src/base/user_messages.dart'; import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/base/version.dart'; import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/doctor.dart'; import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
...@@ -23,19 +25,30 @@ import '../../src/context.dart'; ...@@ -23,19 +25,30 @@ import '../../src/context.dart';
import '../../src/mocks.dart' show MockAndroidSdk, MockProcess, MockProcessManager, MockStdio; import '../../src/mocks.dart' show MockAndroidSdk, MockProcess, MockProcessManager, MockStdio;
class MockAndroidSdkVersion extends Mock implements AndroidSdkVersion {} class MockAndroidSdkVersion extends Mock implements AndroidSdkVersion {}
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
void main() { void main() {
AndroidSdk sdk; AndroidSdk sdk;
Logger logger;
MemoryFileSystem fs; MemoryFileSystem fs;
MockProcessManager processManager; MockProcessManager processManager;
MockStdio stdio; MockStdio stdio;
UserMessages userMessages;
setUp(() { setUp(() {
sdk = MockAndroidSdk(); sdk = MockAndroidSdk();
fs = MemoryFileSystem(); fs = MemoryFileSystem();
fs.directory('/home/me').createSync(recursive: true); fs.directory('/home/me').createSync(recursive: true);
logger = BufferLogger(
terminal: AnsiTerminal(
stdio: null,
platform: const LocalPlatform(),
),
outputPreferences: OutputPreferences.test(),
);
processManager = MockProcessManager(); processManager = MockProcessManager();
stdio = MockStdio(); stdio = MockStdio();
userMessages = UserMessages();
}); });
MockProcess Function(List<String>) processMetaFactory(List<String> stdout) { MockProcess Function(List<String>) processMetaFactory(List<String> stdout) {
...@@ -208,24 +221,26 @@ void main() { ...@@ -208,24 +221,26 @@ void main() {
Stdio: () => stdio, Stdio: () => stdio,
})); }));
testUsingContext('detects license-only SDK installation', () async { testWithoutContext('detects license-only SDK installation', () async {
when(sdk.licensesAvailable).thenReturn(true); when(sdk.licensesAvailable).thenReturn(true);
when(sdk.platformToolsAvailable).thenReturn(false); when(sdk.platformToolsAvailable).thenReturn(false);
final ValidationResult validationResult = await AndroidValidator().validate(); final ValidationResult validationResult = await AndroidValidator(
androidStudio: null,
androidSdk: sdk,
fileSystem: fs,
logger: logger,
processManager: processManager,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
userMessages: userMessages,
).validate();
expect(validationResult.type, ValidationType.partial); expect(validationResult.type, ValidationType.partial);
expect( expect(
validationResult.messages.last.message, validationResult.messages.last.message,
userMessages.androidSdkLicenseOnly(kAndroidHome), userMessages.androidSdkLicenseOnly(kAndroidHome),
); );
}, overrides: Map<Type, Generator>.unmodifiable(<Type, Generator>{ });
AndroidSdk: () => sdk,
FileSystem: () => fs,
ProcessManager: () => processManager,
Platform: () => FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
Stdio: () => stdio,
}));
testUsingContext('detects minium required SDK and buildtools', () async { testWithoutContext('detects minimum required SDK and buildtools', () async {
final AndroidSdkVersion mockSdkVersion = MockAndroidSdkVersion(); final AndroidSdkVersion mockSdkVersion = MockAndroidSdkVersion();
when(sdk.licensesAvailable).thenReturn(true); when(sdk.licensesAvailable).thenReturn(true);
when(sdk.platformToolsAvailable).thenReturn(true); when(sdk.platformToolsAvailable).thenReturn(true);
...@@ -236,13 +251,24 @@ void main() { ...@@ -236,13 +251,24 @@ void main() {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager');
when(sdk.latestVersion).thenReturn(mockSdkVersion); when(sdk.latestVersion).thenReturn(mockSdkVersion);
when(sdk.validateSdkWellFormed()).thenReturn(<String>[]); when(sdk.validateSdkWellFormed()).thenReturn(<String>[]);
when(processManager.runSync(<String>['which', 'java'])).thenReturn(ProcessResult(123, 1, '', ''));
final String errorMessage = userMessages.androidSdkBuildToolsOutdated( final String errorMessage = userMessages.androidSdkBuildToolsOutdated(
sdk.sdkManagerPath, sdk.sdkManagerPath,
kAndroidSdkMinVersion, kAndroidSdkMinVersion,
kAndroidSdkBuildToolsMinVersion.toString(), kAndroidSdkBuildToolsMinVersion.toString(),
); );
ValidationResult validationResult = await AndroidValidator().validate(); final AndroidValidator androidValidator = AndroidValidator(
androidStudio: null,
androidSdk: sdk,
fileSystem: fs,
logger: logger,
processManager: processManager,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
userMessages: userMessages,
);
ValidationResult validationResult = await androidValidator.validate();
expect(validationResult.type, ValidationType.missing); expect(validationResult.type, ValidationType.missing);
expect( expect(
validationResult.messages.last.message, validationResult.messages.last.message,
...@@ -253,7 +279,7 @@ void main() { ...@@ -253,7 +279,7 @@ void main() {
when(mockSdkVersion.sdkLevel).thenReturn(28); when(mockSdkVersion.sdkLevel).thenReturn(28);
when(mockSdkVersion.buildToolsVersion).thenReturn(Version(28, 0, 2)); when(mockSdkVersion.buildToolsVersion).thenReturn(Version(28, 0, 2));
validationResult = await AndroidValidator().validate(); validationResult = await androidValidator.validate();
expect(validationResult.type, ValidationType.missing); expect(validationResult.type, ValidationType.missing);
expect( expect(
validationResult.messages.last.message, validationResult.messages.last.message,
...@@ -265,21 +291,15 @@ void main() { ...@@ -265,21 +291,15 @@ void main() {
when(mockSdkVersion.sdkLevel).thenReturn(kAndroidSdkMinVersion); when(mockSdkVersion.sdkLevel).thenReturn(kAndroidSdkMinVersion);
when(mockSdkVersion.buildToolsVersion).thenReturn(kAndroidSdkBuildToolsMinVersion); when(mockSdkVersion.buildToolsVersion).thenReturn(kAndroidSdkBuildToolsMinVersion);
validationResult = await AndroidValidator().validate(); validationResult = await androidValidator.validate();
expect(validationResult.type, ValidationType.partial); // No Java binary expect(validationResult.type, ValidationType.partial); // No Java binary
expect( expect(
validationResult.messages.any((ValidationMessage message) => message.message == errorMessage), validationResult.messages.any((ValidationMessage message) => message.message == errorMessage),
isFalse, isFalse,
); );
}, overrides: Map<Type, Generator>.unmodifiable(<Type, Generator>{ });
AndroidSdk: () => sdk,
FileSystem: () => fs,
ProcessManager: () => processManager,
Platform: () => FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
Stdio: () => stdio,
}));
testUsingContext('detects minimum required java version', () async { testWithoutContext('detects minimum required java version', () async {
final AndroidSdkVersion mockSdkVersion = MockAndroidSdkVersion(); final AndroidSdkVersion mockSdkVersion = MockAndroidSdkVersion();
// Mock a pass through scenario to reach _checkJavaVersion() // Mock a pass through scenario to reach _checkJavaVersion()
...@@ -293,22 +313,41 @@ void main() { ...@@ -293,22 +313,41 @@ void main() {
//Test with older version of JDK //Test with older version of JDK
const String javaVersionText = 'openjdk version "1.7.0_212"'; const String javaVersionText = 'openjdk version "1.7.0_212"';
when(globals.processManager.run(argThat(contains('-version')))).thenAnswer((_) => when(processManager.run(argThat(contains('-version')))).thenAnswer((_) =>
Future<ProcessResult>.value(ProcessResult(0, 0, null, javaVersionText))); Future<ProcessResult>.value(ProcessResult(0, 0, null, javaVersionText)));
final String errorMessage = userMessages.androidJavaMinimumVersion(javaVersionText); final String errorMessage = userMessages.androidJavaMinimumVersion(javaVersionText);
final ValidationResult validationResult = await AndroidValidator().validate(); final ValidationResult validationResult = await AndroidValidator(
androidSdk: sdk,
androidStudio: null,
fileSystem: fs,
logger: logger,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me', 'JAVA_HOME': 'home/java'},
processManager: processManager,
userMessages: userMessages,
).validate();
expect(validationResult.type, ValidationType.partial); expect(validationResult.type, ValidationType.partial);
expect( expect(
validationResult.messages.last.message, validationResult.messages.last.message,
errorMessage, errorMessage,
); );
}, overrides: Map<Type, Generator>.unmodifiable(<Type, Generator>{ });
AndroidSdk: () => sdk,
FileSystem: () => fs,
Platform: () => FakePlatform()..environment = <String, String>{'HOME': '/home/me', 'JAVA_HOME': 'home/java'},
ProcessManager: () => processManager,
Stdio: () => stdio,
}));
testWithoutContext('Mentions `kAndroidSdkRoot if user has no AndroidSdk`', () async {
final ValidationResult validationResult = await AndroidValidator(
androidSdk: null,
androidStudio: null,
fileSystem: fs,
logger: logger,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me', 'JAVA_HOME': 'home/java'},
processManager: processManager,
userMessages: userMessages,
).validate();
expect(
validationResult.messages.any(
(ValidationMessage message) => message.message.contains(kAndroidSdkRoot)
),
true,
);
});
} }
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