blob: 5e2ac5decfa9aebc379814c80ad3818d3ad81c78 [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.
//
// Dart test program for testing FileSystemEntity.resolveSymbolicLinks
import "package:expect/expect.dart";
import "package:path/path.dart";
import "package:expect/async_helper.dart";
import 'dart:async';
import 'dart:io';
main() {
String testsDir = Directory.current.uri.resolve('tests').toFilePath();
// All of these tests test that resolveSymbolicLinks gives a path
// that points to the same place as the original, and that it removes
// all links, .., and . segments, and that it produces an absolute path.
asyncTest(
() => testFile(
join(testsDir, 'standalone', 'io', 'resolve_symbolic_links_test.dart'),
),
);
asyncTest(
() => testFile(
join(
testsDir,
'standalone',
'io',
'..',
'io',
'resolve_symbolic_links_test.dart',
),
),
);
asyncTest(() => testDir(join(testsDir, 'standalone', 'io')));
asyncTest(() => testDir(join(testsDir, 'lib', '..', 'standalone', 'io')));
// Test a relative path.
if (Platform.isWindows) {
asyncTest(
() => testFile(
join(
'\\\\?\\$testsDir',
'standalone',
'io',
'resolve_symbolic_links_test.dart',
),
),
);
asyncTest(() => testDir('\\\\?\\$testsDir'));
}
asyncTest(
() => Directory.systemTemp.createTemp('dart_resolve_symbolic_links').then((
tempDir,
) {
String temp = tempDir.path;
return makeEntities(temp)
.then(
(_) => Future.wait([
testFile(join(temp, 'dir1', 'file1')),
testFile(join(temp, 'link1', 'file2')),
testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
testLink(join(temp, 'link1')),
testDir('.'),
]),
)
.then((_) {
if (Platform.isWindows) {
// Windows applies '..' to a link without resolving the link first.
return Future.wait([
testFile(
join(
temp,
'dir1',
'..',
'link1',
'..',
'dir1',
'dir2',
'file2',
),
),
testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir1')),
testLink(join(temp, 'link1', '..', 'link1')),
]);
} else {
// Non-Windows platforms resolve the link before adding the '..'.
return Future.wait([
testFile(
join(temp, 'dir1', '..', 'link1', '..', 'dir2', 'file2'),
),
testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir2')),
testLink(join(temp, 'link1', '..', '..', 'link1')),
]);
}
})
.then((_) {
Directory.current = temp;
return Future.wait([
testFile(
'dir1/dir2/file2',
), // Test forward slashes on Windows too.
testFile('link1/file2'),
testFile(join('dir1', '..', 'dir1', '.', 'file1')),
testDir('.'),
testLink('link1'),
]);
})
.then((_) {
Directory.current = 'link1';
if (Platform.isWindows) {
return Future.wait([
testFile('file2'),
// Windows applies '..' to a link without resolving the link first.
testFile('..\\dir1\\file1'),
testLink('.'),
testDir('..'),
testLink('..\\link1'),
]);
} else {
return Future.wait([
testFile('file2'),
// On non-Windows the link is changed to dir1/dir2 before .. happens.
testFile('../dir2/file2'),
testDir('.'),
testDir('..'),
testLink('../../link1'),
]);
}
})
.whenComplete(() {
Directory.current = testsDir;
tempDir.delete(recursive: true);
});
}),
);
asyncTest(testNonExistantPath);
asyncTest(testLinkTargetTypeChangedAfterCreation);
}
Future makeEntities(String temp) {
return new Directory(join(temp, 'dir1', 'dir2'))
.create(recursive: true)
.then((_) => new File(join(temp, 'dir1', 'dir2', 'file2')).create())
.then((_) => new File(join(temp, 'dir1', 'file1')).create())
.then(
(_) => new Link(join(temp, 'link1')).create(join(temp, 'dir1', 'dir2')),
);
}
Future testFile(String name) {
// We test that f.resolveSymbolicLinks points to the same place
// as f, because the actual resolved path is not easily predictable.
// The location of the temp directory varies from system to system,
// and its path includes symbolic links on some systems.
//Expect.isTrue(FileSystemEntity.identicalSync(name,
// new File(name).resolveSymbolicLinksSync()));
return new File(name).resolveSymbolicLinks().then((String resolved) {
//Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
Expect.isTrue(isAbsolute(resolved));
// Test that resolveSymbolicLinks removes all links, .., and . segments.
Expect.isFalse(resolved.contains('..'));
Expect.isFalse(resolved.contains('./'));
Expect.isFalse(resolved.contains('link1'));
});
}
Future testDir(String name) {
Expect.isTrue(
FileSystemEntity.identicalSync(
name,
new Directory(name).resolveSymbolicLinksSync(),
),
);
return new Directory(name).resolveSymbolicLinks().then((String resolved) {
Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
Expect.isTrue(isAbsolute(resolved));
// Test that resolveSymbolicLinks removes all links, .., and . segments.
Expect.isFalse(resolved.contains('..'));
Expect.isFalse(resolved.contains('./'));
Expect.isFalse(resolved.contains('link1'));
});
}
Future testLink(String name) {
Expect.isFalse(
FileSystemEntity.identicalSync(
name,
new Link(name).resolveSymbolicLinksSync(),
),
);
Expect.isTrue(
FileSystemEntity.identicalSync(
new Link(name).targetSync(),
new Link(name).resolveSymbolicLinksSync(),
),
);
return new Link(name).resolveSymbolicLinks().then((String resolved) {
Expect.isFalse(FileSystemEntity.identicalSync(name, resolved));
Expect.isTrue(isAbsolute(resolved));
// Test that resolveSymbolicLinks removes all links, .., and . segments.
Expect.isFalse(resolved.contains('..'));
Expect.isFalse(resolved.contains('./'));
Expect.isFalse(resolved.contains('link1'));
return new Link(name)
.target()
.then((targetName) => FileSystemEntity.identical(targetName, resolved))
.then((identical) => Expect.isTrue(identical));
});
}
Future testNonExistantPath() async {
try {
await File('/tmp/foo/doesnotexist').resolveSymbolicLinks();
Expect.fail("expected FileSystemException");
} on FileSystemException {}
}
Future testLinkTargetTypeChangedAfterCreation() async {
// Test the following scenario:
// 1. create a file
// 2. create a link to that file
// 3. replace the file with a directory
// 4. attempt to resolve the link
final tmp = await Directory.systemTemp.createTemp(
'dart_resolve_symbolic_links',
);
final tmpPath = tmp.absolute.path;
final filePath = join(tmpPath, "file");
final linkPath = join(tmpPath, "link");
await File(filePath).create();
await Link(linkPath).create(filePath);
Expect.isTrue(
FileSystemEntity.identicalSync(
filePath,
await Directory(linkPath).resolveSymbolicLinks(),
),
);
await File(filePath).delete();
await Directory(filePath).create();
if (Platform.isWindows) {
await asyncExpectThrows<PathAccessException>(
Directory(linkPath).resolveSymbolicLinks(),
);
} else {
Expect.isTrue(
await FileSystemEntity.identical(
filePath,
await Directory(linkPath).resolveSymbolicLinks(),
),
);
}
}