[flutter_plugin_tools] Make unit tests pass on Windows (#4149)

The purpose of this PR is to make running all unit tests on Windows pass (vs failing a large portion of the tests as currently happens). This does not mean that the commands actually work when run on Windows, or that Windows support is tested, only that it's possible to actually run the tests themselves. This is prep for actually supporting parts of the tool on Windows in future PRs.

Major changes:
- Make the tests significantly more hermetic:
  - Make almost all tools take a `Platform` constructor argument that can be used to inject a mock platform to control what OS the command acts like it is running on under test.
  - Add a path `Context` object to the base command, whose style matches the `Platform`, and use that almost everywhere instead of the top-level `path` functions.
  - In cases where Posix behavior is always required (such as parsing `git` output), explicitly use the `posix` context object for `path` functions.
- Start laying the groundwork for actual Windows support:
  - Replace all uses of `flutter` as a command with a getter that returns `flutter` or `flutter.bat` as appropriate.
  - For user messages that include relative paths, use a helper that always uses Posix-style relative paths for consistent output.

This bumps the version since quite a few changes have built up, and having a cut point before starting to make more changes to the commands to support Windows seems like a good idea.

Part of https://github.com/flutter/flutter/issues/86113
This commit is contained in:
stuartmorgan
2021-07-09 16:38:13 -07:00
committed by GitHub
parent ac0eed1ac1
commit 77460f03f2
36 changed files with 428 additions and 250 deletions

View File

@ -10,8 +10,6 @@ import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/build_examples_command.dart';
import 'package:flutter_plugin_tools/src/common/core.dart';
import 'package:flutter_plugin_tools/src/common/plugin_utils.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:test/test.dart';
import 'mocks.dart';
@ -20,18 +18,21 @@ import 'util.dart';
void main() {
group('build-example', () {
late FileSystem fileSystem;
late MockPlatform mockPlatform;
late Directory packagesDir;
late CommandRunner<void> runner;
late RecordingProcessRunner processRunner;
final String flutterCommand =
const LocalPlatform().isWindows ? 'flutter.bat' : 'flutter';
setUp(() {
fileSystem = MemoryFileSystem();
mockPlatform = MockPlatform();
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
processRunner = RecordingProcessRunner();
final BuildExamplesCommand command =
BuildExamplesCommand(packagesDir, processRunner: processRunner);
final BuildExamplesCommand command = BuildExamplesCommand(
packagesDir,
processRunner: processRunner,
platform: mockPlatform,
);
runner = CommandRunner<void>(
'build_examples_command', 'Test for build_example_command');
@ -59,7 +60,9 @@ void main() {
kPlatformIos: PlatformSupport.inline
});
processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
processRunner
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
<io.Process>[
MockProcess.failing() // flutter packages get
];
@ -81,6 +84,7 @@ void main() {
test('building for iOS when plugin is not set up for iOS results in no-op',
() async {
mockPlatform.isMacOS = true;
createFakePlugin('plugin', packagesDir);
final List<String> output =
@ -99,7 +103,8 @@ void main() {
expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
});
test('building for ios', () async {
test('building for iOS', () async {
mockPlatform.isMacOS = true;
final Directory pluginDirectory = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformSupport>{
kPlatformIos: PlatformSupport.inline
@ -110,13 +115,11 @@ void main() {
final List<String> output = await runCapturingPrint(runner,
<String>['build-examples', '--ios', '--enable-experiment=exp1']);
final String packageName =
p.relative(pluginExampleDirectory.path, from: packagesDir.path);
expect(
output,
containsAllInOrder(<String>[
'\nBUILDING $packageName for iOS',
'\nBUILDING plugin/example for iOS',
]),
);
@ -124,7 +127,7 @@ void main() {
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
flutterCommand,
getFlutterCommand(mockPlatform),
const <String>[
'build',
'ios',
@ -138,6 +141,7 @@ void main() {
test(
'building for Linux when plugin is not set up for Linux results in no-op',
() async {
mockPlatform.isLinux = true;
createFakePlugin('plugin', packagesDir);
final List<String> output = await runCapturingPrint(
@ -157,6 +161,7 @@ void main() {
});
test('building for Linux', () async {
mockPlatform.isLinux = true;
final Directory pluginDirectory = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformSupport>{
kPlatformLinux: PlatformSupport.inline,
@ -167,26 +172,25 @@ void main() {
final List<String> output = await runCapturingPrint(
runner, <String>['build-examples', '--linux']);
final String packageName =
p.relative(pluginExampleDirectory.path, from: packagesDir.path);
expect(
output,
containsAllInOrder(<String>[
'\nBUILDING $packageName for Linux',
'\nBUILDING plugin/example for Linux',
]),
);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(flutterCommand, const <String>['build', 'linux'],
pluginExampleDirectory.path),
ProcessCall(getFlutterCommand(mockPlatform),
const <String>['build', 'linux'], pluginExampleDirectory.path),
]));
});
test('building for macos with no implementation results in no-op',
test('building for macOS with no implementation results in no-op',
() async {
mockPlatform.isMacOS = true;
createFakePlugin('plugin', packagesDir);
final List<String> output = await runCapturingPrint(
@ -205,7 +209,8 @@ void main() {
expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
});
test('building for macos', () async {
test('building for macOS', () async {
mockPlatform.isMacOS = true;
final Directory pluginDirectory = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformSupport>{
kPlatformMacos: PlatformSupport.inline,
@ -216,21 +221,19 @@ void main() {
final List<String> output = await runCapturingPrint(
runner, <String>['build-examples', '--macos']);
final String packageName =
p.relative(pluginExampleDirectory.path, from: packagesDir.path);
expect(
output,
containsAllInOrder(<String>[
'\nBUILDING $packageName for macOS',
'\nBUILDING plugin/example for macOS',
]),
);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(flutterCommand, const <String>['build', 'macos'],
pluginExampleDirectory.path),
ProcessCall(getFlutterCommand(mockPlatform),
const <String>['build', 'macos'], pluginExampleDirectory.path),
]));
});
@ -264,27 +267,26 @@ void main() {
final List<String> output =
await runCapturingPrint(runner, <String>['build-examples', '--web']);
final String packageName =
p.relative(pluginExampleDirectory.path, from: packagesDir.path);
expect(
output,
containsAllInOrder(<String>[
'\nBUILDING $packageName for web',
'\nBUILDING plugin/example for web',
]),
);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(flutterCommand, const <String>['build', 'web'],
pluginExampleDirectory.path),
ProcessCall(getFlutterCommand(mockPlatform),
const <String>['build', 'web'], pluginExampleDirectory.path),
]));
});
test(
'building for Windows when plugin is not set up for Windows results in no-op',
() async {
mockPlatform.isWindows = true;
createFakePlugin('plugin', packagesDir);
final List<String> output = await runCapturingPrint(
@ -303,7 +305,8 @@ void main() {
expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
});
test('building for windows', () async {
test('building for Windows', () async {
mockPlatform.isWindows = true;
final Directory pluginDirectory = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformSupport>{
kPlatformWindows: PlatformSupport.inline
@ -314,20 +317,20 @@ void main() {
final List<String> output = await runCapturingPrint(
runner, <String>['build-examples', '--windows']);
final String packageName =
p.relative(pluginExampleDirectory.path, from: packagesDir.path);
expect(
output,
containsAllInOrder(<String>[
'\nBUILDING $packageName for Windows',
'\nBUILDING plugin/example for Windows',
]),
);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(flutterCommand, const <String>['build', 'windows'],
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>['build', 'windows'],
pluginExampleDirectory.path),
]));
});
@ -353,7 +356,7 @@ void main() {
expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
});
test('building for android', () async {
test('building for Android', () async {
final Directory pluginDirectory = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformSupport>{
kPlatformAndroid: PlatformSupport.inline
@ -366,21 +369,19 @@ void main() {
'build-examples',
'--apk',
]);
final String packageName =
p.relative(pluginExampleDirectory.path, from: packagesDir.path);
expect(
output,
containsAllInOrder(<String>[
'\nBUILDING $packageName for Android (apk)',
'\nBUILDING plugin/example for Android (apk)',
]),
);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(flutterCommand, const <String>['build', 'apk'],
pluginExampleDirectory.path),
ProcessCall(getFlutterCommand(mockPlatform),
const <String>['build', 'apk'], pluginExampleDirectory.path),
]));
});
@ -400,7 +401,7 @@ void main() {
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
flutterCommand,
getFlutterCommand(mockPlatform),
const <String>['build', 'apk', '--enable-experiment=exp1'],
pluginExampleDirectory.path),
]));
@ -421,7 +422,7 @@ void main() {
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
flutterCommand,
getFlutterCommand(mockPlatform),
const <String>[
'build',
'ios',