[flutter_tools] cleanups to plugin test cases (#67242)

Removes usage of global variables, expands documentation, and fixes some formatting inconsistencies. Increased test coverage for android plugin to prove it can determine the embedding version.
diff --git a/packages/flutter_tools/lib/src/platform_plugins.dart b/packages/flutter_tools/lib/src/platform_plugins.dart
index 3827718..68f7931 100644
--- a/packages/flutter_tools/lib/src/platform_plugins.dart
+++ b/packages/flutter_tools/lib/src/platform_plugins.dart
@@ -7,7 +7,6 @@
 
 import 'base/common.dart';
 import 'base/file_system.dart';
-import 'globals.dart' as globals;
 
 /// Constant for 'pluginClass' key in plugin maps.
 const String kPluginClass = 'pluginClass';
@@ -38,18 +37,22 @@
     @required this.package,
     @required this.pluginClass,
     @required this.pluginPath,
-  });
+    @required FileSystem fileSystem,
+  }) : _fileSystem = fileSystem;
 
-  factory AndroidPlugin.fromYaml(String name, YamlMap yaml, String pluginPath) {
+  factory AndroidPlugin.fromYaml(String name, YamlMap yaml, String pluginPath, FileSystem fileSystem) {
     assert(validate(yaml));
     return AndroidPlugin(
       name: name,
       package: yaml['package'] as String,
       pluginClass: yaml['pluginClass'] as String,
       pluginPath: pluginPath,
+      fileSystem: fileSystem,
     );
   }
 
+  final FileSystem _fileSystem;
+
   static bool validate(YamlMap yaml) {
     if (yaml == null) {
       return false;
@@ -91,7 +94,7 @@
   Set<String> _getSupportedEmbeddings() {
     assert(pluginPath != null);
     final Set<String> supportedEmbeddings = <String>{};
-    final String baseMainPath = globals.fs.path.join(
+    final String baseMainPath = _fileSystem.path.join(
       pluginPath,
       'android',
       'src',
@@ -99,16 +102,16 @@
     );
 
     final List<String> mainClassCandidates = <String>[
-      globals.fs.path.join(
+      _fileSystem.path.join(
         baseMainPath,
         'java',
-        package.replaceAll('.', globals.fs.path.separator),
+        package.replaceAll('.', _fileSystem.path.separator),
         '$pluginClass.java',
       ),
-      globals.fs.path.join(
+      _fileSystem.path.join(
         baseMainPath,
         'kotlin',
-        package.replaceAll('.', globals.fs.path.separator),
+        package.replaceAll('.', _fileSystem.path.separator),
         '$pluginClass.kt',
       )
     ];
@@ -116,7 +119,7 @@
     File mainPluginClass;
     bool mainClassFound = false;
     for (final String mainClassCandidate in mainClassCandidates) {
-      mainPluginClass = globals.fs.file(mainClassCandidate);
+      mainPluginClass = _fileSystem.file(mainClassCandidate);
       if (mainPluginClass.existsSync()) {
         mainClassFound = true;
         break;
@@ -132,15 +135,7 @@
       );
     }
 
-    String mainClassContent;
-    try {
-      mainClassContent = mainPluginClass.readAsStringSync();
-    } on FileSystemException {
-      throwToolExit(
-        "Couldn't read file ${mainPluginClass.path} even though it exists. "
-        'Please verify that this file has read permission and try again.'
-      );
-    }
+    final String mainClassContent = mainPluginClass.readAsStringSync();
     if (mainClassContent
         .contains('io.flutter.embedding.engine.plugins.FlutterPlugin')) {
       supportedEmbeddings.add('2');
@@ -167,7 +162,7 @@
   });
 
   factory IOSPlugin.fromYaml(String name, YamlMap yaml) {
-    assert(validate(yaml));
+    assert(validate(yaml)); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/67241
     return IOSPlugin(
       name: name,
       classPrefix: '',
diff --git a/packages/flutter_tools/lib/src/plugins.dart b/packages/flutter_tools/lib/src/plugins.dart
index 6f801df..fc12f99 100644
--- a/packages/flutter_tools/lib/src/plugins.dart
+++ b/packages/flutter_tools/lib/src/plugins.dart
@@ -68,16 +68,17 @@
     String name,
     String path,
     YamlMap pluginYaml,
-    List<String> dependencies,
-  ) {
+    List<String> dependencies, {
+    @required FileSystem fileSystem,
+  }) {
     final List<String> errors = validatePluginYaml(pluginYaml);
     if (errors.isNotEmpty) {
       throwToolExit('Invalid plugin specification $name.\n${errors.join('\n')}');
     }
     if (pluginYaml != null && pluginYaml['platforms'] != null) {
-      return Plugin._fromMultiPlatformYaml(name, path, pluginYaml, dependencies);
+      return Plugin._fromMultiPlatformYaml(name, path, pluginYaml, dependencies, fileSystem);
     }
-    return Plugin._fromLegacyYaml(name, path, pluginYaml, dependencies);
+    return Plugin._fromLegacyYaml(name, path, pluginYaml, dependencies, fileSystem);
   }
 
   factory Plugin._fromMultiPlatformYaml(
@@ -85,6 +86,7 @@
     String path,
     dynamic pluginYaml,
     List<String> dependencies,
+    FileSystem fileSystem,
   ) {
     assert (pluginYaml != null && pluginYaml['platforms'] != null,
             'Invalid multi-platform plugin specification $name.');
@@ -100,6 +102,7 @@
         name,
         platformsYaml[AndroidPlugin.kConfigKey] as YamlMap,
         path,
+        fileSystem,
       );
     }
 
@@ -141,6 +144,7 @@
     String path,
     dynamic pluginYaml,
     List<String> dependencies,
+    FileSystem fileSystem,
   ) {
     final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{};
     final String pluginClass = pluginYaml['pluginClass'] as String;
@@ -152,6 +156,7 @@
           package: pluginYaml['androidPackage'] as String,
           pluginClass: pluginClass,
           pluginPath: path,
+          fileSystem: fileSystem,
         );
       }
 
@@ -332,6 +337,7 @@
     packageRootPath,
     flutterConfig['plugin'] as YamlMap,
     dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()],
+    fileSystem: globals.fs,
   );
 }
 
diff --git a/packages/flutter_tools/test/general.shard/android_plugin_test.dart b/packages/flutter_tools/test/general.shard/android_plugin_test.dart
new file mode 100644
index 0000000..e411cac
--- /dev/null
+++ b/packages/flutter_tools/test/general.shard/android_plugin_test.dart
@@ -0,0 +1,121 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:file/file.dart';
+import 'package:file/memory.dart';
+import 'package:flutter_tools/src/platform_plugins.dart';
+
+
+import '../src/common.dart';
+
+void main() {
+  testWithoutContext('AndroidPlugin throws tool exit if the plugin main class can not be found', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    final AndroidPlugin androidPlugin = AndroidPlugin(
+      name: 'pluginA',
+      package: 'com.company',
+      pluginClass: 'PluginA',
+      pluginPath: '.pub_cache/plugin_a',
+      fileSystem: fileSystem,
+    );
+
+    expect(() => androidPlugin.toMap(), throwsToolExit(
+      message: "The plugin `pluginA` doesn't have a main class defined in "
+      '.pub_cache/plugin_a/android/src/main/java/com/company/PluginA.java '
+      'or .pub_cache/plugin_a/android/src/main/kotlin/com/company/PluginA.kt'
+    ));
+  });
+
+  testWithoutContext('AndroidPlugin parses embedding version 2 from the Java search path', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    final AndroidPlugin androidPlugin = AndroidPlugin(
+      name: 'pluginA',
+      package: 'com.company',
+      pluginClass: 'PluginA',
+      pluginPath: '.pub_cache/plugin_a',
+      fileSystem: fileSystem,
+    );
+
+    fileSystem.file('.pub_cache/plugin_a/android/src/main/java/com/company/PluginA.java')
+      ..createSync(recursive: true)
+      ..writeAsStringSync('io.flutter.embedding.engine.plugins.FlutterPlugin');
+
+    expect(androidPlugin.toMap(), <String, Object>{
+      'name': 'pluginA',
+      'package': 'com.company',
+      'class': 'PluginA',
+      'supportsEmbeddingV1': false,
+      'supportsEmbeddingV2': true,
+    });
+  });
+
+  testWithoutContext('AndroidPlugin parses embedding version 1 from the Java search path', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    final AndroidPlugin androidPlugin = AndroidPlugin(
+      name: 'pluginA',
+      package: 'com.company',
+      pluginClass: 'PluginA',
+      pluginPath: '.pub_cache/plugin_a',
+      fileSystem: fileSystem,
+    );
+
+    fileSystem.file('.pub_cache/plugin_a/android/src/main/java/com/company/PluginA.java')
+      ..createSync(recursive: true)
+      ..writeAsStringSync('some.other.string');
+
+    expect(androidPlugin.toMap(), <String, Object>{
+      'name': 'pluginA',
+      'package': 'com.company',
+      'class': 'PluginA',
+      'supportsEmbeddingV1': true,
+      'supportsEmbeddingV2': false,
+    });
+  });
+
+  testWithoutContext('AndroidPlugin parses embedding version 2 from the Kotlin search path', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    final AndroidPlugin androidPlugin = AndroidPlugin(
+      name: 'pluginA',
+      package: 'com.company',
+      pluginClass: 'PluginA',
+      pluginPath: '.pub_cache/plugin_a',
+      fileSystem: fileSystem,
+    );
+
+    fileSystem.file('.pub_cache/plugin_a/android/src/main/kotlin/com/company/PluginA.kt')
+      ..createSync(recursive: true)
+      ..writeAsStringSync('io.flutter.embedding.engine.plugins.FlutterPlugin');
+
+    expect(androidPlugin.toMap(), <String, Object>{
+      'name': 'pluginA',
+      'package': 'com.company',
+      'class': 'PluginA',
+      'supportsEmbeddingV1': false,
+      'supportsEmbeddingV2': true,
+    });
+  });
+
+  testWithoutContext('AndroidPlugin parses embedding version 1 from the Kotlin search path', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    final AndroidPlugin androidPlugin = AndroidPlugin(
+      name: 'pluginA',
+      package: 'com.company',
+      pluginClass: 'PluginA',
+      pluginPath: '.pub_cache/plugin_a',
+      fileSystem: fileSystem,
+    );
+
+    fileSystem.file('.pub_cache/plugin_a/android/src/main/kotlin/com/company/PluginA.kt')
+      ..createSync(recursive: true)
+      ..writeAsStringSync('some.other.string');
+
+    expect(androidPlugin.toMap(), <String, Object>{
+      'name': 'pluginA',
+      'package': 'com.company',
+      'class': 'PluginA',
+      'supportsEmbeddingV1': true,
+      'supportsEmbeddingV2': false,
+    });
+  });
+}
diff --git a/packages/flutter_tools/test/general.shard/platform_plugins_test.dart b/packages/flutter_tools/test/general.shard/platform_plugins_test.dart
deleted file mode 100644
index 09cac88..0000000
--- a/packages/flutter_tools/test/general.shard/platform_plugins_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:file/file.dart';
-import 'package:flutter_tools/src/platform_plugins.dart';
-import 'package:mockito/mockito.dart';
-import 'package:path/path.dart' as p;
-
-import '../src/common.dart';
-import '../src/context.dart';
-
-void main() {
-  group('AndroidPlugin', () {
-    MockFileSystem mockFileSystem;
-    MockPathContext pathContext;
-
-    setUp(() {
-      pathContext = MockPathContext();
-      when(pathContext.separator).thenReturn('/');
-
-      mockFileSystem = MockFileSystem();
-      when(mockFileSystem.path).thenReturn(pathContext);
-    });
-
-    testUsingContext("throws tool exit if the plugin main class can't be read", () {
-      when(pathContext.join('.pub_cache/plugin_a', 'android', 'src', 'main'))
-        .thenReturn('.pub_cache/plugin_a/android/src/main');
-
-      when(pathContext.join('.pub_cache/plugin_a/android/src/main', 'java', 'com/company', 'PluginA.java'))
-        .thenReturn('.pub_cache/plugin_a/android/src/main/java/com/company/PluginA.java');
-
-      when(pathContext.join('.pub_cache/plugin_a/android/src/main', 'kotlin', 'com/company', 'PluginA.kt'))
-        .thenReturn('.pub_cache/plugin_a/android/src/main/kotlin/com/company/PluginA.kt');
-
-      final MockFile pluginJavaMainClass = MockFile();
-      when(pluginJavaMainClass.existsSync()).thenReturn(true);
-      when(pluginJavaMainClass.readAsStringSync(encoding: anyNamed('encoding'))).thenThrow(const FileSystemException());
-      when(mockFileSystem.file('.pub_cache/plugin_a/android/src/main/java/com/company/PluginA.java'))
-        .thenReturn(pluginJavaMainClass);
-
-      final MockFile pluginKotlinMainClass = MockFile();
-      when(pluginKotlinMainClass.existsSync()).thenReturn(false);
-      when(mockFileSystem.file('.pub_cache/plugin_a/android/src/main/kotlin/com/company/PluginA.kt'))
-        .thenReturn(pluginKotlinMainClass);
-
-      expect(() {
-        AndroidPlugin(
-          name: 'pluginA',
-          package: 'com.company',
-          pluginClass: 'PluginA',
-          pluginPath: '.pub_cache/plugin_a',
-        ).toMap();
-      }, throwsToolExit(
-        message: "Couldn't read file null even though it exists. "
-                 'Please verify that this file has read permission and try again.'
-      ));
-    }, overrides: <Type, Generator>{
-      FileSystem: () => mockFileSystem,
-      ProcessManager: () => FakeProcessManager.any(),
-    });
-  });
-}
-
-class MockFile extends Mock implements File {}
-class MockFileSystem extends Mock implements FileSystem {}
-class MockPathContext extends Mock implements p.Context {}
diff --git a/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart b/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart
index 680b343..96867c6 100644
--- a/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart
+++ b/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart
@@ -2,6 +2,8 @@
 // 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/platform_plugins.dart';
 import 'package:flutter_tools/src/plugins.dart';
 import 'package:yaml/yaml.dart';
