// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // 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. // // Directory listing test. import "dart:async"; import "dart:io"; import "package:async_helper/async_helper.dart"; import "package:expect/expect.dart"; class DirectoryTest { static void testListing() { bool listedDir = false; bool listedFile = false; Directory directory = Directory.systemTemp.createTempSync('dart_directory_test'); Directory subDirectory = new Directory("${directory.path}/subdir"); Expect.isTrue('$directory'.contains(directory.path)); Expect.isFalse(subDirectory.existsSync()); subDirectory.createSync(); Expect.isTrue(subDirectory.existsSync()); File f = new File('${subDirectory.path}/file.txt'); File fLong = new File('${directory.path}/subdir/../subdir/file.txt'); Expect.isFalse(f.existsSync()); f.createSync(); void testSyncListing(bool recursive) { for (var entry in directory.listSync(recursive: recursive)) { if (entry is File) { Expect.isTrue(entry.path.contains(directory.path)); Expect.isTrue(entry.path.contains('subdir')); Expect.isTrue(entry.path.contains('file.txt')); Expect.isFalse(listedFile); listedFile = true; } else { Expect.isTrue(entry is Directory); Expect.isTrue(entry.path.contains(directory.path)); Expect.isTrue(entry.path.contains('subdir')); Expect.isFalse(listedDir); listedDir = true; } } Expect.equals(listedFile, recursive); Expect.isTrue(listedDir); listedFile = false; listedDir = false; } testSyncListing(true); testSyncListing(false); Expect.equals( f.resolveSymbolicLinksSync(), fLong.resolveSymbolicLinksSync()); asyncStart(); directory.list(recursive: true).listen((FileSystemEntity entity) { if (entity is File) { var path = entity.path; listedFile = true; Expect.isTrue(path.contains(directory.path)); Expect.isTrue(path.contains('subdir')); Expect.isTrue(path.contains('file.txt')); } else { var path = entity.path; Expect.isTrue(entity is Directory); listedDir = true; Expect.isTrue(path.contains(directory.path)); Expect.isTrue(path.contains('subdir')); } }, onDone: () { Expect.isTrue(listedDir, "directory not found"); Expect.isTrue(listedFile, "file not found"); directory.delete(recursive: true).then((ignore) { f.exists().then((exists) => Expect.isFalse(exists)); directory.exists().then((exists) => Expect.isFalse(exists)); subDirectory.exists().then((exists) => Expect.isFalse(exists)); asyncEnd(); }); }); // Listing is asynchronous, so nothing should be listed at this // point. Expect.isFalse(listedDir); Expect.isFalse(listedFile); } static void testListingTailingPaths() { Directory directory = Directory.systemTemp.createTempSync('dart_directory_test'); Directory subDirectory = new Directory("${directory.path}/subdir/"); subDirectory.createSync(); File f = new File('${subDirectory.path}/file.txt'); f.createSync(); void test(entry) { Expect.isFalse(entry.path.contains(new RegExp('[\\/][\\/]'))); } subDirectory.listSync().forEach(test); subDirectory.list().listen(test, onDone: () { directory.deleteSync(recursive: true); }); } static void testListNonExistent() { setupListerHandlers(Stream stream) { stream.listen( (_) => Expect.fail("Listing of non-existing directory should fail"), onError: (error) { Expect.isTrue(error is FileSystemException); }); } Directory.systemTemp.createTemp('dart_directory').then((d) { d.delete().then((ignore) { setupListerHandlers(d.list()); setupListerHandlers(d.list(recursive: true)); }); }); } static void testListTooLongName() { asyncStart(); Directory.systemTemp.createTemp('dart_directory').then((d) { var errors = 0; setupListHandlers(Stream stream) { stream.listen( (_) => Expect.fail("Listing of non-existing directory should fail"), onError: (error) { Expect.isTrue(error is FileSystemException); if (++errors == 2) { d.delete(recursive: true).then((_) { asyncEnd(); }); } }); } var subDirName = 'subdir'; var subDir = new Directory("${d.path}/$subDirName"); subDir.create().then((ignore) { // Construct a long string of the form // 'tempdir/subdir/../subdir/../subdir'. var buffer = new StringBuffer(); buffer.write(subDir.path); for (var i = 0; i < 1000; i++) { buffer.write("/../${subDirName}"); } var long = new Directory("${buffer.toString()}"); setupListHandlers(long.list()); setupListHandlers(long.list(recursive: true)); }); }); } static void testDeleteNonExistent() { // Test that deleting a non-existing directory fails. setupFutureHandlers(future) { future.then((ignore) { Expect.fail("Deletion of non-existing directory should fail"); }).catchError((error) { Expect.isTrue(error is FileSystemException); }); } Directory.systemTemp.createTemp('dart_directory').then((d) { d.delete().then((ignore) { setupFutureHandlers(d.delete()); setupFutureHandlers(d.delete(recursive: true)); }); }); } static void testDeleteTooLongName() { asyncStart(); Directory.systemTemp.createTemp('dart_directory').then((d) { var subDirName = 'subdir'; var subDir = new Directory("${d.path}/$subDirName"); subDir.create().then((ignore) { // Construct a long string of the form // 'tempdir/subdir/../subdir/../subdir'. var buffer = new StringBuffer(); buffer.write(subDir.path); for (var i = 0; i < 1000; i++) { buffer.write("/../${subDirName}"); } var long = new Directory("${buffer.toString()}"); var errors = 0; onError(error) { Expect.isTrue(error is FileSystemException); if (++errors == 2) { d.delete(recursive: true).then((_) => asyncEnd()); } } Future.value(long.delete()).catchError(onError); Future.value(long.delete(recursive: true)).catchError(onError); }); }); } static void testDeleteNonExistentSync() { Directory d = Directory.systemTemp.createTempSync('dart_directory_test'); d.deleteSync(); Expect.throws(d.deleteSync); Expect.throws(() => d.deleteSync(recursive: true)); } static void testDeleteTooLongNameSync() { Directory d = Directory.systemTemp.createTempSync('dart_directory_test'); var subDirName = 'subdir'; var subDir = new Directory("${d.path}/$subDirName"); subDir.createSync(); // Construct a long string of the form // 'tempdir/subdir/../subdir/../subdir'. var buffer = new StringBuffer(); buffer.write(subDir.path); for (var i = 0; i < 1000; i++) { buffer.write("/../${subDirName}"); } var long = new Directory("${buffer.toString()}"); Expect.throws(long.deleteSync); Expect.throws(() => long.deleteSync(recursive: true)); d.deleteSync(recursive: true); } static void testExistsCreateDelete() { Directory.systemTemp.createTemp('dart_directory').then((d) { d.exists().then((bool exists) { Expect.isTrue(exists); Directory created = new Directory("${d.path}/subdir"); created.create().then((ignore) { created.exists().then((bool exists) { Expect.isTrue(exists); created.delete().then((ignore) { created.exists().then((bool exists) { Expect.isFalse(exists); d.delete().then((ignore) { d.exists().then((bool exists) { Expect.isFalse(exists); }); }); }); }); }); }); }); }); } static void testExistsCreateDeleteSync() { Directory d = Directory.systemTemp.createTempSync('dart_directory_test'); Directory d2 = new Directory('${d.path}/'); Expect.isTrue(d.existsSync()); Expect.isTrue(d2.existsSync()); Directory created = new Directory("${d.path}/subdir"); created.createSync(); Expect.isTrue(created.existsSync()); created.deleteSync(); Expect.isFalse(created.existsSync()); d.deleteSync(); Expect.isFalse(d.existsSync()); } static void testDeleteLinkSync() { Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test'); var path = "${tmp.path}${Platform.pathSeparator}"; Directory d = new Directory("${path}target"); d.createSync(); Link l = new Link("${path}symlink"); l.createSync("${path}target"); Expect.isTrue(d.existsSync()); Expect.isTrue(l.existsSync()); new Directory(l.path).deleteSync(recursive: true); Expect.isTrue(d.existsSync()); Expect.isFalse(l.existsSync()); d.deleteSync(); Expect.isFalse(d.existsSync()); tmp.deleteSync(); } static void testDeleteLinkAsFileSync() { Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test'); var path = "${tmp.path}${Platform.pathSeparator}"; Directory d = new Directory("${path}target"); d.createSync(); Link l = new Link("${path}symlink"); l.createSync("${path}target"); Expect.isTrue(d.existsSync()); Expect.isTrue(l.existsSync()); new Link(l.path).deleteSync(); Expect.isTrue(d.existsSync()); Expect.isFalse(l.existsSync()); d.deleteSync(); Expect.isFalse(d.existsSync()); tmp.deleteSync(); } static void testDeleteBrokenLinkAsFileSync() { Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test'); var path = "${tmp.path}${Platform.pathSeparator}"; Directory d = new Directory("${path}target"); d.createSync(); Link l = new Link("${path}symlink"); l.createSync("${path}target"); d.deleteSync(); Expect.isFalse(d.existsSync()); Expect.isTrue(l.existsSync()); new Link(l.path).deleteSync(); Expect.isFalse(l.existsSync()); Expect.isFalse(d.existsSync()); tmp.deleteSync(); } static void testListBrokenLinkSync() { Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test'); var path = "${tmp.path}${Platform.pathSeparator}"; Directory d = new Directory("${path}target"); d.createSync(); Link l = new Link("${path}symlink"); l.createSync("${path}target"); d.deleteSync(); int count = 0; tmp.list(followLinks: true).listen((file) { count++; Expect.isTrue(file is Link); }, onDone: () { Expect.equals(1, count); l.deleteSync(); tmp.deleteSync(); }); } static void testListLinkSync() { Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test'); var path = "${tmp.path}${Platform.pathSeparator}"; Directory d = new Directory("${path}target"); d.createSync(); Link l = new Link("${path}symlink"); l.createSync("${path}target"); int count = 0; tmp.list(followLinks: true).listen((file) { count++; Expect.isTrue(file is Directory); }, onDone: () { Expect.equals(2, count); l.deleteSync(); d.deleteSync(); tmp.deleteSync(); }); } static void testCreateTemp() { Directory base = new Directory('/tmp'); String template = 'dart_temp_dir'; if (base.existsSync()) { asyncStart(); Future.wait([base.createTemp(template), base.createTemp(template)]) .then((tempDirs) { Expect.notEquals(tempDirs[0].path, tempDirs[1].path); for (Directory t in tempDirs) { Expect.isTrue(t.existsSync()); t.deleteSync(); Expect.isFalse(t.existsSync()); } asyncEnd(); }); } } static void testCreateSystemTemp() { String template = 'dart_system_temp_dir'; asyncStart(); Future.wait([ Directory.systemTemp.createTemp(template), Directory.systemTemp.createTemp(template) ]).then((tempDirs) { Expect.notEquals(tempDirs[0].path, tempDirs[1].path); for (Directory t in tempDirs) { Expect.isTrue(t.existsSync()); t.deleteSync(); Expect.isFalse(t.existsSync()); } asyncEnd(); }); } static void testCreateDeleteTemp() { Directory.systemTemp.createTemp('dart_directory').then((tempDirectory) { String filename = "${tempDirectory.path}${Platform.pathSeparator}dart_testfile"; File file = new File(filename); Expect.isFalse(file.existsSync()); file.create().then((ignore) { file.exists().then((exists) { Expect.isTrue(exists); // Try to delete the directory containing the file - should throw. Expect.throws(tempDirectory.deleteSync); Expect.isTrue(tempDirectory.existsSync()); // Delete the file, and then delete the directory. file.delete().then((ignore) { tempDirectory.deleteSync(); Expect.isFalse(tempDirectory.existsSync()); }); }); }); }); } static void testCurrent() { Directory current = Directory.current; if (Platform.operatingSystem != "windows") { Expect.equals("/", current.path.substring(0, 1)); } } static void testEquals() { var name = new File('.').resolveSymbolicLinksSync(); Directory current1 = new Directory(name); Directory current2 = new Directory(name); Expect.equals(current1.path, current2.path); Expect.isTrue(current1.existsSync()); } static void testMain() { testListing(); testListingTailingPaths(); testListNonExistent(); testListTooLongName(); testDeleteNonExistent(); testDeleteTooLongName(); testDeleteNonExistentSync(); testDeleteTooLongNameSync(); testExistsCreateDelete(); testExistsCreateDeleteSync(); testDeleteLinkSync(); testDeleteLinkAsFileSync(); testDeleteBrokenLinkAsFileSync(); testListBrokenLinkSync(); testListLinkSync(); testCreateTemp(); testCreateSystemTemp(); testCreateDeleteTemp(); testCurrent(); testEquals(); } } class NestedTempDirectoryTest { List createdDirectories; NestedTempDirectoryTest.run() : createdDirectories = [] { Directory.systemTemp.createTemp('dart_directory').then(createPhaseCallback); } void createPhaseCallback(temp) { createdDirectories.add(temp); int nestingDepth = 6; var os = Platform.operatingSystem; if (os == "windows") nestingDepth = 2; if (createdDirectories.length < nestingDepth) { temp .createTemp('nested_temp_dir_${createdDirectories.length}_') .then(createPhaseCallback); } else { deletePhaseCallback(); } } void deletePhaseCallback() { if (!createdDirectories.isEmpty) { final current = createdDirectories.removeLast(); current.deleteSync(); deletePhaseCallback(); } } static void testMain() { new NestedTempDirectoryTest.run(); new NestedTempDirectoryTest.run(); } } String? illegalTempDirectoryLocation() { // Determine a platform specific illegal location for a temporary directory. var os = Platform.operatingSystem; if (os == "linux" || os == "macos") { return "/dev/zero/"; } if (os == "windows") { return "*"; } return null; } testCreateTempErrorSync() { var location = illegalTempDirectoryLocation(); if (location != null) { Expect.throws(() => new Directory(location).createTempSync('dart_tempdir'), (e) => e is FileSystemException); } } testCreateTempError() { var location = illegalTempDirectoryLocation(); if (location == null) return; asyncStart(); var future = new Directory(location).createTemp('dart_tempdir'); Future.value(future).catchError((_) => asyncEnd()); } testCreateExistingSync() { // Test that creating an existing directory succeeds. var temp = Directory.systemTemp.createTempSync('directory_test'); var subDir = new Directory('${temp.path}/flaf'); Expect.isFalse(subDir.existsSync()); subDir.createSync(); Expect.isTrue(subDir.existsSync()); subDir.createSync(); Expect.isTrue(subDir.existsSync()); temp.deleteSync(recursive: true); } testCreateExisting() { // Test that creating an existing directory succeeds. asyncStart(); Directory.systemTemp.createTemp('dart_directory').then((temp) { var subDir = new Directory('${temp.path}/flaf'); subDir.exists().then((dirExists) { Expect.isFalse(dirExists); subDir.create().then((_) { subDir.exists().then((dirExists) { Expect.isTrue(dirExists); subDir.create().then((_) { subDir.exists().then((dirExists) { Expect.isTrue(dirExists); temp.delete(recursive: true).then((_) { asyncEnd(); }); }); }); }); }); }); }); } testCreateDirExistingFileSync() { // Test that creating an existing directory succeeds. var temp = Directory.systemTemp.createTempSync('directory_test'); var path = '${temp.path}/flaf'; var file = new File(path); file.createSync(); Expect.isTrue(file.existsSync()); Expect.throws( new Directory(path).createSync, (e) => e is FileSystemException); temp.deleteSync(recursive: true); } testCreateDirExistingFile() { // Test that creating an existing directory succeeds. asyncStart(); Directory.systemTemp.createTemp('dart_directory').then((temp) { var path = '${temp.path}/flaf'; var file = new File(path); var subDir = new Directory(path); file.create().then((_) { subDir.create().then((_) { Expect.fail("dir create should fail on existing file"); }).catchError((error) { Expect.isTrue(error is FileSystemException); temp.delete(recursive: true).then((_) { asyncEnd(); }); }); }); }); } testRename() { var temp1 = Directory.systemTemp.createTempSync('directory_test'); var temp2 = Directory.systemTemp.createTempSync('directory_test'); var temp3 = temp1.renameSync(temp2.path); Expect.isFalse(temp1.existsSync()); Expect.isTrue(temp2.existsSync()); Expect.equals(temp3.path, temp2.path); var temp4 = temp2.renameSync(temp1.path); Expect.isFalse(temp3.existsSync()); Expect.isFalse(temp2.existsSync()); Expect.isTrue(temp1.existsSync()); Expect.isTrue(temp4.existsSync()); Expect.equals(temp1.path, temp4.path); String foo = '${temp4.path}/foo'; String bar = '${temp4.path}/bar'; new File(foo).createSync(); try { new Directory(foo).renameSync(bar); Expect.fail('Directory.rename should fail to rename a non-directory'); } on FileSystemException catch (e) { if (Platform.isLinux || Platform.isMacOS) { Expect.isTrue(e.osError!.message.contains('Not a directory')); } } temp1.deleteSync(recursive: true); } main() { DirectoryTest.testMain(); NestedTempDirectoryTest.testMain(); testCreateTempErrorSync(); testCreateTempError(); testCreateExistingSync(); testCreateExisting(); testCreateDirExistingFileSync(); testCreateDirExistingFile(); testRename(); }