blob: 5826b3e843932e99e366e4ecb5b8040c7adde71b [file] [log] [blame]
// Copyright (c) 2013, 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.
import "package:expect/expect.dart";
import "package:path/path.dart";
import "dart:async";
import "dart:io";
import "dart:isolate";
// Test the dart:io Link class.
class FutureExpect {
static Future isTrue(Future<bool> result) =>
result.then((value) => Expect.isTrue(value));
static Future isFalse(Future<bool> result) =>
result.then((value) => Expect.isFalse(value));
static Future equals(expected, Future result) =>
result.then((value) => Expect.equals(expected, value));
static Future listEquals(expected, Future result) =>
result.then((value) => Expect.listEquals(expected, value));
static Future throws(Future result) =>
result.then((value) {
throw new ExpectException(
"FutureExpect.throws received $value instead of an exception");
}, onError: (_) => null);
}
Future testCreate() {
return new Directory('').createTemp().then((baseDir) {
String base = baseDir.path;
String link = join(base, 'link');
String target = join(base, 'target');
return new Directory(target).create()
.then((_) => new Link(link).create(target))
.then((_) => FutureExpect.equals(FileSystemEntityType.DIRECTORY,
FileSystemEntity.type(link)))
.then((_) => FutureExpect.equals(FileSystemEntityType.DIRECTORY,
FileSystemEntity.type(target)))
.then((_) => FutureExpect.equals(FileSystemEntityType.LINK,
FileSystemEntity.type(link, followLinks: false)))
.then((_) => FutureExpect.equals(FileSystemEntityType.DIRECTORY,
FileSystemEntity.type(target, followLinks: false)))
.then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(link)))
.then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(target)))
.then((_) => FutureExpect.isTrue(new Directory(link).exists()))
.then((_) => FutureExpect.isTrue(new Directory(target).exists()))
.then((_) => FutureExpect.isTrue(new Link(link).exists()))
.then((_) => FutureExpect.isFalse(new Link(target).exists()))
.then((_) => FutureExpect.equals(target, new Link(link).target()))
.then((_) => FutureExpect.throws(new Link(target).target()))
.then((_) {
String createdThroughLink = join(base, 'link', 'createdThroughLink');
String createdDirectly = join(base, 'target', 'createdDirectly');
String createdFile = join(base, 'link', 'createdFile');
return new Directory(createdThroughLink).create()
.then((_) => new Directory(createdDirectly).create())
.then((_) => new File(createdFile).create())
.then((_) => FutureExpect.isTrue(
new Directory(createdThroughLink).exists()))
.then((_) => FutureExpect.isTrue(
new Directory(createdDirectly).exists()))
.then((_) => FutureExpect.isTrue(
new Directory(join(base, 'link', 'createdDirectly')).exists()))
.then((_) => FutureExpect.isTrue(
new Directory(join(base, 'target', 'createdThroughLink')).exists()))
.then((_) => FutureExpect.equals(FileSystemEntityType.DIRECTORY,
FileSystemEntity.type(createdThroughLink, followLinks: false)))
.then((_) => FutureExpect.equals(FileSystemEntityType.DIRECTORY,
FileSystemEntity.type(createdDirectly, followLinks: false)))
// Test FileSystemEntity.identical on files, directories, and links,
// reached by different paths.
.then((_) => FutureExpect.isTrue(FileSystemEntity.identical(
createdDirectly,
createdDirectly)))
.then((_) => FutureExpect.isFalse(FileSystemEntity.identical(
createdDirectly,
createdThroughLink)))
.then((_) => FutureExpect.isTrue(FileSystemEntity.identical(
createdDirectly,
join(base, 'link', 'createdDirectly'))))
.then((_) => FutureExpect.isTrue(FileSystemEntity.identical(
createdThroughLink,
join(base, 'target', 'createdThroughLink'))))
.then((_) => FutureExpect.isFalse(FileSystemEntity.identical(
target,
link)))
.then((_) => FutureExpect.isTrue(FileSystemEntity.identical(
link,
link)))
.then((_) => FutureExpect.isTrue(FileSystemEntity.identical(
target,
target)))
.then((_) => new Link(link).target())
.then((linkTarget) => FutureExpect.isTrue(FileSystemEntity.identical(
target,
linkTarget)))
.then((_) => new File(".").fullPath())
.then((fullCurrentDir) => FutureExpect.isTrue(FileSystemEntity.identical(
".",
fullCurrentDir)))
.then((_) => FutureExpect.isTrue(FileSystemEntity.identical(
createdFile,
createdFile)))
.then((_) => FutureExpect.isFalse(FileSystemEntity.identical(
createdFile,
createdDirectly)))
.then((_) => FutureExpect.isTrue(FileSystemEntity.identical(
createdFile,
join(base, 'link', 'createdFile'))))
.then((_) => FutureExpect.throws(FileSystemEntity.identical(
createdFile,
join(base, 'link', 'does_not_exist'))))
.then((_) => testDirectoryListing(base, baseDir))
.then((_) => new Directory(target).delete(recursive: true))
.then((_) {
List<Future> futures = [];
for (bool recursive in [true, false]) {
for (bool followLinks in [true, false]) {
var result = baseDir.listSync(recursive: recursive,
followLinks: followLinks);
Expect.equals(1, result.length);
Expect.isTrue(result[0] is Link);
futures.add(FutureExpect.isTrue(
baseDir.list(recursive: recursive,
followLinks: followLinks)
.single.then((element) => element is Link)));
}
}
return Future.wait(futures);
})
.then((_) => baseDir.delete(recursive: true));
});
});
}
Future testCreateLoopingLink() {
return new Directory('').createTemp()
.then((dir) => dir.path)
.then((String base) =>
new Directory(join(base, 'a', 'b', 'c')).create(recursive: true)
.then((_) => new Link(join(base, 'a', 'b', 'c', 'd'))
.create(join(base, 'a', 'b')))
.then((_) => new Link(join(base, 'a', 'b', 'c', 'e'))
.create(join(base, 'a')))
.then((_) => new Directory(join(base, 'a'))
.list(recursive: true, followLinks: false).last)
// This directory listing must terminate, even though it contains loops.
.then((_) => new Directory(join(base, 'a'))
.list(recursive: true, followLinks: true).last)
// This directory listing must terminate, even though it contains loops.
.then((_) => new Directory(join(base, 'a', 'b', 'c'))
.list(recursive: true, followLinks: true).last)
.then((_) => new Directory(base).delete(recursive: true))
.then((_) => FutureExpect.isFalse(new Directory(base).exists()))
);
}
Future testRename() {
Future testRename(String base , String target) {
Link link1;
Link link2;
return new Link(join(base, 'c')).create(target)
.then((link) {
link1 = link;
Expect.isTrue(link1.existsSync());
return link1.rename(join(base, 'd'));
})
.then((link) {
link2 = link;
Expect.isFalse(link1.existsSync());
Expect.isTrue(link2.existsSync());
return link2.delete();
})
.then((_) => Expect.isFalse(link2.existsSync()));
}
return new Directory('').createTemp().then((baseDir) {
String base = baseDir.path;
var targetsFutures = [];
targetsFutures.add(new Directory(join(base, 'a')).create());
if (Platform.isWindows) {
// Currently only links to directories are supported on Windows.
targetsFutures.add(
new Directory(join(base, 'b')).create());
} else {
targetsFutures.add(new File(join(base, 'b')).create());
}
return Future.wait(targetsFutures).then((targets) {
return testRename(base, targets[0].path)
.then((_) => testRename(base, targets[1].path))
.then((_) => baseDir.delete(recursive: true));
});
});
}
Future testDirectoryListing(String base, Directory baseDir) {
Map makeExpected(bool recursive, bool followLinks) {
Map expected = new Map();
expected['target'] = 'Directory';
expected['link'] = followLinks ? 'Directory' : 'Link';
if (recursive) {
expected[join('target', 'createdDirectly')] = 'Directory';
expected[join('target', 'createdThroughLink')] = 'Directory';
expected[join('target', 'createdFile')] = 'File';
if (followLinks) {
expected[join('link', 'createdDirectly')] = 'Directory';
expected[join('link', 'createdThroughLink')] = 'Directory';
expected[join('link', 'createdFile')] = 'File';
}
}
return expected;
}
void checkEntity(FileSystemEntity x, Map expected) {
String ending = relative(x.path, from: base);
Expect.isNotNull(expected[ending]);
Expect.isTrue(x.toString().startsWith(expected[ending]));
expected[ending] = 'Found';
}
List futures = [];
for (bool recursive in [true, false]) {
for (bool followLinks in [true, false]) {
Map expected = makeExpected(recursive, followLinks);
for (var x in baseDir.listSync(recursive: recursive,
followLinks: followLinks)) {
checkEntity(x, expected);
}
for (var v in expected.values) {
Expect.equals('Found', v);
}
expected = makeExpected(recursive, followLinks);
futures.add(
baseDir.list(recursive: recursive, followLinks: followLinks)
.forEach((entity) => checkEntity(entity, expected))
.then((_) {
for (var v in expected.values) {
Expect.equals('Found', v);
}
})
);
}
}
return Future.wait(futures);
}
main() {
ReceivePort keepAlive = new ReceivePort();
testCreate()
.then((_) => testCreateLoopingLink())
.then((_) => testRename())
.then((_) => keepAlive.close());
}