Unverified Commit 3a0abac7 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] android workflow tests migrate from mockito (#81545)

parent 44157cf9
...@@ -7,43 +7,35 @@ ...@@ -7,43 +7,35 @@
import 'package:file/memory.dart'; import 'package:file/memory.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/io.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
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_validator.dart'; import 'package:flutter_tools/src/doctor_validator.dart';
import 'package:mockito/mockito.dart'; import 'package:test/fake.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fakes.dart'; import '../../src/fakes.dart';
import '../../src/mocks.dart' show MockAndroidSdk, MockProcessManager;
class MockAndroidSdkVersion extends Mock implements AndroidSdkVersion {}
void main() { void main() {
AndroidSdk sdk; FakeAndroidSdk sdk;
Logger logger; Logger logger;
MemoryFileSystem fileSystem; MemoryFileSystem fileSystem;
MockProcessManager processManager; FakeProcessManager processManager;
FakeStdio stdio; FakeStdio stdio;
setUp(() { setUp(() {
sdk = MockAndroidSdk(); sdk = FakeAndroidSdk();
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
fileSystem.directory('/home/me').createSync(recursive: true); fileSystem.directory('/home/me').createSync(recursive: true);
logger = BufferLogger.test(); logger = BufferLogger.test();
processManager = MockProcessManager(); processManager = FakeProcessManager.empty();
stdio = FakeStdio(); stdio = FakeStdio();
}); });
FakeProcess Function(List<String>) processMetaFactory(List<String> stdout) {
final Stream<List<int>> stdoutStream = Stream<List<int>>.fromIterable(
stdout.map<List<int>>((String s) => s.codeUnits));
return (List<String> command) => FakeProcess(stdout: stdoutStream);
}
testWithoutContext('AndroidWorkflow handles a null AndroidSDK', () { testWithoutContext('AndroidWorkflow handles a null AndroidSDK', () {
final AndroidWorkflow androidWorkflow = AndroidWorkflow( final AndroidWorkflow androidWorkflow = AndroidWorkflow(
featureFlags: TestFeatureFlags(), featureFlags: TestFeatureFlags(),
...@@ -57,8 +49,8 @@ void main() { ...@@ -57,8 +49,8 @@ void main() {
}); });
testWithoutContext('AndroidWorkflow handles a null adb', () { testWithoutContext('AndroidWorkflow handles a null adb', () {
final MockAndroidSdk androidSdk = MockAndroidSdk(); final FakeAndroidSdk androidSdk = FakeAndroidSdk();
when(androidSdk.adbPath).thenReturn(null); androidSdk.adbPath = null;
final AndroidWorkflow androidWorkflow = AndroidWorkflow( final AndroidWorkflow androidWorkflow = AndroidWorkflow(
featureFlags: TestFeatureFlags(), featureFlags: TestFeatureFlags(),
androidSdk: androidSdk, androidSdk: androidSdk,
...@@ -72,8 +64,8 @@ void main() { ...@@ -72,8 +64,8 @@ void main() {
// Android Studio is not currently supported on Linux Arm64 hosts. // Android Studio is not currently supported on Linux Arm64 hosts.
testWithoutContext('Not supported AndroidStudio on Linux Arm Hosts', () { testWithoutContext('Not supported AndroidStudio on Linux Arm Hosts', () {
final MockAndroidSdk androidSdk = MockAndroidSdk(); final FakeAndroidSdk androidSdk = FakeAndroidSdk();
when(androidSdk.adbPath).thenReturn(null); androidSdk.adbPath = null;
final AndroidWorkflow androidWorkflow = AndroidWorkflow( final AndroidWorkflow androidWorkflow = AndroidWorkflow(
featureFlags: TestFeatureFlags(), featureFlags: TestFeatureFlags(),
androidSdk: androidSdk, androidSdk: androidSdk,
...@@ -84,8 +76,8 @@ void main() { ...@@ -84,8 +76,8 @@ void main() {
}); });
testWithoutContext('licensesAccepted returns LicensesAccepted.unknown if cannot find sdkmanager', () async { testWithoutContext('licensesAccepted returns LicensesAccepted.unknown if cannot find sdkmanager', () async {
processManager.canRunSucceeds = false; sdk.sdkManagerPath = '/foo/bar/sdkmanager';
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); processManager.excludedExecutables.add('/foo/bar/sdkmanager');
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -103,8 +95,8 @@ void main() { ...@@ -103,8 +95,8 @@ void main() {
}); });
testWithoutContext('licensesAccepted returns LicensesAccepted.unknown if cannot run sdkmanager', () async { testWithoutContext('licensesAccepted returns LicensesAccepted.unknown if cannot run sdkmanager', () async {
processManager.runSucceeds = false; sdk.sdkManagerPath = '/foo/bar/sdkmanager';
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); processManager.excludedExecutables.add('/foo/bar/sdkmanager');
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -122,7 +114,13 @@ void main() { ...@@ -122,7 +114,13 @@ void main() {
}); });
testWithoutContext('licensesAccepted handles garbage/no output', () async { testWithoutContext('licensesAccepted handles garbage/no output', () async {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.sdkManagerPath = '/foo/bar/sdkmanager';
processManager.addCommand(const FakeCommand(
command: <String>[
'/foo/bar/sdkmanager',
'--licenses',
], stdout: 'asdasassad',
));
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -136,17 +134,21 @@ void main() { ...@@ -136,17 +134,21 @@ void main() {
); );
final LicensesAccepted result = await licenseValidator.licensesAccepted; final LicensesAccepted result = await licenseValidator.licensesAccepted;
expect(result, equals(LicensesAccepted.unknown)); expect(result, LicensesAccepted.unknown);
expect(processManager.commands.first, equals('/foo/bar/sdkmanager'));
expect(processManager.commands.last, equals('--licenses'));
}); });
testWithoutContext('licensesAccepted works for all licenses accepted', () async { testWithoutContext('licensesAccepted works for all licenses accepted', () async {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.sdkManagerPath = '/foo/bar/sdkmanager';
processManager.processFactory = processMetaFactory(<String>[ const String output = '''
'[=======================================] 100% Computing updates... ', [=======================================] 100% Computing updates...
'All SDK package licenses accepted.', All SDK package licenses accepted.
]); ''';
processManager.addCommand(const FakeCommand(
command: <String>[
'/foo/bar/sdkmanager',
'--licenses',
], stdout: output,
));
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
...@@ -161,16 +163,22 @@ void main() { ...@@ -161,16 +163,22 @@ void main() {
); );
final LicensesAccepted result = await licenseValidator.licensesAccepted; final LicensesAccepted result = await licenseValidator.licensesAccepted;
expect(result, equals(LicensesAccepted.all)); expect(result, LicensesAccepted.all);
}); });
testWithoutContext('licensesAccepted works for some licenses accepted', () async { testWithoutContext('licensesAccepted works for some licenses accepted', () async {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.sdkManagerPath = '/foo/bar/sdkmanager';
processManager.processFactory = processMetaFactory(<String>[ const String output = '''
'[=======================================] 100% Computing updates... ', [=======================================] 100% Computing updates...
'2 of 5 SDK package licenses not accepted.', 2 of 5 SDK package licenses not accepted.
'Review licenses that have not been accepted (y/N)?', Review licenses that have not been accepted (y/N)?
]); ''';
processManager.addCommand(const FakeCommand(
command: <String>[
'/foo/bar/sdkmanager',
'--licenses',
], stdout: output,
));
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
...@@ -185,16 +193,22 @@ void main() { ...@@ -185,16 +193,22 @@ void main() {
); );
final LicensesAccepted result = await licenseValidator.licensesAccepted; final LicensesAccepted result = await licenseValidator.licensesAccepted;
expect(result, equals(LicensesAccepted.some)); expect(result, LicensesAccepted.some);
}); });
testWithoutContext('licensesAccepted works for no licenses accepted', () async { testWithoutContext('licensesAccepted works for no licenses accepted', () async {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.sdkManagerPath = '/foo/bar/sdkmanager';
processManager.processFactory = processMetaFactory(<String>[ const String output = '''
'[=======================================] 100% Computing updates... ', [=======================================] 100% Computing updates...
'5 of 5 SDK package licenses not accepted.', 5 of 5 SDK package licenses not accepted.
'Review licenses that have not been accepted (y/N)?', Review licenses that have not been accepted (y/N)?
]); ''';
processManager.addCommand(const FakeCommand(
command: <String>[
'/foo/bar/sdkmanager',
'--licenses',
], stdout: output,
));
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
...@@ -209,12 +223,18 @@ void main() { ...@@ -209,12 +223,18 @@ void main() {
); );
final LicensesAccepted result = await licenseValidator.licensesAccepted; final LicensesAccepted result = await licenseValidator.licensesAccepted;
expect(result, equals(LicensesAccepted.none)); expect(result, LicensesAccepted.none);
}); });
testWithoutContext('runLicenseManager succeeds for version >= 26', () async { testWithoutContext('runLicenseManager succeeds for version >= 26', () async {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.sdkManagerPath = '/foo/bar/sdkmanager';
when(sdk.sdkManagerVersion).thenReturn('26.0.0'); sdk.sdkManagerVersion = '26.0.0';
processManager.addCommand(const FakeCommand(
command: <String>[
'/foo/bar/sdkmanager',
'--licenses',
], stdout: '',
));
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
...@@ -232,8 +252,8 @@ void main() { ...@@ -232,8 +252,8 @@ void main() {
}); });
testWithoutContext('runLicenseManager errors when sdkmanager is not found', () async { testWithoutContext('runLicenseManager errors when sdkmanager is not found', () async {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.sdkManagerPath = '/foo/bar/sdkmanager';
processManager.canRunSucceeds = false; processManager.excludedExecutables.add('/foo/bar/sdkmanager');
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
...@@ -251,8 +271,8 @@ void main() { ...@@ -251,8 +271,8 @@ void main() {
}); });
testWithoutContext('runLicenseManager errors when sdkmanager fails to run', () async { testWithoutContext('runLicenseManager errors when sdkmanager fails to run', () async {
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.sdkManagerPath = '/foo/bar/sdkmanager';
processManager.runSucceeds = false; processManager.excludedExecutables.add('/foo/bar/sdkmanager');
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator( final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk, androidSdk: sdk,
...@@ -270,8 +290,8 @@ void main() { ...@@ -270,8 +290,8 @@ void main() {
}); });
testWithoutContext('detects license-only SDK installation', () async { testWithoutContext('detects license-only SDK installation', () async {
when(sdk.licensesAvailable).thenReturn(true); sdk.licensesAvailable = true;
when(sdk.platformToolsAvailable).thenReturn(false); sdk.platformToolsAvailable = false;
final ValidationResult validationResult = await AndroidValidator( final ValidationResult validationResult = await AndroidValidator(
androidStudio: null, androidStudio: null,
androidSdk: sdk, androidSdk: sdk,
...@@ -281,6 +301,7 @@ void main() { ...@@ -281,6 +301,7 @@ void main() {
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'}, platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
userMessages: UserMessages(), userMessages: UserMessages(),
).validate(); ).validate();
expect(validationResult.type, ValidationType.partial); expect(validationResult.type, ValidationType.partial);
expect( expect(
validationResult.messages.last.message, validationResult.messages.last.message,
...@@ -289,18 +310,24 @@ void main() { ...@@ -289,18 +310,24 @@ void main() {
}); });
testWithoutContext('detects minimum required SDK and buildtools', () async { testWithoutContext('detects minimum required SDK and buildtools', () async {
final AndroidSdkVersion mockSdkVersion = MockAndroidSdkVersion(); processManager.addCommand(const FakeCommand(
when(sdk.licensesAvailable).thenReturn(true); command: <String>[
when(sdk.platformToolsAvailable).thenReturn(true); 'which',
'java',
], exitCode: 1,
));
final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion()
..sdkLevel = 28
..buildToolsVersion = Version(26, 0, 3);
sdk
..licensesAvailable = true
..platformToolsAvailable = true
// Test with invalid SDK and build tools // Test with invalid SDK and build tools
when(mockSdkVersion.sdkLevel).thenReturn(28); ..directory = fileSystem.directory('/foo/bar')
when(mockSdkVersion.buildToolsVersion).thenReturn(Version(26, 0, 3)); ..sdkManagerPath = '/foo/bar/sdkmanager'
when(sdk.directory).thenReturn(fileSystem.directory('/foo/bar')); ..latestVersion = sdkVersion;
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager');
when(sdk.latestVersion).thenReturn(mockSdkVersion);
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,
...@@ -326,8 +353,8 @@ void main() { ...@@ -326,8 +353,8 @@ void main() {
); );
// Test with valid SDK but invalid build tools // Test with valid SDK but invalid build tools
when(mockSdkVersion.sdkLevel).thenReturn(29); sdkVersion.sdkLevel = 29;
when(mockSdkVersion.buildToolsVersion).thenReturn(Version(28, 0, 2)); sdkVersion.buildToolsVersion = Version(28, 0, 2);
validationResult = await androidValidator.validate(); validationResult = await androidValidator.validate();
expect(validationResult.type, ValidationType.missing); expect(validationResult.type, ValidationType.missing);
...@@ -338,8 +365,8 @@ void main() { ...@@ -338,8 +365,8 @@ void main() {
// Test with valid SDK and valid build tools // Test with valid SDK and valid build tools
// Will still be partial because AnroidSdk.findJavaBinary is static :( // Will still be partial because AnroidSdk.findJavaBinary is static :(
when(mockSdkVersion.sdkLevel).thenReturn(kAndroidSdkMinVersion); sdkVersion.sdkLevel = kAndroidSdkMinVersion;
when(mockSdkVersion.buildToolsVersion).thenReturn(kAndroidSdkBuildToolsMinVersion); sdkVersion.buildToolsVersion = 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
...@@ -350,22 +377,26 @@ void main() { ...@@ -350,22 +377,26 @@ void main() {
}); });
testWithoutContext('detects minimum required java version', () async { testWithoutContext('detects minimum required java version', () async {
final AndroidSdkVersion mockSdkVersion = MockAndroidSdkVersion(); // Test with older version of JDK
const String javaVersionText = 'openjdk version "1.7.0_212"';
processManager.addCommand(const FakeCommand(
command: <String>[
'home/java/bin/java',
'-version',
], stderr: javaVersionText,
));
final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion()
..sdkLevel = 29
..buildToolsVersion = Version(28, 0, 3);
// Mock a pass through scenario to reach _checkJavaVersion() // Mock a pass through scenario to reach _checkJavaVersion()
when(sdk.licensesAvailable).thenReturn(true); sdk
when(sdk.platformToolsAvailable).thenReturn(true); ..licensesAvailable = true
when(mockSdkVersion.sdkLevel).thenReturn(29); ..platformToolsAvailable = true
when(mockSdkVersion.buildToolsVersion).thenReturn(Version(28, 0, 3)); ..directory = fileSystem.directory('/foo/bar')
when(sdk.directory).thenReturn(fileSystem.directory('/foo/bar')); ..sdkManagerPath = '/foo/bar/sdkmanager';
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); sdk.latestVersion = sdkVersion;
when(sdk.latestVersion).thenReturn(mockSdkVersion);
when(sdk.validateSdkWellFormed()).thenReturn(<String>[]);
//Test with older version of JDK
const String javaVersionText = 'openjdk version "1.7.0_212"';
when(processManager.run(argThat(contains('-version')))).thenAnswer((_) =>
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( final ValidationResult validationResult = await AndroidValidator(
...@@ -410,6 +441,49 @@ void main() { ...@@ -410,6 +441,49 @@ void main() {
}); });
} }
class FakeAndroidSdk extends Fake implements AndroidSdk {
@override
String sdkManagerPath;
@override
String sdkManagerVersion;
@override
String adbPath;
@override
bool licensesAvailable;
@override
bool platformToolsAvailable;
@override
Directory directory;
@override
AndroidSdkVersion latestVersion;
@override
List<String> validateSdkWellFormed() => <String>[];
@override
Map<String, String> get sdkManagerEnv => <String, String>{};
}
class FakeAndroidSdkVersion extends Fake implements AndroidSdkVersion {
@override
int sdkLevel;
@override
Version buildToolsVersion;
@override
String get buildToolsVersionName => '';
@override
String get platformName => '';
}
class CustomFakeOperatingSystemUtils extends Fake implements OperatingSystemUtils { class CustomFakeOperatingSystemUtils extends Fake implements OperatingSystemUtils {
CustomFakeOperatingSystemUtils({ CustomFakeOperatingSystemUtils({
HostPlatform hostPlatform = HostPlatform.linux_x64 HostPlatform hostPlatform = HostPlatform.linux_x64
......
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