@@ -12,209 +14,261 @@
 const String _kTestPluginPath = 'test_plugin_path';
 
 void main() {
-  group('PluginParsing', () {
-    test('Legacy Format', () {
-      const String pluginYamlRaw = 'androidPackage: com.flutter.dev\n'
-          'iosPrefix: FLT\n'
-          'pluginClass: SamplePlugin\n';
+  testWithoutContext('Plugin creation from the legacy format', () {
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    const String pluginYamlRaw = 'androidPackage: com.flutter.dev\n'
+      'iosPrefix: FLT\n'
+      'pluginClass: SamplePlugin\n';
 
-      final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
-      final Plugin plugin =
-          Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]);
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
+    final Plugin plugin = Plugin.fromYaml(
+      _kTestPluginName,
+      _kTestPluginPath,
+      pluginYaml,
+      const <String>[],
+      fileSystem: fileSystem,
+    );
 
-      final AndroidPlugin androidPlugin =
-          plugin.platforms[AndroidPlugin.kConfigKey] as AndroidPlugin;
-      final IOSPlugin iosPlugin = plugin.platforms[IOSPlugin.kConfigKey] as IOSPlugin;
-      final String androidPluginClass = androidPlugin.pluginClass;
-      final String iosPluginClass = iosPlugin.pluginClass;
+    final AndroidPlugin androidPlugin = plugin.platforms[AndroidPlugin.kConfigKey] as AndroidPlugin;
+    final IOSPlugin iosPlugin = plugin.platforms[IOSPlugin.kConfigKey] as IOSPlugin;
+    final String androidPluginClass = androidPlugin.pluginClass;
+    final String iosPluginClass = iosPlugin.pluginClass;
 
-      expect(iosPluginClass, 'SamplePlugin');
-      expect(androidPluginClass, 'SamplePlugin');
-      expect(iosPlugin.classPrefix, 'FLT');
-      expect(androidPlugin.package, 'com.flutter.dev');
-    });
+    expect(iosPluginClass, 'SamplePlugin');
+    expect(androidPluginClass, 'SamplePlugin');
+    expect(iosPlugin.classPrefix, 'FLT');
+    expect(androidPlugin.package, 'com.flutter.dev');
+  });
 
-    test('Multi-platform Format', () {
-      const String pluginYamlRaw = 'platforms:\n'
-          ' android:\n'
-          '  package: com.flutter.dev\n'
-          '  pluginClass: ASamplePlugin\n'
-          ' ios:\n'
-          '  pluginClass: ISamplePlugin\n'
-          ' linux:\n'
-          '  pluginClass: LSamplePlugin\n'
-          ' macos:\n'
-          '  pluginClass: MSamplePlugin\n'
-          ' web:\n'
-          '  pluginClass: WebSamplePlugin\n'
-          '  fileName: web_plugin.dart\n'
-          ' windows:\n'
-          '  pluginClass: WinSamplePlugin\n';
+  testWithoutContext('Plugin creation from the multi-platform format', () {
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    const String pluginYamlRaw = 'platforms:\n'
+      ' android:\n'
+      '  package: com.flutter.dev\n'
+      '  pluginClass: ASamplePlugin\n'
+      ' ios:\n'
+      '  pluginClass: ISamplePlugin\n'
+      ' linux:\n'
+      '  pluginClass: LSamplePlugin\n'
+      ' macos:\n'
+      '  pluginClass: MSamplePlugin\n'
+      ' web:\n'
+      '  pluginClass: WebSamplePlugin\n'
+      '  fileName: web_plugin.dart\n'
+      ' windows:\n'
+      '  pluginClass: WinSamplePlugin\n';
 
-      final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
-      final Plugin plugin =
-          Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]);
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
+    final Plugin plugin = Plugin.fromYaml(
+      _kTestPluginName,
+      _kTestPluginPath,
+      pluginYaml,
+      const <String>[],
+      fileSystem: fileSystem,
+    );
 
-      final AndroidPlugin androidPlugin =
-          plugin.platforms[AndroidPlugin.kConfigKey] as AndroidPlugin;
-      final IOSPlugin iosPlugin = plugin.platforms[IOSPlugin.kConfigKey] as IOSPlugin;
-      final LinuxPlugin linuxPlugin =
-          plugin.platforms[LinuxPlugin.kConfigKey] as LinuxPlugin;
-      final MacOSPlugin macOSPlugin =
-          plugin.platforms[MacOSPlugin.kConfigKey] as MacOSPlugin;
-      final WebPlugin webPlugin = plugin.platforms[WebPlugin.kConfigKey] as WebPlugin;
-      final WindowsPlugin windowsPlugin =
-          plugin.platforms[WindowsPlugin.kConfigKey] as WindowsPlugin;
-      final String androidPluginClass = androidPlugin.pluginClass;
-      final String iosPluginClass = iosPlugin.pluginClass;
+    final AndroidPlugin androidPlugin = plugin.platforms[AndroidPlugin.kConfigKey] as AndroidPlugin;
+    final IOSPlugin iosPlugin = plugin.platforms[IOSPlugin.kConfigKey] as IOSPlugin;
+    final LinuxPlugin linuxPlugin = plugin.platforms[LinuxPlugin.kConfigKey] as LinuxPlugin;
+    final MacOSPlugin macOSPlugin = plugin.platforms[MacOSPlugin.kConfigKey] as MacOSPlugin;
+    final WebPlugin webPlugin = plugin.platforms[WebPlugin.kConfigKey] as WebPlugin;
+    final WindowsPlugin windowsPlugin = plugin.platforms[WindowsPlugin.kConfigKey] as WindowsPlugin;
+    final String androidPluginClass = androidPlugin.pluginClass;
+    final String iosPluginClass = iosPlugin.pluginClass;
 
-      expect(iosPluginClass, 'ISamplePlugin');
-      expect(androidPluginClass, 'ASamplePlugin');
-      expect(iosPlugin.classPrefix, '');
-      expect(androidPlugin.package, 'com.flutter.dev');
-      expect(linuxPlugin.pluginClass, 'LSamplePlugin');
-      expect(macOSPlugin.pluginClass, 'MSamplePlugin');
-      expect(webPlugin.pluginClass, 'WebSamplePlugin');
-      expect(webPlugin.fileName, 'web_plugin.dart');
-      expect(windowsPlugin.pluginClass, 'WinSamplePlugin');
-    });
+    expect(iosPluginClass, 'ISamplePlugin');
+    expect(androidPluginClass, 'ASamplePlugin');
+    expect(iosPlugin.classPrefix, '');
+    expect(androidPlugin.package, 'com.flutter.dev');
+    expect(linuxPlugin.pluginClass, 'LSamplePlugin');
+    expect(macOSPlugin.pluginClass, 'MSamplePlugin');
+    expect(webPlugin.pluginClass, 'WebSamplePlugin');
+    expect(webPlugin.fileName, 'web_plugin.dart');
+    expect(windowsPlugin.pluginClass, 'WinSamplePlugin');
+  });
 
