Unverified Commit 6bfff984 authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tools] Handle AndroidStudio validator crash (#50282)

parent 20327605
......@@ -4,6 +4,7 @@
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/process.dart';
import '../base/utils.dart';
import '../base/version.dart';
......@@ -307,8 +308,13 @@ class AndroidStudio implements Comparable<AndroidStudio> {
if (!globals.processManager.canRun(javaExecutable)) {
_validationMessages.add('Unable to find bundled Java version.');
} else {
final RunResult result = processUtils.runSync(<String>[javaExecutable, '-version']);
if (result.exitCode == 0) {
RunResult result;
try {
result = processUtils.runSync(<String>[javaExecutable, '-version']);
} on ProcessException catch (e) {
_validationMessages.add('Failed to run Java: $e');
}
if (result != null && result.exitCode == 0) {
final List<String> versionLines = result.stderr.split('\n');
final String javaVersion = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
_validationMessages.add('Java version $javaVersion');
......
......@@ -22,7 +22,9 @@ class AndroidStudioValidator extends DoctorValidator {
if (studios.isEmpty)
NoAndroidStudioValidator()
else
...studios.map<DoctorValidator>((AndroidStudio studio) => AndroidStudioValidator(studio)),
...studios.map<DoctorValidator>(
(AndroidStudio studio) => AndroidStudioValidator(studio)
),
];
}
......@@ -32,24 +34,33 @@ class AndroidStudioValidator extends DoctorValidator {
ValidationType type = ValidationType.missing;
final String studioVersionText = _studio.version == Version.unknown
? null
: userMessages.androidStudioVersion(_studio.version.toString());
messages
.add(ValidationMessage(userMessages.androidStudioLocation(_studio.directory)));
? null
: userMessages.androidStudioVersion(_studio.version.toString());
messages.add(ValidationMessage(
userMessages.androidStudioLocation(_studio.directory),
));
final IntelliJPlugins plugins = IntelliJPlugins(_studio.pluginsPath);
plugins.validatePackage(messages, <String>['flutter-intellij', 'flutter-intellij.jar'],
'Flutter', minVersion: IntelliJPlugins.kMinFlutterPluginVersion);
plugins.validatePackage(
messages,
<String>['flutter-intellij', 'flutter-intellij.jar'],
'Flutter',
minVersion: IntelliJPlugins.kMinFlutterPluginVersion,
);
plugins.validatePackage(messages, <String>['Dart'], 'Dart');
if (_studio.isValid) {
type = _hasIssues(messages) ? ValidationType.partial : ValidationType.installed;
messages.addAll(_studio.validationMessages
.map<ValidationMessage>((String m) => ValidationMessage(m)));
type = _hasIssues(messages)
? ValidationType.partial
: ValidationType.installed;
messages.addAll(_studio.validationMessages.map<ValidationMessage>(
(String m) => ValidationMessage(m),
));
} else {
type = ValidationType.partial;
messages.addAll(_studio.validationMessages
.map<ValidationMessage>((String m) => ValidationMessage.error(m)));
messages.addAll(_studio.validationMessages.map<ValidationMessage>(
(String m) => ValidationMessage.error(m),
));
messages.add(ValidationMessage(userMessages.androidStudioNeedsUpdate));
if (_studio.configured != null) {
messages.add(ValidationMessage(userMessages.androidStudioResetDir));
......@@ -71,13 +82,20 @@ class NoAndroidStudioValidator extends DoctorValidator {
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
final String cfgAndroidStudio = globals.config.getValue('android-studio-dir') as String;
final String cfgAndroidStudio = globals.config.getValue(
'android-studio-dir',
) as String;
if (cfgAndroidStudio != null) {
messages.add(ValidationMessage.error(userMessages.androidStudioMissing(cfgAndroidStudio)));
messages.add(ValidationMessage.error(
userMessages.androidStudioMissing(cfgAndroidStudio),
));
}
messages.add(ValidationMessage(userMessages.androidStudioInstallation));
return ValidationResult(ValidationType.notAvailable, messages,
statusInfo: 'not installed');
return ValidationResult(
ValidationType.notAvailable,
messages,
statusInfo: 'not installed',
);
}
}
......@@ -2,9 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/android/android_studio_validator.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';
import '../../src/common.dart';
import '../../src/context.dart';
......@@ -28,4 +34,42 @@ void main() {
Platform: () => linuxPlatform(),
});
});
group('AndroidStudioValidator', () {
MemoryFileSystem fs;
MockProcessManager mockProcessManager;
setUp(() {
fs = MemoryFileSystem();
mockProcessManager = MockProcessManager();
});
testUsingContext('gives doctor error on java crash', () async {
when(mockProcessManager.canRun(any)).thenReturn(true);
when(mockProcessManager.runSync(any)).thenAnswer((Invocation _) {
throw const ProcessException('java', <String>['--version']);
});
const String installPath = '/opt/android-studio-with-cheese-5.0';
const String studioHome = '$home/.AndroidStudioWithCheese5.0';
const String homeFile = '$studioHome/system/.home';
globals.fs.directory(installPath).createSync(recursive: true);
globals.fs.file(homeFile).createSync(recursive: true);
globals.fs.file(homeFile).writeAsStringSync(installPath);
// This checks that running the validator doesn't throw an unhandled
// exception and that the ProcessException makes it into the error
// message list.
for (final DoctorValidator validator in AndroidStudioValidator.allValidators) {
final ValidationResult result = await validator.validate();
expect(result.messages.where((ValidationMessage message) {
return message.isError && message.message.contains('ProcessException');
}).isNotEmpty, true);
}
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
Platform: () => linuxPlatform(),
});
});
}
class MockProcessManager extends Mock implements ProcessManager {}
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