[path] Fix test race condition caused by changing Directory.current (#890)

diff --git a/pkgs/path/test/io_test.dart b/pkgs/path/test/io_test.dart
index e428b89..fa33ab9 100644
--- a/pkgs/path/test/io_test.dart
+++ b/pkgs/path/test/io_test.dart
@@ -43,81 +43,81 @@
 
     test(
       'uses the previous working directory if deleted',
-      () {
-        final dir = io.Directory.current.path;
-        try {
-          final temp = io.Directory.systemTemp.createTempSync('path_test');
-          final tempPath = temp.resolveSymbolicLinksSync();
-          io.Directory.current = temp;
+      withLocalCurrentDirectory(() {
+        final temp = io.Directory.systemTemp.createTempSync('path_test');
+        final tempPath = temp.resolveSymbolicLinksSync();
+        io.Directory.current = temp;
 
-          // Call "current" once so that it can be cached.
-          expect(path.normalize(path.absolute(path.current)), equals(tempPath));
+        // Call "current" once so that it can be cached.
+        expect(path.normalize(path.absolute(path.current)), equals(tempPath));
 
-          temp.deleteSync();
+        temp.deleteSync();
 
-          // Even though the directory no longer exists, no exception is thrown.
-          expect(path.normalize(path.absolute(path.current)), equals(tempPath));
-        } finally {
-          io.Directory.current = dir;
-        }
-      },
+        // Even though the directory no longer exists, no exception is thrown.
+        expect(path.normalize(path.absolute(path.current)), equals(tempPath));
+      }),
       //TODO: Figure out why this is failing on windows and fix!
       skip: io.Platform.isWindows ? 'Untriaged failure on Windows' : false,
     );
   });
 
-  test('registers changes to the working directory', () {
+  test('registers changes to the working directory',
+      withLocalCurrentDirectory(() {
     final dir = io.Directory.current.path;
-    try {
-      expect(path.absolute('foo/bar'), equals(path.join(dir, 'foo/bar')));
-      expect(
-        path.absolute('foo/bar'),
-        equals(path.context.join(dir, 'foo/bar')),
-      );
+    expect(path.absolute('foo/bar'), equals(path.join(dir, 'foo/bar')));
+    expect(
+      path.absolute('foo/bar'),
+      equals(path.context.join(dir, 'foo/bar')),
+    );
 
-      io.Directory.current = path.dirname(dir);
-      expect(
-        path.normalize(path.absolute('foo/bar')),
-        equals(path.normalize(path.join(dir, '../foo/bar'))),
-      );
-      expect(
-        path.normalize(path.absolute('foo/bar')),
-        equals(path.normalize(path.context.join(dir, '../foo/bar'))),
-      );
-    } finally {
-      io.Directory.current = dir;
-    }
-  });
+    io.Directory.current = path.dirname(dir);
+    expect(
+      path.normalize(path.absolute('foo/bar')),
+      equals(path.normalize(path.join(dir, '../foo/bar'))),
+    );
+    expect(
+      path.normalize(path.absolute('foo/bar')),
+      equals(path.normalize(path.context.join(dir, '../foo/bar'))),
+    );
+  }));
 
   // Regression test for #35. This tests against the *actual* working directory
   // rather than just a custom context because we do some processing in
   // [path.current] that has clobbered the root in the past.
   test(
     'absolute works on root working directory',
-    () {
-      final dir = path.current;
-      try {
-        io.Directory.current = path.rootPrefix(path.current);
+    withLocalCurrentDirectory(() {
+      io.Directory.current = path.rootPrefix(path.current);
 
-        expect(
-          path.relative(path.absolute('foo/bar'), from: path.current),
-          path.relative(path.absolute('foo/bar')),
-        );
+      expect(
+        path.relative(path.absolute('foo/bar'), from: path.current),
+        path.relative(path.absolute('foo/bar')),
+      );
 
-        expect(
-          path.normalize(path.absolute('foo/bar')),
-          equals(path.normalize(path.join(path.current, '../foo/bar'))),
-        );
+      expect(
+        path.normalize(path.absolute('foo/bar')),
+        equals(path.normalize(path.join(path.current, '../foo/bar'))),
+      );
 
-        expect(
-          path.normalize(path.absolute('foo/bar')),
-          equals(path.normalize(path.join(path.current, '../foo/bar'))),
-        );
-      } finally {
-        io.Directory.current = dir;
-      }
-    },
+      expect(
+        path.normalize(path.absolute('foo/bar')),
+        equals(path.normalize(path.join(path.current, '../foo/bar'))),
+      );
+    }),
     //TODO(kevmoo): figure out why this is failing on windows and fix!
     skip: io.Platform.isWindows ? 'Untriaged failure on Windows' : null,
   );
 }
+
+/// Runs [body] in a zone with a local current working directory.
+///
+/// Avoids clobbering the current working directory of the entire process
+/// when writing to it and reading it back through `dart:io` functions.
+R Function() withLocalCurrentDirectory<R>(R Function() body) {
+  var savedCurrentDirectory = io.Directory.current;
+  return () => io.IOOverrides.runZoned(body,
+      getCurrentDirectory: () => savedCurrentDirectory,
+      setCurrentDirectory: (dir) {
+        savedCurrentDirectory = io.Directory(dir);
+      });
+}