-    test('Unknown fields are allowed (allows some future compatibility)', () {
-      const String pluginYamlRaw = 'implements: same_plugin\n' // this should be ignored by the tool
-          'platforms:\n'
-          ' android:\n'
-          '  package: com.flutter.dev\n'
-          '  pluginClass: ASamplePlugin\n'
-          '  anUnknownField: ASamplePlugin\n' // this should be ignored by the tool
-          ' ios:\n'
-          '  pluginClass: ISamplePlugin\n'
-          ' linux:\n'
-          '  pluginClass: LSamplePlugin\n'
-          ' macos:\n'
-          '  pluginClass: MSamplePlugin\n'
-          ' web:\n'
-          '  pluginClass: WebSamplePlugin\n'
-          '  fileName: web_plugin.dart\n'
-          ' windows:\n'
-          '  pluginClass: WinSamplePlugin\n';
+  testWithoutContext('Plugin parsing of unknown fields are allowed (allows some future compatibility)', () {
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    const String pluginYamlRaw = 'implements: same_plugin\n' // this should be ignored by the tool
+      'platforms:\n'
+      ' android:\n'
+      '  package: com.flutter.dev\n'
+      '  pluginClass: ASamplePlugin\n'
+      '  anUnknownField: ASamplePlugin\n' // this should be ignored by the tool
+      ' ios:\n'
+      '  pluginClass: ISamplePlugin\n'
+      ' linux:\n'
+      '  pluginClass: LSamplePlugin\n'
+      ' macos:\n'
+      '  pluginClass: MSamplePlugin\n'
+      ' web:\n'
+      '  pluginClass: WebSamplePlugin\n'
+      '  fileName: web_plugin.dart\n'
+      ' windows:\n'
+        '  pluginClass: WinSamplePlugin\n';
 
-      final dynamic pluginYaml = loadYaml(pluginYamlRaw);
-      final Plugin plugin =
-      Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml as YamlMap, const <String>[]);
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
+    final Plugin plugin = Plugin.fromYaml(
+      _kTestPluginName,
+      _kTestPluginPath,
+      pluginYaml,
+      const <String>[],
+      fileSystem: fileSystem,
+    );
 
-      final AndroidPlugin androidPlugin = plugin.platforms[AndroidPlugin.kConfigKey] as AndroidPlugin;
-      final IOSPlugin iosPlugin = plugin.platforms[IOSPlugin.kConfigKey] as IOSPlugin;
-      final LinuxPlugin linuxPlugin = plugin.platforms[LinuxPlugin.kConfigKey] as LinuxPlugin;
-      final MacOSPlugin macOSPlugin = plugin.platforms[MacOSPlugin.kConfigKey] as MacOSPlugin;
-      final WebPlugin webPlugin = plugin.platforms[WebPlugin.kConfigKey] as WebPlugin;
-      final WindowsPlugin windowsPlugin = plugin.platforms[WindowsPlugin.kConfigKey] as WindowsPlugin;
-      final String androidPluginClass = androidPlugin.pluginClass;
-      final String iosPluginClass = iosPlugin.pluginClass;
+    final AndroidPlugin androidPlugin = plugin.platforms[AndroidPlugin.kConfigKey] as AndroidPlugin;
+    final IOSPlugin iosPlugin = plugin.platforms[IOSPlugin.kConfigKey] as IOSPlugin;
+    final LinuxPlugin linuxPlugin = plugin.platforms[LinuxPlugin.kConfigKey] as LinuxPlugin;
+    final MacOSPlugin macOSPlugin = plugin.platforms[MacOSPlugin.kConfigKey] as MacOSPlugin;
+    final WebPlugin webPlugin = plugin.platforms[WebPlugin.kConfigKey] as WebPlugin;
+    final WindowsPlugin windowsPlugin = plugin.platforms[WindowsPlugin.kConfigKey] as WindowsPlugin;
+    final String androidPluginClass = androidPlugin.pluginClass;
+    final String iosPluginClass = iosPlugin.pluginClass;
 
-      expect(iosPluginClass, 'ISamplePlugin');
-      expect(androidPluginClass, 'ASamplePlugin');
-      expect(iosPlugin.classPrefix, '');
-      expect(androidPlugin.package, 'com.flutter.dev');
-      expect(linuxPlugin.pluginClass, 'LSamplePlugin');
-      expect(macOSPlugin.pluginClass, 'MSamplePlugin');
-      expect(webPlugin.pluginClass, 'WebSamplePlugin');
-      expect(webPlugin.fileName, 'web_plugin.dart');
-      expect(windowsPlugin.pluginClass, 'WinSamplePlugin');
-    });
+    expect(iosPluginClass, 'ISamplePlugin');
+    expect(androidPluginClass, 'ASamplePlugin');
+    expect(iosPlugin.classPrefix, '');
+    expect(androidPlugin.package, 'com.flutter.dev');
+    expect(linuxPlugin.pluginClass, 'LSamplePlugin');
+    expect(macOSPlugin.pluginClass, 'MSamplePlugin');
+    expect(webPlugin.pluginClass, 'WebSamplePlugin');
+    expect(webPlugin.fileName, 'web_plugin.dart');
+    expect(windowsPlugin.pluginClass, 'WinSamplePlugin');
+  });
 
