Migrate tests to sound mode, fix type error in MemoryDirectory (#180)

diff --git a/packages/file/CHANGELOG.md b/packages/file/CHANGELOG.md
index a8a9547..4537832 100644
--- a/packages/file/CHANGELOG.md
+++ b/packages/file/CHANGELOG.md
@@ -1,3 +1,7 @@
+#### 6.0.1
+
+* Fix sound type error in memory backend when reading non-existent `MemoryDirectory`.
+
 #### 6.0.0
 
 * First stable null safe release.
diff --git a/packages/file/lib/src/backends/memory/memory_directory.dart b/packages/file/lib/src/backends/memory/memory_directory.dart
index 63e40d2..6b11263 100644
--- a/packages/file/lib/src/backends/memory/memory_directory.dart
+++ b/packages/file/lib/src/backends/memory/memory_directory.dart
@@ -73,9 +73,9 @@
     String fullPath = fileSystem.path.join(path, prefix);
     String dirname = fileSystem.path.dirname(fullPath);
     String basename = fileSystem.path.basename(fullPath);
-    DirectoryNode node = fileSystem.findNode(dirname) as DirectoryNode;
+    DirectoryNode? node = fileSystem.findNode(dirname) as DirectoryNode?;
     checkExists(node, () => dirname);
-    utils.checkIsDir(node, () => dirname);
+    utils.checkIsDir(node!, () => dirname);
     int _tempCounter = _systemTempCounter[fileSystem] ?? 0;
     String name() => '$basename$_tempCounter';
     while (node.children.containsKey(name())) {
diff --git a/packages/file/pubspec.yaml b/packages/file/pubspec.yaml
index 2498dd1..f7485f1 100644
--- a/packages/file/pubspec.yaml
+++ b/packages/file/pubspec.yaml
@@ -1,5 +1,5 @@
 name: file
-version: 6.0.0
+version: 6.0.1
 description:
   A pluggable, mockable file system abstraction for Dart. Supports local file
   system access, as well as in-memory file systems, record-replay file systems,
@@ -14,5 +14,5 @@
   path: ^1.8.0
 
 dev_dependencies:
-  file_testing: '>=2.0.0 <3.0.0'
-  test: '^1.16.0-nullsafety.8'
+  file_testing: '>=3.0.0 <4.0.0'
+  test: '^1.16.0'
diff --git a/packages/file/test/chroot_test.dart b/packages/file/test/chroot_test.dart
index 6efd7bb..6c34ff2 100644
--- a/packages/file/test/chroot_test.dart
+++ b/packages/file/test/chroot_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.8
 @TestOn('vm')
 import 'dart:io' as io;
 
@@ -35,8 +34,8 @@
     });
 
     group('localBacked', () {
-      ChrootFileSystem fs;
-      io.Directory tmp;
+      late ChrootFileSystem fs;
+      late io.Directory tmp;
 
       setUp(() {
         tmp = io.Directory.systemTemp.createTempSync('file_test_');
@@ -63,8 +62,8 @@
     }, skip: io.Platform.isWindows);
 
     group('chrootSpecific', () {
-      ChrootFileSystem fs;
-      MemoryFileSystem mem;
+      late ChrootFileSystem fs;
+      late MemoryFileSystem mem;
 
       setUp(() {
         fs = createMemoryBackedChrootFileSystem();
diff --git a/packages/file/test/common_tests.dart b/packages/file/test/common_tests.dart
index b60f1f2..207c082 100644
--- a/packages/file/test/common_tests.dart
+++ b/packages/file/test/common_tests.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.8
 @TestOn('vm')
 import 'dart:async';
 import 'dart:convert';
@@ -51,19 +50,18 @@
 /// the invocation(s) must first be made.
 void runCommonTests(
   FileSystemGenerator createFileSystem, {
-  RootPathGenerator root,
+  RootPathGenerator? root,
   List<String> skip = const <String>[],
-  FileSystemGenerator replay,
+  FileSystemGenerator? replay,
 }) {
-  RootPathGenerator rootfn = root;
+  RootPathGenerator? rootfn = root;
 
   group('common', () {
-    FileSystemGenerator createFs;
-    List<SetUpTearDown> setUps;
-    List<SetUpTearDown> tearDowns;
-    FileSystem fs;
-    String root;
-
+    late FileSystemGenerator createFs;
+    late List<SetUpTearDown> setUps;
+    late List<SetUpTearDown> tearDowns;
+    late FileSystem fs;
+    late String root;
     List<String> stack = <String>[];
 
     void skipIfNecessary(String description, void callback()) {
@@ -80,8 +78,6 @@
       createFs = createFileSystem;
       setUps = <SetUpTearDown>[];
       tearDowns = <SetUpTearDown>[];
-      fs = null;
-      root = null;
     });
 
     void setUp(FutureOr<void> callback()) {
@@ -990,7 +986,7 @@
       });
 
       group('parent', () {
-        String root;
+        late String root;
 
         setUp(() {
           root = fs.path.style.name == 'windows' ? r'C:\' : '/';
@@ -1052,7 +1048,7 @@
       });
 
       group('list', () {
-        Directory dir;
+        late Directory dir;
 
         setUp(() {
           dir = fs.currentDirectory = fs.directory(ns('/foo'))..createSync();
@@ -1722,8 +1718,8 @@
 
         void testRandomAccessFileOperations(FileMode mode) {
           group('RandomAccessFile', () {
-            File f;
-            RandomAccessFile raf;
+            late File f;
+            late RandomAccessFile raf;
 
             setUp(() {
               f = fs.file(ns('/foo'))..createSync();
@@ -1805,7 +1801,7 @@
 
               test('throwsIfReadInto', () {
                 expectFileSystemException(ErrorCodes.EBADF, () {
-                  raf.readIntoSync(List<int>(5));
+                  raf.readIntoSync(List<int>.filled(5, 0));
                 });
               });
             } else {
@@ -1830,7 +1826,7 @@
                 });
 
                 test('readIntoWithBufferLargerThanContent', () {
-                  List<int> buffer = List<int>(1024);
+                  List<int> buffer = List<int>.filled(1024, 0);
                   int numRead = raf.readIntoSync(buffer);
                   expect(numRead, 21);
                   expect(utf8.decode(buffer.sublist(0, 21)),
@@ -1838,21 +1834,21 @@
                 });
 
                 test('readIntoWithBufferSmallerThanContent', () {
-                  List<int> buffer = List<int>(10);
+                  List<int> buffer = List<int>.filled(10, 0);
                   int numRead = raf.readIntoSync(buffer);
                   expect(numRead, 10);
                   expect(utf8.decode(buffer), 'pre-existi');
                 });
 
                 test('readIntoWithStart', () {
-                  List<int> buffer = List<int>(10);
+                  List<int> buffer = List<int>.filled(10, 0);
                   int numRead = raf.readIntoSync(buffer, 2);
                   expect(numRead, 8);
                   expect(utf8.decode(buffer.sublist(2)), 'pre-exis');
                 });
 
                 test('readIntoWithStartAndEnd', () {
-                  List<int> buffer = List<int>(10);
+                  List<int> buffer = List<int>.filled(10, 0);
                   int numRead = raf.readIntoSync(buffer, 2, 5);
                   expect(numRead, 3);
                   expect(utf8.decode(buffer.sublist(2, 5)), 'pre');
@@ -2201,8 +2197,8 @@
           f.writeAsBytesSync(data, flush: true);
           final Stream<List<int>> stream = f.openRead();
 
-          File newFile;
-          List<int> initialChunk;
+          File? newFile;
+          List<int>? initialChunk;
           final List<int> remainingChunks = <int>[];
 
           await for (List<int> chunk in stream) {
@@ -2219,10 +2215,10 @@
 
           expect(
             remainingChunks,
-            data.getRange(initialChunk.length, data.length),
+            data.getRange(initialChunk!.length, data.length),
           );
 
-          assert(newFile.path != f.path);
+          assert(newFile?.path != f.path);
           expect(f, isNot(exists));
           expect(newFile, exists);
         });
@@ -2310,9 +2306,9 @@
         });
 
         group('ioSink', () {
-          File f;
-          IOSink sink;
-          bool isSinkClosed;
+          late File f;
+          late IOSink sink;
+          late bool isSinkClosed;
 
           Future<dynamic> closeSink() {
             Future<dynamic> future = sink.close();
@@ -2338,11 +2334,6 @@
             isSinkClosed = true;
           });
 
-          test('throwsIfEncodingIsNullAndWriteObject', () async {
-            sink.encoding = null;
-            expect(() => sink.write('Hello world'), throwsNoSuchMethodError);
-          });
-
           test('allowsChangingEncoding', () async {
             sink.encoding = latin1;
             sink.write('ÿ');
@@ -2408,8 +2399,8 @@
           });
 
           group('addStream', () {
-            StreamController<List<int>> controller;
-            bool isControllerClosed;
+            late StreamController<List<int>> controller;
+            late bool isControllerClosed;
 
             Future<dynamic> closeController() {
               Future<dynamic> future = controller.close();
@@ -2552,13 +2543,6 @@
           File f = fs.file(ns('/foo'))..createSync();
           expect(f.readAsStringSync(), isEmpty);
         });
-
-        test('throwsIfEncodingIsNull', () {
-          File f = fs.file(ns('/foo'))..createSync();
-          f.writeAsStringSync('Hello world');
-          expect(() => f.readAsStringSync(encoding: null),
-              throwsNoSuchMethodError);
-        });
       });
 
       group('readAsLines', () {
@@ -2756,12 +2740,6 @@
           f.writeAsStringSync('');
           expect(f.readAsStringSync(), isEmpty);
         });
-
-        test('throwsIfNullEncoding', () {
-          File f = fs.file(ns('/foo'))..createSync();
-          expect(() => f.writeAsStringSync('Hello world', encoding: null),
-              throwsNoSuchMethodError);
-        });
       });
 
       group('exists', () {