Unverified Commit 6e5f9ed9 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Replace MockProcessManager with FakeProcessManager (#67019)

parent b42cf8a7
......@@ -827,8 +827,6 @@ class TestHotRunnerFactory extends HotRunnerFactory {
}
class MockDartDevelopmentService extends Mock implements DartDevelopmentService {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {}
class MockHttpClientRequest extends Mock implements HttpClientRequest {}
class MockHttpClientResponse extends Mock implements HttpClientResponse {}
class MockHttpHeaders extends Mock implements HttpHeaders {}
......@@ -5,7 +5,6 @@
import 'package:file/memory.dart';
import 'package:file_testing/file_testing.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/cache.dart';
import 'package:flutter_tools/src/commands/build_windows.dart';
......@@ -420,7 +419,5 @@ C:\foo\windows\runner\main.cpp(17,1): error C2065: 'Baz': undeclared identifier
});
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {}
class MockVisualStudio extends Mock implements VisualStudio {}
class MockUsage extends Mock implements Usage {}
......@@ -24,7 +24,7 @@ void main() {
group('UpgradeCommandRunner', () {
FakeUpgradeCommandRunner fakeCommandRunner;
UpgradeCommandRunner realCommandRunner;
MockProcessManager processManager;
FakeProcessManager processManager;
FakePlatform fakePlatform;
final MockFlutterVersion flutterVersion = MockFlutterVersion();
const GitTagVersion gitTagVersion = GitTagVersion(
......@@ -40,19 +40,7 @@ void main() {
setUp(() {
fakeCommandRunner = FakeUpgradeCommandRunner();
realCommandRunner = UpgradeCommandRunner();
processManager = MockProcessManager();
when(processManager.start(
<String>[
globals.fs.path.join('bin', 'flutter'),
'upgrade',
'--continue',
'--no-version-check',
],
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) async {
return Future<Process>.value(createMockProcess());
});
processManager = FakeProcessManager.list(<FakeCommand>[]);
fakeCommandRunner.willHaveUncomittedChanges = false;
fakePlatform = FakePlatform()..environment = Map<String, String>.unmodifiable(<String, String>{
'ENV1': 'irrelevant',
......@@ -69,24 +57,11 @@ void main() {
flutterVersion: flutterVersion,
);
expect(result, throwsToolExit());
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
Platform: () => fakePlatform,
});
testUsingContext('does not throw on unknown tag, official branch, force', () async {
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: true,
continueFlow: false,
testFlow: false,
gitTagVersion: const GitTagVersion.unknown(),
flutterVersion: flutterVersion,
);
expect(await result, FlutterCommandResult.success());
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('throws tool exit with uncommitted changes', () async {
fakeCommandRunner.willHaveUncomittedChanges = true;
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
......@@ -97,40 +72,11 @@ void main() {
flutterVersion: flutterVersion,
);
expect(result, throwsToolExit());
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
Platform: () => fakePlatform,
});
testUsingContext('does not throw tool exit with uncommitted changes and force', () async {
fakeCommandRunner.willHaveUncomittedChanges = true;
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: true,
continueFlow: false,
testFlow: false,
gitTagVersion: gitTagVersion,
flutterVersion: flutterVersion,
);
expect(await result, FlutterCommandResult.success());
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext("Doesn't throw on known tag, dev branch, no force", () async {
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: false,
continueFlow: false,
testFlow: false,
gitTagVersion: gitTagVersion,
flutterVersion: flutterVersion,
);
expect(await result, FlutterCommandResult.success());
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext("Doesn't continue on known tag, dev branch, no force, already up-to-date", () async {
const String revision = 'abc123';
when(flutterVersion.frameworkRevision).thenReturn(revision);
......@@ -144,17 +90,8 @@ void main() {
flutterVersion: flutterVersion,
);
expect(await result, FlutterCommandResult.success());
verifyNever(globals.processManager.start(
<String>[
globals.fs.path.join('bin', 'flutter'),
'upgrade',
'--continue',
'--no-version-check',
],
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
));
expect(testLogger.statusText, contains('Flutter is already up to date'));
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
......@@ -162,78 +99,75 @@ void main() {
testUsingContext('fetchRemoteRevision returns revision if git succeeds', () async {
const String revision = 'abc123';
when(processManager.run(
<String>['git', 'fetch', '--tags'],
environment:anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
).thenAnswer((Invocation invocation) async {
return FakeProcessResult()
..exitCode = 0;
});
when(processManager.run(
<String>['git', 'rev-parse', '--verify', '@{u}'],
environment:anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
).thenAnswer((Invocation invocation) async {
return FakeProcessResult()
..exitCode = 0
..stdout = revision;
});
processManager.addCommands(<FakeCommand>[
const FakeCommand(command: <String>[
'git', 'fetch', '--tags'
]),
const FakeCommand(command: <String>[
'git', 'rev-parse', '--verify', '@{u}',
],
stdout: revision),
]);
expect(await realCommandRunner.fetchRemoteRevision(), revision);
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('fetchRemoteRevision throws toolExit if HEAD is detached', () async {
when(processManager.run(
<String>['git', 'fetch', '--tags'],
environment:anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
).thenAnswer((Invocation invocation) async {
return FakeProcessResult()..exitCode = 0;
});
when(processManager.run(
<String>['git', 'rev-parse', '--verify', '@{u}'],
environment:anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
).thenThrow(const ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: HEAD does not point to a branch',
));
expect(
() async => await realCommandRunner.fetchRemoteRevision(),
processManager.addCommands(<FakeCommand>[
const FakeCommand(command: <String>[
'git', 'fetch', '--tags'
]),
FakeCommand(
command: const <String>['git', 'rev-parse', '--verify', '@{u}'],
onRun: () {
throw const ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: HEAD does not point to a branch',
);
}
),
]);
await expectLater(
() async => await realCommandRunner.fetchRemoteRevision(),
throwsToolExit(message: 'You are not currently on a release branch.'),
);
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('fetchRemoteRevision throws toolExit if no upstream configured', () async {
when(processManager.run(
<String>['git', 'fetch', '--tags'],
environment:anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
).thenAnswer((Invocation invocation) async {
return FakeProcessResult()..exitCode = 0;
});
when(processManager.run(
<String>['git', 'rev-parse', '--verify', '@{u}'],
environment:anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
).thenThrow(const ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: no upstream configured for branch',
));
expect(
() async => await realCommandRunner.fetchRemoteRevision(),
processManager.addCommands(<FakeCommand>[
const FakeCommand(command: <String>[
'git', 'fetch', '--tags'
]),
FakeCommand(
command: const <String>['git', 'rev-parse', '--verify', '@{u}'],
onRun: () {
throw const ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: no upstream configured for branch',
);
},
),
]);
await expectLater(
() async => await realCommandRunner.fetchRemoteRevision(),
throwsToolExit(
message: 'Unable to upgrade Flutter: no origin repository configured\.',
),
);
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
......@@ -242,132 +176,185 @@ void main() {
testUsingContext('git exception during attemptReset throwsToolExit', () async {
const String revision = 'abc123';
const String errorMessage = 'fatal: Could not parse object ´$revision´';
when(processManager.run(
<String>['git', 'reset', '--hard', revision]
)).thenThrow(const ProcessException(
'git',
<String>['reset', '--hard', revision],
errorMessage,
));
expect(
() async => await realCommandRunner.attemptReset(revision),
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: const <String>['git', 'reset', '--hard', revision],
onRun: () {
throw const ProcessException(
'git',
<String>['reset', '--hard', revision],
errorMessage,
);
},
),
]);
await expectLater(
() async => await realCommandRunner.attemptReset(revision),
throwsToolExit(message: errorMessage),
);
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('flutterUpgradeContinue passes env variables to child process', () async {
processManager.addCommand(
FakeCommand(
command: <String>[
globals.fs.path.join('bin', 'flutter'),
'upgrade',
'--continue',
'--no-version-check',
],
environment: <String, String>{'FLUTTER_ALREADY_LOCKED': 'true', ...fakePlatform.environment}
),
);
await realCommandRunner.flutterUpgradeContinue();
final VerificationResult result = verify(globals.processManager.start(
<String>[
globals.fs.path.join('bin', 'flutter'),
'upgrade',
'--continue',
'--no-version-check',
],
environment: captureAnyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
));
expect(result.captured.first,
<String, String>{ 'FLUTTER_ALREADY_LOCKED': 'true', ...fakePlatform.environment });
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('precacheArtifacts passes env variables to child process', () async {
final List<String> precacheCommand = <String>[
globals.fs.path.join('bin', 'flutter'),
'--no-color',
'--no-version-check',
'precache',
];
when(globals.processManager.start(
precacheCommand,
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) async {
return Future<Process>.value(createMockProcess());
});
processManager.addCommand(
FakeCommand(
command: <String>[
globals.fs.path.join('bin', 'flutter'),
'--no-color',
'--no-version-check',
'precache',
],
environment: <String, String>{'FLUTTER_ALREADY_LOCKED': 'true', ...fakePlatform.environment}
),
);
await realCommandRunner.precacheArtifacts();
final VerificationResult result = verify(globals.processManager.start(
precacheCommand,
environment: captureAnyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
));
expect(result.captured.first,
<String, String>{ 'FLUTTER_ALREADY_LOCKED': 'true', ...fakePlatform.environment });
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
group('full command', () {
FakeProcessManager fakeProcessManager;
Directory tempDir;
File flutterToolState;
FlutterVersion mockFlutterVersion;
group('runs upgrade', () {
setUp(() {
Cache.disableLocking();
fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(
command: <String>[
'git', 'tag', '--points-at', 'HEAD',
],
stdout: '',
),
const FakeCommand(
command: <String>[
'git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags',
],
stdout: 'v1.12.16-19-gb45b676af',
),
]);
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_upgrade_test.');
flutterToolState = tempDir.childFile('.flutter_tool_state');
mockFlutterVersion = MockFlutterVersion(isStable: true);
processManager.addCommand(
FakeCommand(command: <String>[
globals.fs.path.join('bin', 'flutter'),
'upgrade',
'--continue',
'--no-version-check',
]),
);
});
tearDown(() {
Cache.enableLocking();
tryToDelete(tempDir);
testUsingContext('does not throw on unknown tag, official branch, force', () async {
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: true,
continueFlow: false,
testFlow: false,
gitTagVersion: const GitTagVersion.unknown(),
flutterVersion: flutterVersion,
);
expect(await result, FlutterCommandResult.success());
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
testUsingContext('upgrade continue prints welcome message', () async {
final UpgradeCommand upgradeCommand = UpgradeCommand(fakeCommandRunner);
applyMocksToCommand(upgradeCommand);
testUsingContext('does not throw tool exit with uncommitted changes and force', () async {
fakeCommandRunner.willHaveUncomittedChanges = true;
await createTestCommandRunner(upgradeCommand).run(
<String>[
'upgrade',
'--continue',
],
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: true,
continueFlow: false,
testFlow: false,
gitTagVersion: gitTagVersion,
flutterVersion: flutterVersion,
);
expect(await result, FlutterCommandResult.success());
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
expect(
json.decode(flutterToolState.readAsStringSync()),
containsPair('redisplay-welcome-message', true),
testUsingContext("Doesn't throw on known tag, dev branch, no force", () async {
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: false,
continueFlow: false,
testFlow: false,
gitTagVersion: gitTagVersion,
flutterVersion: flutterVersion,
);
expect(await result, FlutterCommandResult.success());
expect(processManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
FlutterVersion: () => mockFlutterVersion,
ProcessManager: () => fakeProcessManager,
PersistentToolState: () => PersistentToolState.test(
directory: tempDir,
logger: testLogger,
),
ProcessManager: () => processManager,
Platform: () => fakePlatform,
});
group('full command', () {
FakeProcessManager fakeProcessManager;
Directory tempDir;
File flutterToolState;
FlutterVersion mockFlutterVersion;
setUp(() {
Cache.disableLocking();
fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(
command: <String>[
'git', 'tag', '--points-at', 'HEAD',
],
stdout: '',
),
const FakeCommand(
command: <String>[
'git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags',
],
stdout: 'v1.12.16-19-gb45b676af',
),
]);
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_upgrade_test.');
flutterToolState = tempDir.childFile('.flutter_tool_state');
mockFlutterVersion = MockFlutterVersion(isStable: true);
});
tearDown(() {
Cache.enableLocking();
tryToDelete(tempDir);
});
testUsingContext('upgrade continue prints welcome message', () async {
final UpgradeCommand upgradeCommand = UpgradeCommand(fakeCommandRunner);
applyMocksToCommand(upgradeCommand);
await createTestCommandRunner(upgradeCommand).run(
<String>[
'upgrade',
'--continue',
],
);
expect(
json.decode(flutterToolState.readAsStringSync()),
containsPair('redisplay-welcome-message', true),
);
}, overrides: <Type, Generator>{
FlutterVersion: () => mockFlutterVersion,
ProcessManager: () => fakeProcessManager,
PersistentToolState: () => PersistentToolState.test(
directory: tempDir,
logger: testLogger,
),
});
});
});
});
}
......@@ -399,19 +386,3 @@ class FakeUpgradeCommandRunner extends UpgradeCommandRunner {
@override
Future<void> runDoctor() async {}
}
class MockProcess extends Mock implements Process {}
class MockProcessManager extends Mock implements ProcessManager {}
class FakeProcessResult implements ProcessResult {
@override
int exitCode;
@override
int pid = 0;
@override
String stderr = '';
@override
String stdout = '';
}
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:convert';
import 'dart:io' show ProcessResult;
import 'package:file/file.dart';
import 'package:file/memory.dart';
......@@ -30,44 +29,35 @@ final Map<Type, Generator> noColorTerminalOverride = <Type, Generator>{
Platform: _kNoColorTerminalPlatform,
};
class MockitoProcessManager extends Mock implements ProcessManager {}
class MockitoAndroidSdk extends Mock implements AndroidSdk {}
class MockitoAndroidSdkVersion extends Mock implements AndroidSdkVersion {}
void main() {
group('Apk with partial Android SDK works', () {
AndroidSdk sdk;
ProcessManager mockProcessManager;
FakeProcessManager fakeProcessManager;
MemoryFileSystem fs;
Cache cache;
File gradle;
final Map<Type, Generator> overrides = <Type, Generator>{
AndroidSdk: () => sdk,
ProcessManager: () => mockProcessManager,
ProcessManager: () => fakeProcessManager,
FileSystem: () => fs,
Cache: () => cache,
};
setUp(() async {
sdk = MockitoAndroidSdk();
mockProcessManager = MockitoProcessManager();
fakeProcessManager = FakeProcessManager.list(<FakeCommand>[]);
fs = MemoryFileSystem.test();
cache = Cache.test(
processManager: FakeProcessManager.any()
processManager: FakeProcessManager.any(),
);
Cache.flutterRoot = '../..';
when(sdk.licensesAvailable).thenReturn(true);
when(mockProcessManager.canRun(any)).thenReturn(true);
when(mockProcessManager.run(
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) async => ProcessResult(1, 0, 'stdout', 'stderr'));
when(mockProcessManager.runSync(any)).thenReturn(ProcessResult(1, 0, 'stdout', 'stderr'));
final FlutterProject project = FlutterProject.current();
gradle = globals.fs.file(project.android.hostAppGradleRoot.childFile(
globals.fs.file(project.android.hostAppGradleRoot.childFile(
globals.platform.isWindows ? 'gradlew.bat' : 'gradlew',
).path)..createSync(recursive: true);
).path).createSync(recursive: true);
});
testUsingContext('Licenses not available, platform and buildtools available, apk exists', () async {
......@@ -78,18 +68,19 @@ void main() {
when(sdk.latestVersion).thenReturn(sdkVersion);
when(sdk.platformToolsAvailable).thenReturn(true);
when(sdk.licensesAvailable).thenReturn(false);
when(mockProcessManager.runSync(
argThat(equals(<String>[
fakeProcessManager.addCommand(
FakeCommand(
command: <String>[
aaptPath,
'dump',
'xmltree',
apkFile.path,
apkFile.path,
'AndroidManifest.xml',
])),
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
),
).thenReturn(ProcessResult(0, 0, _aaptDataWithDefaultEnabledAndMainLauncherActivity, ''));
],
stdout: _aaptDataWithDefaultEnabledAndMainLauncherActivity
)
);
final ApplicationPackage applicationPackage = await ApplicationPackageFactory.instance.getPackageForPlatform(
TargetPlatform.android_arm,
......@@ -97,6 +88,7 @@ void main() {
applicationBinary: apkFile,
);
expect(applicationPackage.name, 'app.apk');
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
}, overrides: overrides);
testUsingContext('Licenses available, build tools not, apk exists', () async {
......@@ -117,18 +109,14 @@ void main() {
gradleWrapperDir.childFile('gradlew').writeAsStringSync('irrelevant');
gradleWrapperDir.childFile('gradlew.bat').writeAsStringSync('irrelevant');
fakeProcessManager.addCommand(FakeCommand(command: <String>[gradle.path, 'dependencies']));
await ApplicationPackageFactory.instance.getPackageForPlatform(
TargetPlatform.android_arm,
buildInfo: null,
applicationBinary: globals.fs.file('app.apk'),
);
verify(
mockProcessManager.run(
argThat(equals(<String>[gradle.path, 'dependencies'])),
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
),
).called(1);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
}, overrides: overrides);
testUsingContext('Licenses available, build tools available, does not call gradle dependencies', () async {
......@@ -139,22 +127,15 @@ void main() {
TargetPlatform.android_arm,
buildInfo: null,
);
verifyNever(
mockProcessManager.run(
argThat(equals(<String>[gradle.path, 'dependencies'])),
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
),
);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
}, overrides: overrides);
testUsingContext('returns null when failed to extract manifest', () async {
final AndroidSdkVersion sdkVersion = MockitoAndroidSdkVersion();
when(sdk.latestVersion).thenReturn(sdkVersion);
when(mockProcessManager.runSync(argThat(contains('logcat'))))
.thenReturn(ProcessResult(0, 1, '', ''));
expect(AndroidApk.fromApk(null), isNull);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
}, overrides: overrides);
});
......
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