-    test('Allow for Dart-only plugins without a pluginClass', () {
-      /// This is currently supported only on macOS, linux, Windows.
-      const String pluginYamlRaw = 'implements: same_plugin\n' // this should be ignored by the tool
-          'platforms:\n'
-          ' linux:\n'
-          '  dartPluginClass: LSamplePlugin\n'
-          ' macos:\n'
-          '  dartPluginClass: MSamplePlugin\n'
-          ' windows:\n'
-          '  dartPluginClass: WinSamplePlugin\n';
+  testWithoutContext('Plugin parsing allows for Dart-only plugins without a pluginClass', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    /// This is currently supported only on macOS, linux, Windows.
+    const String pluginYamlRaw = 'implements: same_plugin\n' // this should be ignored by the tool
+      'platforms:\n'
+      ' linux:\n'
+      '  dartPluginClass: LSamplePlugin\n'
+      ' macos:\n'
+      '  dartPluginClass: MSamplePlugin\n'
+      ' windows:\n'
+      '  dartPluginClass: WinSamplePlugin\n';
 
-      final dynamic pluginYaml = loadYaml(pluginYamlRaw);
-      final Plugin plugin =
-      Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml as YamlMap, const <String>[]);
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
+    final Plugin plugin = Plugin.fromYaml(
+      _kTestPluginName,
+      _kTestPluginPath,
+      pluginYaml,
+      const <String>[],
+      fileSystem: fileSystem,
+    );
 
-      final LinuxPlugin linuxPlugin = plugin.platforms[LinuxPlugin.kConfigKey] as LinuxPlugin;
-      final MacOSPlugin macOSPlugin = plugin.platforms[MacOSPlugin.kConfigKey] as MacOSPlugin;
-      final WindowsPlugin windowsPlugin = plugin.platforms[WindowsPlugin.kConfigKey] as WindowsPlugin;
+    final LinuxPlugin linuxPlugin = plugin.platforms[LinuxPlugin.kConfigKey] as LinuxPlugin;
+    final MacOSPlugin macOSPlugin = plugin.platforms[MacOSPlugin.kConfigKey] as MacOSPlugin;
+    final WindowsPlugin windowsPlugin = plugin.platforms[WindowsPlugin.kConfigKey] as WindowsPlugin;
 
-      expect(linuxPlugin.pluginClass, isNull);
-      expect(macOSPlugin.pluginClass, isNull);
-      expect(windowsPlugin.pluginClass, isNull);
-      expect(linuxPlugin.dartPluginClass, 'LSamplePlugin');
-      expect(macOSPlugin.dartPluginClass, 'MSamplePlugin');
-      expect(windowsPlugin.dartPluginClass, 'WinSamplePlugin');
-    });
+    expect(linuxPlugin.pluginClass, isNull);
+    expect(macOSPlugin.pluginClass, isNull);
+    expect(windowsPlugin.pluginClass, isNull);
+    expect(linuxPlugin.dartPluginClass, 'LSamplePlugin');
+    expect(macOSPlugin.dartPluginClass, 'MSamplePlugin');
+    expect(windowsPlugin.dartPluginClass, 'WinSamplePlugin');
+  });
 
