[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); + }); +}