diff --git a/pkgs/io_file/test/copy_file_test.dart b/pkgs/io_file/test/copy_file_test.dart index b256ee6e..79b7aa93 100644 --- a/pkgs/io_file/test/copy_file_test.dart +++ b/pkgs/io_file/test/copy_file_test.dart @@ -20,322 +20,324 @@ import 'package:win32/win32.dart' as win32; import 'errors.dart' as errors; import 'fifo.dart'; +import 'file_system_file_utils.dart' hide fileUtils; import 'test_utils.dart'; -void main() { - group('copyFile', () { - late String tmp; - late String cwd; +void tests(FileUtils utils, FileSystem fs) { + late String tmp; + late String cwd; - setUp(() { - tmp = createTemp('copyFile'); - cwd = fileSystem.currentDirectory; - fileSystem.currentDirectory = tmp; - }); + setUp(() { + tmp = utils.createTestDirectory('createDirectory'); + cwd = fs.currentDirectory; + fs.currentDirectory = tmp; + }); + + tearDown(() { + fs.currentDirectory = cwd; + utils.deleteDirectoryTree(tmp); + }); - tearDown(() { - fileSystem.currentDirectory = cwd; - deleteTemp(tmp); + test('copy does not preserve source permissions', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils.createBinaryFile(oldPath, data); + + // Give "other users" write permissions. + using((arena) { + // rw-rw-rw- + if (libc.chmod(oldPath.toNativeUtf8(allocator: arena).cast(), 438) == + -1) { + assert(false, 'libc.errno: ${libc.errno}'); + } + final metadata = fs.metadata(oldPath); + assert((metadata as PosixMetadata).mode & libc.S_IWOTH != 0); }); - test('copy does not preserve source permissions', () { - final data = randomUint8List(1024); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(oldPath).writeAsBytesSync(data); - - // Give "other users" write permissions. - using((arena) { - // rw-rw-rw- - if (libc.chmod(oldPath.toNativeUtf8(allocator: arena).cast(), 438) == - -1) { - assert(false, 'libc.errno: ${libc.errno}'); - } - final metadata = fileSystem.metadata(oldPath); - assert((metadata as PosixMetadata).mode & libc.S_IWOTH != 0); - }); + fs.copyFile(oldPath, newPath); - fileSystem.copyFile(oldPath, newPath); + // Ensure that "other users" do not have write permissions on the copied + // file. + final metadata = fs.metadata(newPath); + expect((metadata as PosixMetadata).mode & libc.S_IWOTH, 0); + }, skip: fs is! PosixFileSystem); - // Ensure that "other users" do not have write permissions on the copied - // file. - final metadata = fileSystem.metadata(newPath); - expect((metadata as PosixMetadata).mode & libc.S_IWOTH, 0); - }, skip: io.Platform.isWindows); + test('copy does not preserve source file attributes', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils.createBinaryFile(oldPath, data); + (fs as WindowsFileSystem).setMetadata(oldPath, isReadOnly: true); + addTearDown(() => fs.setMetadata(oldPath, isReadOnly: false)); - test( - 'copy does not preserve source file attributes', - () { - final data = randomUint8List(1024); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(oldPath).writeAsBytesSync(data); - (fileSystem as WindowsFileSystem).setMetadata( - oldPath, - isReadOnly: true, - ); - - fileSystem.copyFile(oldPath, newPath); - - final metadata = fileSystem.metadata(newPath); - expect((metadata as WindowsMetadata).isReadOnly, isFalse); - }, - skip: !io.Platform.isWindows, - ); + fs.copyFile(oldPath, newPath); - test('copy file absolute path', () { - final data = randomUint8List(1024); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(oldPath).writeAsBytesSync(data); + final metadata = fs.metadata(newPath); + expect(metadata.isReadOnly, isFalse); + }, skip: fs is! WindowsFileSystem); - fileSystem.copyFile(oldPath, newPath); + test('copy file absolute path', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils.createBinaryFile(oldPath, data); - expect(io.File(newPath).readAsBytesSync(), data); - }); + fs.copyFile(oldPath, newPath); - test('copy between absolute paths, long file names', () { - final data = randomUint8List(1024); - final oldPath = p.join(tmp, '1' * 255); - final newPath = p.join(tmp, '2' * 255); - io.File(oldPath).writeAsBytesSync(data); + expect(utils.readBinaryFile(newPath), data); + }); - fileSystem.copyFile(oldPath, newPath); + test('copy between absolute paths, long file names', () { + final data = randomUint8List(1024); + final oldPath = p.join(tmp, '1' * 255); + final newPath = p.join(tmp, '2' * 255); + utils.createBinaryFile(oldPath, data); - expect(io.File(newPath).readAsBytesSync(), data); - }); + fs.copyFile(oldPath, newPath); - test('copy between relative path, long file names', () { - final data = randomUint8List(1024); - final oldPath = '1' * 255; - final newPath = '2' * 255; - io.File(oldPath).writeAsBytesSync(data); + expect(utils.readBinaryFile(newPath), data); + }); - fileSystem.copyFile(oldPath, newPath); + test('copy between relative path, long file names', () { + final data = randomUint8List(1024); + final oldPath = '1' * 255; + final newPath = '2' * 255; + utils.createBinaryFile(oldPath, data); - expect(io.File(newPath).readAsBytesSync(), data); - }); + fs.copyFile(oldPath, newPath); - test('copy directory', () { - final oldPath = '$tmp/dir1'; - final newPath = '$tmp/dir2'; - io.Directory(oldPath).createSync(); - - expect( - () => fileSystem.copyFile(oldPath, newPath), - throwsA( - isA() - .having((e) => e.path1, 'path1', oldPath) - .having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows - ? win32.ERROR_ACCESS_DENIED - : errors.eisdir, - ), - ), - ); - }); - - test('copy link', () { - final data = randomUint8List(1024); - final oldPath = '$tmp/link'; - final linkedFile = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(linkedFile).writeAsBytesSync(data); - io.Link(oldPath).createSync(linkedFile); + expect(utils.readBinaryFile(newPath), data); + }); - fileSystem.copyFile(oldPath, newPath); + test('copy directory', () { + final oldPath = '$tmp/dir1'; + final newPath = '$tmp/dir2'; + utils.createDirectory(oldPath); + + expect( + () => fs.copyFile(oldPath, newPath), + throwsA( + isA() + .having((e) => e.path1, 'path1', oldPath) + .having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows ? win32.ERROR_ACCESS_DENIED : errors.eisdir, + ), + ), + ); + }); - expect(io.File(newPath).readAsBytesSync(), data); - }); + test('copy link', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/link'; + final linkedFile = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils.createBinaryFile(linkedFile, data); + io.Link(oldPath).createSync(linkedFile); - test('copy file to existing file', () { - final data = randomUint8List(1024); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(oldPath).writeAsBytesSync(data); - io.File(newPath).writeAsStringSync('Hello World!'); - - expect( - () => fileSystem.copyFile(oldPath, newPath), - throwsA( - isA() - .having((e) => e.path1, 'path1', newPath) - .having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows ? win32.ERROR_FILE_EXISTS : errors.eexist, - ), - ), - ); - }); + fs.copyFile(oldPath, newPath); - test('copy file to existing link', () { - final data = randomUint8List(1024); - final oldPath = '$tmp/file1'; - final linkedFile = '$tmp/file2'; - final newPath = '$tmp/link'; - io.File(oldPath).writeAsBytesSync(data); - io.File(linkedFile).writeAsStringSync('Hello World'); - io.Link(newPath).createSync(linkedFile); - - expect( - () => fileSystem.copyFile(oldPath, newPath), - throwsA( - isA() - .having((e) => e.path1, 'path1', newPath) - .having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows ? win32.ERROR_FILE_EXISTS : errors.eexist, - ), - ), - ); - }); + expect(utils.readBinaryFile(newPath), data); + }); - test('copy to existing directory', () { - final data = randomUint8List(1024); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(oldPath).writeAsBytesSync(data); - io.Directory(newPath).createSync(); - - expect( - () => fileSystem.copyFile(oldPath, newPath), - throwsA( - isA() - .having((e) => e.path1, 'path1', newPath) - .having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows - ? win32.ERROR_ACCESS_DENIED - : errors.eexist, - ), - ), - ); - }); + test('copy file to existing file', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils + ..createBinaryFile(oldPath, data) + ..createTextFile(newPath, 'Hello World!'); + + expect( + () => fs.copyFile(oldPath, newPath), + throwsA( + isA() + .having((e) => e.path1, 'path1', newPath) + .having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows ? win32.ERROR_FILE_EXISTS : errors.eexist, + ), + ), + ); + }); - test('copy non-existent', () { - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; + test('copy file to existing link', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/file1'; + final linkedFile = '$tmp/file2'; + final newPath = '$tmp/link'; + utils + ..createBinaryFile(oldPath, data) + ..createTextFile(linkedFile, 'Hello World!'); + io.Link(newPath).createSync(linkedFile); + + expect( + () => fs.copyFile(oldPath, newPath), + throwsA( + isA() + .having((e) => e.path1, 'path1', newPath) + .having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows ? win32.ERROR_FILE_EXISTS : errors.eexist, + ), + ), + ); + }); - expect( - () => fileSystem.copyFile(oldPath, newPath), - throwsA( - isA() - .having((e) => e.path1, 'path1', oldPath) - .having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows - ? win32.ERROR_FILE_NOT_FOUND - : errors.enoent, - ), - ), - ); - }); + test('copy to existing directory', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils + ..createBinaryFile(oldPath, data) + ..createDirectory(newPath); + + expect( + () => fs.copyFile(oldPath, newPath), + throwsA( + isA() + .having((e) => e.path1, 'path1', newPath) + .having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows ? win32.ERROR_ACCESS_DENIED : errors.eexist, + ), + ), + ); + }); - test('copy to non-existent directory', () { - final data = randomUint8List(1024); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/foo/file2'; - io.File(oldPath).writeAsBytesSync(data); - - expect( - () => fileSystem.copyFile(oldPath, newPath), - throwsA( - isA() - .having((e) => e.path1, 'path1', newPath) - .having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows - ? win32.ERROR_PATH_NOT_FOUND - : errors.enoent, - ), - ), - ); - }); + test('copy non-existent', () { + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + + expect( + () => fs.copyFile(oldPath, newPath), + throwsA( + isA() + .having((e) => e.path1, 'path1', oldPath) + .having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows + ? win32.ERROR_FILE_NOT_FOUND + : errors.enoent, + ), + ), + ); + }); - group('fifo', () { - for (var i = 0; i <= 1024; ++i) { - test('Read small file: $i bytes', () async { - final data = randomUint8List(i); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - final fifo = - (await Fifo.create(oldPath)) - ..write(data) - ..close(); - - fileSystem.copyFile(fifo.path, newPath); - - expect(io.File(newPath).readAsBytesSync(), data); - }); - } + test('copy to non-existent directory', () { + final data = randomUint8List(1024); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/foo/file2'; + utils.createBinaryFile(oldPath, data); + + expect( + () => fs.copyFile(oldPath, newPath), + throwsA( + isA() + .having((e) => e.path1, 'path1', newPath) + .having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows + ? win32.ERROR_PATH_NOT_FOUND + : errors.enoent, + ), + ), + ); + }); - test('many single byte reads', () async { - final data = randomUint8List(20); + group('fifo', () { + for (var i = 0; i <= 1024; ++i) { + test('Read small file: $i bytes', () async { + final data = randomUint8List(i); final oldPath = '$tmp/file1'; final newPath = '$tmp/file2'; - final fifo = await Fifo.create(oldPath); - for (var byte in data) { - fifo - ..write(Uint8List(1)..[0] = byte) - ..delay(const Duration(milliseconds: 10)); - } - fifo.close(); + final fifo = + (await Fifo.create(oldPath)) + ..write(data) + ..close(); - fileSystem.copyFile(fifo.path, newPath); + fs.copyFile(fifo.path, newPath); - expect(io.File(newPath).readAsBytesSync(), data); + expect(utils.readBinaryFile(newPath), data); }); + } - for (var i = blockSize - 2; i <= blockSize + 2; ++i) { - test('Read close to `blockSize`: $i bytes', () async { - final data = randomUint8List(i); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - final fifo = - (await Fifo.create(oldPath)) - ..write(data) - ..close(); + test('many single byte reads', () async { + final data = randomUint8List(20); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + final fifo = await Fifo.create(oldPath); + for (var byte in data) { + fifo + ..write(Uint8List(1)..[0] = byte) + ..delay(const Duration(milliseconds: 10)); + } + fifo.close(); - fileSystem.copyFile(fifo.path, newPath); + fs.copyFile(fifo.path, newPath); - expect(io.File(newPath).readAsBytesSync(), data); - }); - } + expect(utils.readBinaryFile(newPath), data); }); - group('regular files', () { - for (var i = 0; i <= 1024; ++i) { - test('copyFile small file: $i bytes', () { - final data = randomUint8List(i); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(oldPath).writeAsBytesSync(data); + for (var i = blockSize - 2; i <= blockSize + 2; ++i) { + test('Read close to `blockSize`: $i bytes', () async { + final data = randomUint8List(i); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + final fifo = + (await Fifo.create(oldPath)) + ..write(data) + ..close(); - fileSystem.copyFile(oldPath, newPath); + fs.copyFile(fifo.path, newPath); - expect(io.File(newPath).readAsBytesSync(), data); - }); - } + expect(utils.readBinaryFile(newPath), data); + }); + } + }); - for (var i = blockSize - 2; i <= blockSize + 2; ++i) { - test('copyFile close to `blockSize`: $i bytes', () { - final data = randomUint8List(i); - final oldPath = '$tmp/file1'; - final newPath = '$tmp/file2'; - io.File(oldPath).writeAsBytesSync(data); + group('regular files', () { + for (var i = 0; i <= 1024; ++i) { + test('copyFile small file: $i bytes', () { + final data = randomUint8List(i); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils.createBinaryFile(oldPath, data); - fileSystem.copyFile(oldPath, newPath); + fs.copyFile(oldPath, newPath); - expect(io.File(newPath).readAsBytesSync(), data); - }); - } - }); + expect(utils.readBinaryFile(newPath), data); + }); + } + + for (var i = blockSize - 2; i <= blockSize + 2; ++i) { + test('copyFile close to `blockSize`: $i bytes', () { + final data = randomUint8List(i); + final oldPath = '$tmp/file1'; + final newPath = '$tmp/file2'; + utils.createBinaryFile(oldPath, data); + + fs.copyFile(oldPath, newPath); + + expect(utils.readBinaryFile(newPath), data); + }); + } + }); +} + +void main() { + group('copyFile', () { + group('dart:io verification', () => tests(fileUtils(), fileSystem)); + group( + 'self verification', + () => tests(FileSystemFileUtils(fileSystem), fileSystem), + ); }); } diff --git a/pkgs/io_file/test/create_directory_test.dart b/pkgs/io_file/test/create_directory_test.dart index 2410fc67..0e9770c6 100644 --- a/pkgs/io_file/test/create_directory_test.dart +++ b/pkgs/io_file/test/create_directory_test.dart @@ -21,14 +21,14 @@ void tests(FileUtils utils, FileSystem fs) { late String cwd; setUp(() { - tmp = createTemp('createDirectory'); + tmp = utils.createTestDirectory('createDirectory'); cwd = fs.currentDirectory; fs.currentDirectory = tmp; }); tearDown(() { fs.currentDirectory = cwd; - deleteTemp(tmp); + utils.deleteDirectoryTree(tmp); }); test('success', () { diff --git a/pkgs/io_file/test/create_temporary_directory_test.dart b/pkgs/io_file/test/create_temporary_directory_test.dart index 2e267e69..ff4979e1 100644 --- a/pkgs/io_file/test/create_temporary_directory_test.dart +++ b/pkgs/io_file/test/create_temporary_directory_test.dart @@ -13,181 +13,184 @@ import 'package:test/test.dart'; import 'package:win32/win32.dart' as win32; import 'errors.dart' as errors; +import 'file_system_file_utils.dart' hide fileUtils; import 'test_utils.dart'; -void main() { - group('createTemporaryDirectory', () { - late String tmp; - late String cwd; - - setUp(() { - tmp = createTemp('createTemporaryDirectory'); - cwd = fileSystem.currentDirectory; - fileSystem.currentDirectory = tmp; - }); - - tearDown(() { - fileSystem.currentDirectory = cwd; - deleteTemp(tmp); - }); - - test('no arguments', () { - final tmp1 = fileSystem.createTemporaryDirectory(); - addTearDown(() => io.Directory(tmp1).deleteSync()); - final tmp2 = fileSystem.createTemporaryDirectory(); - addTearDown(() => io.Directory(tmp2).deleteSync()); - - expect(fileSystem.same(tmp1, tmp2), isFalse); - expect(io.Directory(tmp1).existsSync(), isTrue); - expect(io.Directory(tmp2).existsSync(), isTrue); - }); - - test('prefix', () { - final tmp1 = fileSystem.createTemporaryDirectory(prefix: 'myprefix'); - addTearDown(() => io.Directory(tmp1).deleteSync()); - final tmp2 = fileSystem.createTemporaryDirectory(prefix: 'myprefix'); - addTearDown(() => io.Directory(tmp2).deleteSync()); - - expect(tmp1, contains('myprefix')); - expect(tmp2, contains('myprefix')); - expect(fileSystem.same(tmp1, tmp2), isFalse); - expect(io.Directory(tmp1).existsSync(), isTrue); - expect(io.Directory(tmp2).existsSync(), isTrue); - }); - - test('prefix is empty string', () { - final tmp1 = fileSystem.createTemporaryDirectory(prefix: ''); - addTearDown(() => io.Directory(tmp1).deleteSync()); - final tmp2 = fileSystem.createTemporaryDirectory(prefix: ''); - addTearDown(() => io.Directory(tmp2).deleteSync()); - - expect(fileSystem.same(tmp1, tmp2), isFalse); - expect(io.Directory(tmp1).existsSync(), isTrue); - expect(io.Directory(tmp2).existsSync(), isTrue); - }); - - test('prefix contains XXXXXX', () { - final tmp1 = fileSystem.createTemporaryDirectory( - prefix: 'myprefix-XXXXXX', - ); - addTearDown(() => io.Directory(tmp1).deleteSync()); - final tmp2 = fileSystem.createTemporaryDirectory( - prefix: 'myprefix-XXXXXX', - ); - addTearDown(() => io.Directory(tmp2).deleteSync()); - - expect(tmp1, contains('myprefix-')); - expect(tmp2, contains('myprefix-')); - expect(fileSystem.same(tmp1, tmp2), isFalse); - expect(io.Directory(tmp1).existsSync(), isTrue); - expect(io.Directory(tmp2).existsSync(), isTrue); - }); - - test('parent', () { - final tmp1 = fileSystem.createTemporaryDirectory(parent: tmp); - final tmp2 = fileSystem.createTemporaryDirectory(parent: tmp); - - expect(tmp1, startsWith(tmp)); - expect(tmp2, startsWith(tmp)); - expect(fileSystem.same(tmp1, tmp2), isFalse); - expect(io.Directory(tmp1).existsSync(), isTrue); - expect(io.Directory(tmp2).existsSync(), isTrue); - }); - - test('parent has a long directory name', () { - // On Windows: - // When using an API to create a directory, the specified path cannot be - // so long that you cannot append an 8.3 file name (that is, the directory - // name cannot exceed MAX_PATH minus 12). - final dirname = 'd' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255); - final parent = p.join(tmp, dirname); - io.Directory(parent).createSync(); - - final tmp1 = fileSystem.createTemporaryDirectory(parent: parent); - final tmp2 = fileSystem.createTemporaryDirectory(parent: parent); - - expect(tmp1, startsWith(tmp)); - expect(tmp2, startsWith(tmp)); - expect(fileSystem.same(tmp1, tmp2), isFalse); - expect(io.Directory(tmp1).existsSync(), isTrue); - expect(io.Directory(tmp2).existsSync(), isTrue); - }); - - test('parent is empty string', () { - final tmp1 = fileSystem.createTemporaryDirectory(parent: ''); - addTearDown(() => io.Directory(tmp1).deleteSync()); - final tmp2 = fileSystem.createTemporaryDirectory(parent: ''); - addTearDown(() => io.Directory(tmp2).deleteSync()); - - expect(p.isRelative(tmp1), isTrue); - expect(p.isRelative(tmp2), isTrue); - expect(fileSystem.same(tmp1, tmp2), isFalse); - expect(io.Directory(tmp1).existsSync(), isTrue); - expect(io.Directory(tmp2).existsSync(), isTrue); - }); - - test('parent does not exist', () { - expect( - () => fileSystem.createTemporaryDirectory(parent: '/foo/bar/baz'), - throwsA( - isA().having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows ? win32.ERROR_PATH_NOT_FOUND : errors.enoent, - ), +void tests(FileUtils utils, FileSystem fs) { + late String tmp; + late String cwd; + + setUp(() { + tmp = utils.createTestDirectory('createTemporaryDirectory'); + cwd = fs.currentDirectory; + fs.currentDirectory = tmp; + }); + + tearDown(() { + fs.currentDirectory = cwd; + utils.deleteDirectoryTree(tmp); + }); + + test('no arguments', () { + final tmp1 = fs.createTemporaryDirectory(); + addTearDown(() => utils.deleteDirectory(tmp1)); + final tmp2 = fs.createTemporaryDirectory(); + addTearDown(() => utils.deleteDirectory(tmp2)); + + expect(fs.same(tmp1, tmp2), isFalse); + expect(utils.isDirectory(tmp1), isTrue); + expect(utils.isDirectory(tmp2), isTrue); + }); + + test('prefix', () { + final tmp1 = fs.createTemporaryDirectory(prefix: 'myprefix'); + addTearDown(() => utils.deleteDirectory(tmp1)); + final tmp2 = fs.createTemporaryDirectory(prefix: 'myprefix'); + addTearDown(() => utils.deleteDirectory(tmp2)); + + expect(tmp1, contains('myprefix')); + expect(tmp2, contains('myprefix')); + expect(fs.same(tmp1, tmp2), isFalse); + expect(utils.isDirectory(tmp1), isTrue); + expect(utils.isDirectory(tmp2), isTrue); + }); + + test('prefix is empty string', () { + final tmp1 = fs.createTemporaryDirectory(prefix: ''); + addTearDown(() => utils.deleteDirectory(tmp1)); + final tmp2 = fs.createTemporaryDirectory(prefix: ''); + addTearDown(() => utils.deleteDirectory(tmp2)); + + expect(fs.same(tmp1, tmp2), isFalse); + expect(utils.isDirectory(tmp1), isTrue); + expect(utils.isDirectory(tmp2), isTrue); + }); + + test('prefix contains XXXXXX', () { + final tmp1 = fs.createTemporaryDirectory(prefix: 'myprefix-XXXXXX'); + addTearDown(() => utils.deleteDirectory(tmp1)); + final tmp2 = fs.createTemporaryDirectory(prefix: 'myprefix-XXXXXX'); + addTearDown(() => utils.deleteDirectory(tmp2)); + + expect(tmp1, contains('myprefix-')); + expect(tmp2, contains('myprefix-')); + expect(fs.same(tmp1, tmp2), isFalse); + expect(utils.isDirectory(tmp1), isTrue); + expect(utils.isDirectory(tmp2), isTrue); + }); + + test('parent', () { + final tmp1 = fs.createTemporaryDirectory(parent: tmp); + final tmp2 = fs.createTemporaryDirectory(parent: tmp); + + expect(tmp1, startsWith(tmp)); + expect(tmp2, startsWith(tmp)); + expect(fs.same(tmp1, tmp2), isFalse); + expect(utils.isDirectory(tmp1), isTrue); + expect(utils.isDirectory(tmp2), isTrue); + }); + + test('parent has a long directory name', () { + // On Windows: + // When using an API to create a directory, the specified path cannot be + // so long that you cannot append an 8.3 file name (that is, the directory + // name cannot exceed MAX_PATH minus 12). + final dirname = 'd' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255); + final parent = p.join(tmp, dirname); + utils.createDirectory(parent); + + final tmp1 = fs.createTemporaryDirectory(parent: parent); + final tmp2 = fs.createTemporaryDirectory(parent: parent); + + expect(tmp1, startsWith(tmp)); + expect(tmp2, startsWith(tmp)); + expect(fs.same(tmp1, tmp2), isFalse); + expect(utils.isDirectory(tmp1), isTrue); + expect(utils.isDirectory(tmp2), isTrue); + }); + + test('parent is empty string', () { + final tmp1 = fs.createTemporaryDirectory(parent: ''); + addTearDown(() => utils.deleteDirectory(tmp1)); + final tmp2 = fs.createTemporaryDirectory(parent: ''); + addTearDown(() => utils.deleteDirectory(tmp2)); + + expect(p.isRelative(tmp1), isTrue); + expect(p.isRelative(tmp2), isTrue); + expect(fs.same(tmp1, tmp2), isFalse); + expect(utils.isDirectory(tmp1), isTrue); + expect(utils.isDirectory(tmp2), isTrue); + }); + + test('parent does not exist', () { + expect( + () => fs.createTemporaryDirectory(parent: '/foo/bar/baz'), + throwsA( + isA().having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows ? win32.ERROR_PATH_NOT_FOUND : errors.enoent, ), - ); - }); - - test('prefix is absolute path inside of parent', () { - final subdir1 = '$tmp/dir1'; - io.Directory(subdir1).createSync(); - - final tmp1 = fileSystem.createTemporaryDirectory( - parent: subdir1, - prefix: '$subdir1/file', - ); - - expect(tmp1, startsWith(subdir1)); - }); - - test('prefix is absolute path outside of parent', () { - final subdir1 = '$tmp/dir1'; - final subdir2 = '$tmp/dir2'; - io.Directory(subdir1).createSync(); - io.Directory(subdir2).createSync(); - - final tmp1 = fileSystem.createTemporaryDirectory( - parent: subdir1, - prefix: '$subdir2/file', - ); - - expect(tmp1, startsWith(subdir2)); - }); - - test('prefix is non-existant path inside temp directory', () { - expect( - () => fileSystem.createTemporaryDirectory(prefix: 'subdir/file'), - throwsA( - isA().having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows ? win32.ERROR_PATH_NOT_FOUND : errors.enoent, - ), + ), + ); + }); + + test('prefix is absolute path inside of parent', () { + final subdir1 = '$tmp/dir1'; + utils.createDirectory(subdir1); + + final tmp1 = fs.createTemporaryDirectory( + parent: subdir1, + prefix: '$subdir1/file', + ); + + expect(tmp1, startsWith(subdir1)); + }); + + test('prefix is absolute path outside of parent', () { + final subdir1 = '$tmp/dir1'; + final subdir2 = '$tmp/dir2'; + utils + ..createDirectory(subdir1) + ..createDirectory(subdir2); + + final tmp1 = fs.createTemporaryDirectory( + parent: subdir1, + prefix: '$subdir2/file', + ); + + expect(tmp1, startsWith(subdir2)); + }); + + test('prefix is non-existant path inside temp directory', () { + expect( + () => fs.createTemporaryDirectory(prefix: 'subdir/file'), + throwsA( + isA().having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows ? win32.ERROR_PATH_NOT_FOUND : errors.enoent, ), - ); - }); - - test('prefix is existant path inside temp directory', () { - final subdir1 = '$tmp/dir1'; - io.Directory(subdir1).createSync(); - - final tmp1 = fileSystem.createTemporaryDirectory( - parent: tmp, - prefix: 'dir1/file', - ); - expect(p.canonicalize(tmp1), startsWith(p.canonicalize(subdir1))); - expect(io.Directory(tmp1).existsSync(), isTrue); - }); + ), + ); + }); + + test('prefix is existant path inside temp directory', () { + final subdir1 = '$tmp/dir1'; + utils.createDirectory(subdir1); + + final tmp1 = fs.createTemporaryDirectory(parent: tmp, prefix: 'dir1/file'); + expect(p.canonicalize(tmp1), startsWith(p.canonicalize(subdir1))); + expect(utils.isDirectory(tmp1), isTrue); + }); +} + +void main() { + group('createTemporaryDirectory', () { + group('dart:io verification', () => tests(fileUtils(), fileSystem)); + group( + 'self verification', + () => tests(FileSystemFileUtils(fileSystem), fileSystem), + ); }); } diff --git a/pkgs/io_file/test/current_directory_test.dart b/pkgs/io_file/test/current_directory_test.dart index 9482d033..2a6a6f14 100644 --- a/pkgs/io_file/test/current_directory_test.dart +++ b/pkgs/io_file/test/current_directory_test.dart @@ -8,87 +8,96 @@ library; import 'dart:io' as io; import 'package:io_file/io_file.dart'; +import 'package:io_file/windows_file_system.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; import 'package:win32/win32.dart' as win32; +import 'file_system_file_utils.dart' hide fileUtils; import 'test_utils.dart'; -void main() { - group('currentDirectory', () { - late String tmp; - late String cwd; +void tests(FileUtils utils, FileSystem fs) { + late String tmp; + late String cwd; - setUp(() { - tmp = createTemp('currentDirectory'); - cwd = fileSystem.currentDirectory; - fileSystem.currentDirectory = tmp; - }); + setUp(() { + tmp = utils.createTestDirectory('createDirectory'); + cwd = fs.currentDirectory; + fs.currentDirectory = tmp; + }); - tearDown(() { - fileSystem.currentDirectory = cwd; - deleteTemp(tmp); - }); + tearDown(() { + fs.currentDirectory = cwd; + utils.deleteDirectoryTree(tmp); + }); - test('absolute path', () { - final path = '$tmp/dir'; - io.Directory(path).createSync(recursive: true); + test('absolute path', () { + final path = '$tmp/dir'; + utils.createDirectory(path); + fs.currentDirectory = path; - fileSystem.currentDirectory = path; + expect( + fs.same(fs.currentDirectory, path), + isTrue, + reason: + '${fs.currentDirectory} is a diffent directory than' + '$path', + ); + expect( + p.isAbsolute(fs.currentDirectory), + isTrue, + reason: '${fs.currentDirectory} is not absolute', + ); + }); - expect( - fileSystem.same(fileSystem.currentDirectory, path), - isTrue, - reason: - '${fileSystem.currentDirectory} is a diffent directory than' - '$path', - ); - expect( - p.isAbsolute(fileSystem.currentDirectory), - isTrue, - reason: '${fileSystem.currentDirectory} is not absolute', - ); - }); + test('absolute path, too long path', () { + // On Windows, limited to MAX_PATH (260) characters. + final path = p.join(tmp, 'a' * 200, 'b' * 200); + io.Directory(path).createSync(recursive: true); + final oldCurrentDirectory = fs.currentDirectory; - test('absolute path, too long path', () { - // On Windows, limited to MAX_PATH (260) characters. - final path = p.join(tmp, 'a' * 200, 'b' * 200); - io.Directory(path).createSync(recursive: true); - final oldCurrentDirectory = fileSystem.currentDirectory; + expect( + () => fs.currentDirectory = path, + throwsA( + isA() + .having((e) => e.path1, 'path1', path) + .having( + (e) => e.errorCode, + 'errorCode', + win32.ERROR_FILENAME_EXCED_RANGE, + ), + ), + ); + expect(fs.currentDirectory, oldCurrentDirectory); + }, skip: fs is! WindowsFileSystem); - expect( - () => fileSystem.currentDirectory = path, - throwsA( - isA() - .having((e) => e.path1, 'path1', path) - .having( - (e) => e.errorCode, - 'errorCode', - win32.ERROR_FILENAME_EXCED_RANGE, - ), - ), - ); - expect(fileSystem.currentDirectory, oldCurrentDirectory); - }, skip: !io.Platform.isWindows); + test('relative path', () { + final path = '$tmp/dir'; + utils.createDirectory(path); - test('relative path', () { - final path = '$tmp/dir'; - io.Directory(path).createSync(recursive: true); + fs.currentDirectory = 'dir'; - fileSystem.currentDirectory = 'dir'; + expect( + fs.same(fs.currentDirectory, path), + isTrue, + reason: + '${fs.currentDirectory} is a diffent directory than ' + '$path', + ); + expect( + p.isAbsolute(fs.currentDirectory), + isTrue, + reason: '${fs.currentDirectory} is not absolute', + ); + }); +} - expect( - fileSystem.same(fileSystem.currentDirectory, path), - isTrue, - reason: - '${fileSystem.currentDirectory} is a diffent directory than ' - '$path', - ); - expect( - p.isAbsolute(fileSystem.currentDirectory), - isTrue, - reason: '${fileSystem.currentDirectory} is not absolute', - ); - }); +void main() { + group('currentDirectory', () { + group('dart:io verification', () => tests(fileUtils(), fileSystem)); + group( + 'self verification', + () => tests(FileSystemFileUtils(fileSystem), fileSystem), + ); }); } diff --git a/pkgs/io_file/test/dart_io_file_utils.dart b/pkgs/io_file/test/dart_io_file_utils.dart index c2fa6da3..ecb876db 100644 --- a/pkgs/io_file/test/dart_io_file_utils.dart +++ b/pkgs/io_file/test/dart_io_file_utils.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'dart:typed_data'; import 'test_utils.dart'; @@ -6,6 +7,10 @@ import 'test_utils.dart'; /// /// Used to verify `package:io_file` behavior against an external reference. class DartIOFileUtils implements FileUtils { + @override + void createBinaryFile(String path, Uint8List b) => + File(path).writeAsBytesSync(b); + @override String createTestDirectory(String testName) => Directory.systemTemp.createTempSync(testName).absolute.path; @@ -20,8 +25,14 @@ class DartIOFileUtils implements FileUtils { @override void createDirectory(String path) => Directory(path).createSync(); + @override + void deleteDirectory(String path) => Directory(path).deleteSync(); + @override void createTextFile(String path, String s) => File(path).writeAsStringSync(s); + + @override + Uint8List readBinaryFile(String path) => File(path).readAsBytesSync(); } FileUtils fileUtils() => DartIOFileUtils(); diff --git a/pkgs/io_file/test/file_system_file_utils.dart b/pkgs/io_file/test/file_system_file_utils.dart index 14125c7d..69b2b501 100644 --- a/pkgs/io_file/test/file_system_file_utils.dart +++ b/pkgs/io_file/test/file_system_file_utils.dart @@ -1,3 +1,5 @@ +import 'dart:typed_data'; + import 'package:io_file/io_file.dart'; import 'test_utils.dart'; @@ -11,11 +13,19 @@ class FileSystemFileUtils implements FileUtils { FileSystemFileUtils([FileSystem? fs]) : fs = fs ?? fileSystem; + @override + void createBinaryFile(String path, Uint8List b) => fs.writeAsBytes(path, b); + @override void createDirectory(String path) { fs.createDirectory(path); } + @override + void deleteDirectory(String path) { + // TODO: implement deleteDirectory + } + @override String createTestDirectory(String testName) => fs.createTemporaryDirectory(prefix: testName); @@ -32,6 +42,9 @@ class FileSystemFileUtils implements FileUtils { @override bool isDirectory(String path) => fs.metadata(path).isDirectory; + + @override + Uint8List readBinaryFile(String path) => fs.readAsBytes(path); } FileUtils fileUtils() => FileSystemFileUtils(); diff --git a/pkgs/io_file/test/metadata_apple_test.dart b/pkgs/io_file/test/metadata_apple_test.dart index 19cd2574..8d6d59a1 100644 --- a/pkgs/io_file/test/metadata_apple_test.dart +++ b/pkgs/io_file/test/metadata_apple_test.dart @@ -6,54 +6,62 @@ library; import 'dart:ffi'; -import 'dart:io'; import 'package:ffi/ffi.dart'; +import 'package:io_file/io_file.dart'; import 'package:io_file/src/vm_posix_file_system.dart'; import 'package:stdlibc/stdlibc.dart' as stdlibc; import 'package:test/test.dart'; +import 'file_system_file_utils.dart' hide fileUtils; import 'test_utils.dart'; @Native, Uint32)>(isLeaf: false) external int chflags(Pointer buf, int count); -void main() { - final posixFileSystem = PosixFileSystem(); +void tests(FileUtils utils, PosixFileSystem fs) { + late String tmp; + late String cwd; - group('apple metadata', () { - late String tmp; - late String cwd; + setUp(() { + tmp = utils.createTestDirectory('createDirectory'); + cwd = fs.currentDirectory; + fs.currentDirectory = tmp; + }); - setUp(() { - tmp = createTemp('createDirectory'); - cwd = posixFileSystem.currentDirectory; - posixFileSystem.currentDirectory = tmp; - }); + tearDown(() { + fs.currentDirectory = cwd; + utils.deleteDirectoryTree(tmp); + }); + test('false', () { + final path = '$tmp/file'; + utils.createTextFile(path, 'Hello World'); - tearDown(() { - posixFileSystem.currentDirectory = cwd; - deleteTemp(tmp); + final data = fs.metadata(path); + expect(data.isHidden, isFalse); + }); + test('true', () { + final path = '$tmp/file'; + utils.createTextFile(path, 'Hello World'); + using((arena) { + chflags(path.toNativeUtf8(), stdlibc.UF_HIDDEN); }); - group('isHidden', () { - test('false', () { - final path = '$tmp/file'; - File(path).writeAsStringSync('Hello World'); - - final data = posixFileSystem.metadata(path); - expect(data.isHidden, isFalse); - }); - test('true', () { - final path = '$tmp/file'; - File(path).writeAsStringSync('Hello World'); - using((arena) { - chflags(path.toNativeUtf8(), stdlibc.UF_HIDDEN); - }); - - final data = posixFileSystem.metadata(path); - expect(data.isHidden, isTrue); - }); - }); + final data = fs.metadata(path); + expect(data.isHidden, isTrue); + }); +} + +void main() { + group('apple metadata', () { + group( + 'dart:io verification', + () => tests(fileUtils(), fileSystem as PosixFileSystem), + ); + group( + 'self verification', + () => + tests(FileSystemFileUtils(fileSystem), fileSystem as PosixFileSystem), + ); }); } diff --git a/pkgs/io_file/test/metadata_test.dart b/pkgs/io_file/test/metadata_test.dart index b94f4a75..da17b583 100644 --- a/pkgs/io_file/test/metadata_test.dart +++ b/pkgs/io_file/test/metadata_test.dart @@ -14,209 +14,217 @@ import 'package:win32/win32.dart' as win32; import 'errors.dart' as errors; import 'fifo.dart'; +import 'file_system_file_utils.dart' hide fileUtils; import 'test_utils.dart'; -void main() { - group('metadata', () { - late String tmp; - late String cwd; - - setUp(() { - tmp = createTemp('createTemporaryDirectory'); - cwd = fileSystem.currentDirectory; - fileSystem.currentDirectory = tmp; - }); +void tests(FileUtils utils, FileSystem fs) { + late String tmp; + late String cwd; - tearDown(() { - fileSystem.currentDirectory = cwd; - deleteTemp(tmp); - }); + setUp(() { + tmp = utils.createTestDirectory('createDirectory'); + cwd = fs.currentDirectory; + fs.currentDirectory = tmp; + }); - test('path does not exist', () { - expect( - () => fileSystem.metadata('$tmp/file1'), - throwsA( - isA().having( - (e) => e.errorCode, - 'errorCode', - io.Platform.isWindows ? win32.ERROR_FILE_NOT_FOUND : errors.enoent, - ), + tearDown(() { + fs.currentDirectory = cwd; + utils.deleteDirectoryTree(tmp); + }); + test('path does not exist', () { + expect( + () => fs.metadata('$tmp/file1'), + throwsA( + isA().having( + (e) => e.errorCode, + 'errorCode', + io.Platform.isWindows ? win32.ERROR_FILE_NOT_FOUND : errors.enoent, ), - ); - }); - - test('absolute path, long name', () { - final path = p.join(tmp, 'f' * 255); - io.File(path).writeAsStringSync('Hello World'); - - final data = fileSystem.metadata(path); - expect(data.isFile, isTrue); - }); - - test('relative path, long name', () { - final path = 'f' * 255; - io.File(path).writeAsStringSync('Hello World'); - - final data = fileSystem.metadata(path); - expect(data.isFile, isTrue); - }); - - group('file types', () { - test('directory', () { - final data = fileSystem.metadata(tmp); - expect(data.isDirectory, isTrue); - expect(data.isFile, isFalse); - expect(data.isLink, isFalse); - expect(data.type, FileSystemType.directory); - }); - test( - 'tty', - () { - final data = fileSystem.metadata('/dev/tty'); - expect(data.isDirectory, isFalse); - expect(data.isFile, isFalse); - expect(data.isLink, isFalse); - expect(data.type, FileSystemType.character); - }, - skip: - !(io.Platform.isAndroid | - io.Platform.isIOS | - io.Platform.isLinux | - io.Platform.isIOS) - ? 'no /dev/tty' - : false, - ); - test('file', () { - final path = '$tmp/file1'; - io.File(path).writeAsStringSync('Hello World'); + ), + ); + }); - final data = fileSystem.metadata(path); - expect(data.isDirectory, isFalse); - expect(data.isFile, isTrue); - expect(data.isLink, isFalse); - expect(data.type, FileSystemType.file); - }); - test('fifo', () async { - final fifo = (await Fifo.create('$tmp/file'))..close(); + test('absolute path, long name', () { + final path = p.join(tmp, 'f' * 255); + utils.createTextFile(path, 'Hello World'); - final data = fileSystem.metadata(fifo.path); - expect(data.isDirectory, isFalse); - expect(data.isFile, isFalse); - expect(data.isLink, isFalse); - expect( - data.type, - io.Platform.isWindows ? FileSystemType.unknown : FileSystemType.pipe, - ); + final data = fs.metadata(path); + expect(data.isFile, isTrue); + }); - try { - // On Windows, opening the pipe consumes it. See: - // https://github.com/dotnet/runtime/issues/69604 - fileSystem.readAsBytes(fifo.path); - } catch (_) {} - }); - test('file link', () { - io.File('$tmp/file1').writeAsStringSync('Hello World'); - final path = '$tmp/link'; - io.Link(path).createSync('$tmp/file1'); + test('relative path, long name', () { + final path = 'f' * 255; + utils.createTextFile(path, 'Hello World'); - final data = fileSystem.metadata(path); - expect(data.isDirectory, isFalse); - expect(data.isFile, isFalse); - expect(data.isLink, isTrue); - expect(data.type, FileSystemType.link); - }); - test('directory link', () { - io.Directory('$tmp/dir').createSync(); - final path = '$tmp/link'; - io.Link(path).createSync('$tmp/dir'); + final data = fs.metadata(path); + expect(data.isFile, isTrue); + }); - final data = fileSystem.metadata(path); - expect(data.isDirectory, isFalse); - expect(data.isFile, isFalse); - expect(data.isLink, isTrue); - expect(data.type, FileSystemType.link); - }); + group('file types', () { + test('directory', () { + final data = fs.metadata(tmp); + expect(data.isDirectory, isTrue); + expect(data.isFile, isFalse); + expect(data.isLink, isFalse); + expect(data.type, FileSystemType.directory); }); - test( - 'isHidden', + 'tty', () { - // Tested on iOS/macOS at: metadata_apple_test.dart - // Tested on Windows at: metadata_windows_test.dart - - final path = '$tmp/file1'; - io.File(path).writeAsStringSync('Hello World!'); - - final data = fileSystem.metadata(path); - expect(data.isHidden, isNull); + final data = fs.metadata('/dev/tty'); + expect(data.isDirectory, isFalse); + expect(data.isFile, isFalse); + expect(data.isLink, isFalse); + expect(data.type, FileSystemType.character); }, skip: - (io.Platform.isIOS || io.Platform.isMacOS || io.Platform.isWindows) - ? 'does not support hidden file metadata' + !(io.Platform.isAndroid | + io.Platform.isIOS | + io.Platform.isLinux | + io.Platform.isIOS) + ? 'no /dev/tty' : false, ); - group('size', () { - test('empty file', () { - final path = '$tmp/file1'; - io.File(path).writeAsStringSync(''); + test('file', () { + final path = '$tmp/file1'; + utils.createTextFile(path, 'Hello World'); - final data = fileSystem.metadata(path); - expect(data.size, 0); - }); - test('non-empty file', () { - final path = '$tmp/file1'; - io.File(path).writeAsStringSync('Hello World!'); + final data = fs.metadata(path); + expect(data.isDirectory, isFalse); + expect(data.isFile, isTrue); + expect(data.isLink, isFalse); + expect(data.type, FileSystemType.file); + }); + test('fifo', () async { + final fifo = (await Fifo.create('$tmp/file'))..close(); - final data = fileSystem.metadata(path); - expect(data.size, 12); - }); + final data = fs.metadata(fifo.path); + expect(data.isDirectory, isFalse); + expect(data.isFile, isFalse); + expect(data.isLink, isFalse); + expect( + data.type, + io.Platform.isWindows ? FileSystemType.unknown : FileSystemType.pipe, + ); + + try { + // On Windows, opening the pipe consumes it. See: + // https://github.com/dotnet/runtime/issues/69604 + fs.readAsBytes(fifo.path); + } catch (_) {} }); + test('file link', () { + utils.createTextFile('$tmp/file1', 'Hello World'); + final path = '$tmp/link'; + io.Link(path).createSync('$tmp/file1'); + + final data = fs.metadata(path); + expect(data.isDirectory, isFalse); + expect(data.isFile, isFalse); + expect(data.isLink, isTrue); + expect(data.type, FileSystemType.link); + }); + test('directory link', () { + io.Directory('$tmp/dir').createSync(); + final path = '$tmp/link'; + io.Link(path).createSync('$tmp/dir'); + + final data = fs.metadata(path); + expect(data.isDirectory, isFalse); + expect(data.isFile, isFalse); + expect(data.isLink, isTrue); + expect(data.type, FileSystemType.link); + }); + }); - group( - 'creation', - () { - test('newly created', () { - final path = '$tmp/file1'; - io.File(path).writeAsStringSync(''); - - final data = fileSystem.metadata(path); - expect( - data.creation!.millisecondsSinceEpoch, - closeTo(DateTime.now().millisecondsSinceEpoch, 5000), - ); - }); - }, - skip: - !(io.Platform.isIOS || io.Platform.isMacOS || io.Platform.isWindows) - ? 'creation not supported' - : false, - ); + test( + 'isHidden', + () { + // Tested on iOS/macOS at: metadata_apple_test.dart + // Tested on Windows at: metadata_windows_test.dart + + final path = '$tmp/file1'; + io.File(path).writeAsStringSync('Hello World!'); + + final data = fs.metadata(path); + expect(data.isHidden, isNull); + }, + skip: + (io.Platform.isIOS || io.Platform.isMacOS || io.Platform.isWindows) + ? 'does not support hidden file metadata' + : false, + ); + group('size', () { + test('empty file', () { + final path = '$tmp/file1'; + io.File(path).writeAsStringSync(''); + + final data = fs.metadata(path); + expect(data.size, 0); + }); + test('non-empty file', () { + final path = '$tmp/file1'; + io.File(path).writeAsStringSync('Hello World!'); + + final data = fs.metadata(path); + expect(data.size, 12); + }); + }); - group('modification', () { + group( + 'creation', + () { test('newly created', () { final path = '$tmp/file1'; - io.File(path).writeAsStringSync('Hello World!'); + io.File(path).writeAsStringSync(''); - final data = fileSystem.metadata(path); + final data = fs.metadata(path); expect( - data.modification.millisecondsSinceEpoch, + data.creation!.millisecondsSinceEpoch, closeTo(DateTime.now().millisecondsSinceEpoch, 5000), ); }); - test('modified after creation', () async { - final path = '$tmp/file1'; - io.File(path).writeAsStringSync('Hello World!'); - final data1 = fileSystem.metadata(path); + }, + skip: + !(io.Platform.isIOS || io.Platform.isMacOS || io.Platform.isWindows) + ? 'creation not supported' + : false, + ); + + group('modification', () { + test('newly created', () { + final path = '$tmp/file1'; + io.File(path).writeAsStringSync('Hello World!'); + + final data = fs.metadata(path); + expect( + data.modification.millisecondsSinceEpoch, + closeTo(DateTime.now().millisecondsSinceEpoch, 5000), + ); + }); + test('modified after creation', () async { + final path = '$tmp/file1'; + io.File(path).writeAsStringSync('Hello World!'); + final data1 = fs.metadata(path); - await Future.delayed(const Duration(milliseconds: 1000)); - io.File(path).writeAsStringSync('Hello World!'); - final data2 = fileSystem.metadata(path); + await Future.delayed(const Duration(milliseconds: 1000)); + io.File(path).writeAsStringSync('Hello World!'); + final data2 = fs.metadata(path); - expect( - data2.modification.millisecondsSinceEpoch, - greaterThan(data1.modification.millisecondsSinceEpoch), - ); - }); + expect( + data2.modification.millisecondsSinceEpoch, + greaterThan(data1.modification.millisecondsSinceEpoch), + ); }); }); } + +void main() { + group('metadata', () { + group('dart:io verification', () => tests(fileUtils(), fileSystem)); + group( + 'self verification', + () => tests(FileSystemFileUtils(fileSystem), fileSystem), + ); + }); +} diff --git a/pkgs/io_file/test/test_utils.dart b/pkgs/io_file/test/test_utils.dart index 90a03fa6..f621f9eb 100644 --- a/pkgs/io_file/test/test_utils.dart +++ b/pkgs/io_file/test/test_utils.dart @@ -30,6 +30,10 @@ abstract interface class FileUtils { bool isDirectory(String path); void createDirectory(String path); + void deleteDirectory(String path); void createTextFile(String path, String s); + void createBinaryFile(String path, Uint8List b); + + Uint8List readBinaryFile(String path); }