-    test('Legacy Format and Multi-Platform Format together is not allowed and error message contains plugin name', () {
-      const String pluginYamlRaw = 'androidPackage: com.flutter.dev\n'
-          'platforms:\n'
-          ' android:\n'
-          '  package: com.flutter.dev\n';
+  testWithoutContext('Plugin parsing of legacy format and multi-platform format together is not allowed '
+    'and fatal error message contains plugin name', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    const String pluginYamlRaw = 'androidPackage: com.flutter.dev\n'
+      'platforms:\n'
+      ' android:\n'
+      '  package: com.flutter.dev\n';
 
-      final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
-      expect(
-        () => Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]),
-        throwsToolExit(message: _kTestPluginName),
-      );
-    });
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
 
-    test('A default_package field is allowed', () {
-      const String pluginYamlRaw =
-          'platforms:\n'
-          ' android:\n'
-          '  default_package: sample_package_android\n'
-          ' ios:\n'
-          '  default_package: sample_package_ios\n'
-          ' linux:\n'
-          '  default_package: sample_package_linux\n'
-          ' macos:\n'
-          '  default_package: sample_package_macos\n'
-          ' web:\n'
-          '  default_package: sample_package_web\n'
-          ' windows:\n'
-          '  default_package: sample_package_windows\n';
+    expect(
+     () => Plugin.fromYaml(
+        _kTestPluginName,
+        _kTestPluginPath,
+        pluginYaml,
+        const <String>[],
+        fileSystem: fileSystem,
+      ),
+      throwsToolExit(message: _kTestPluginName),
+    );
+  });
 
-      final dynamic pluginYaml = loadYaml(pluginYamlRaw);
-      final Plugin plugin =
-      Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml as YamlMap, const <String>[]);
+  testWithoutContext('Plugin parsing allows a default_package field', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    const String pluginYamlRaw =
+      'platforms:\n'
+      ' android:\n'
+      '  default_package: sample_package_android\n'
+      ' ios:\n'
+      '  default_package: sample_package_ios\n'
+      ' linux:\n'
+      '  default_package: sample_package_linux\n'
+      ' macos:\n'
+      '  default_package: sample_package_macos\n'
+      ' web:\n'
+      '  default_package: sample_package_web\n'
+      ' windows:\n'
+      '  default_package: sample_package_windows\n';
 
-      expect(plugin.platforms, <String, PluginPlatform> {});
-    });
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
+    final Plugin plugin = Plugin.fromYaml(
+      _kTestPluginName,
+      _kTestPluginPath,
+      pluginYaml,
+      const <String>[],
+      fileSystem: fileSystem,
+    );
 
-    test('error on empty plugin', () {
-      const String pluginYamlRaw = '';
+    expect(plugin.platforms, <String, PluginPlatform>{});
+  });
 
-      final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
-      expect(
-            () => Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]),
-        throwsToolExit(message: 'Invalid "plugin" specification.'),
-      );
-    });
+  testWithoutContext('Plugin parsing throws a fatal error on an empty plugin', () {
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    final YamlMap pluginYaml = loadYaml('') as YamlMap;
 
-    test('error on empty platforms', () {
-      const String pluginYamlRaw = 'platforms:\n';
+    expect(
+      () => Plugin.fromYaml(
+        _kTestPluginName,
+        _kTestPluginPath,
+        pluginYaml,
+        const <String>[],
+        fileSystem: fileSystem,
+      ),
+      throwsToolExit(message: 'Invalid "plugin" specification.'),
+    );
+  });
 
-      final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
-      expect(
-            () => Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]),
-        throwsToolExit(message: 'Invalid "platforms" specification.'),
-      );
-    });
+  testWithoutContext('Plugin parsing throws a fatal error on empty platforms', () {
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    const String pluginYamlRaw = 'platforms:\n';
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
 
-    test('error on empty platform', () {
-      const String pluginYamlRaw =
-          'platforms:\n'
-          ' android:\n';
+    expect(
+      () => Plugin.fromYaml(
+        _kTestPluginName,
+        _kTestPluginPath,
+        pluginYaml,
+        const <String>[],
+        fileSystem: fileSystem,
+      ),
+      throwsToolExit(message: 'Invalid "platforms" specification.'),
+    );
+  });
 
-      final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
-      expect(
-            () => Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]),
-        throwsToolExit(message: 'Invalid "android" plugin specification.'),
-      );
-    });
+  test('Plugin parsing throws a fatal error on an empty platform key', () {
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    const String pluginYamlRaw =
+      'platforms:\n'
+      ' android:\n';
+
+    final YamlMap pluginYaml = loadYaml(pluginYamlRaw) as YamlMap;
+    expect(
+      () => Plugin.fromYaml(
+        _kTestPluginName,
+        _kTestPluginPath,
+        pluginYaml,
+        const <String>[],
+        fileSystem: fileSystem,
+      ),
+      throwsToolExit(message: 'Invalid "android" plugin specification.'),
+    );
   });
 }