Skip to content

Commit 4531665

Browse files
authored
Implement tests for Directory (flutter#19)
1 parent 4b48927 commit 4531665

File tree

6 files changed

+656
-247
lines changed

6 files changed

+656
-247
lines changed

lib/src/backends/memory/memory_directory.dart

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class _MemoryDirectory extends _MemoryFileSystemEntity implements Directory {
3030
}
3131
return null;
3232
},
33+
resolveTailLink: true,
3334
);
3435
if (node.type != expectedType) {
3536
// There was an existing non-directory node at this object's path
@@ -42,8 +43,8 @@ class _MemoryDirectory extends _MemoryFileSystemEntity implements Directory {
4243

4344
@override
4445
Directory createTempSync([String prefix]) {
45-
prefix ??= '';
46-
String fullPath = '$path$_separator$prefix';
46+
prefix = (prefix ?? '') + 'rand';
47+
String fullPath = fileSystem._context.join(path, prefix);
4748
String dirname = fileSystem._context.dirname(fullPath);
4849
String basename = fileSystem._context.basename(fullPath);
4950
_DirectoryNode node = fileSystem._findNode(dirname);
@@ -55,7 +56,8 @@ class _MemoryDirectory extends _MemoryFileSystemEntity implements Directory {
5556
}
5657
_DirectoryNode tempDir = new _DirectoryNode(node);
5758
node.children[name()] = tempDir;
58-
return new _MemoryDirectory(fileSystem, '$dirname$_separator${name()}');
59+
return new _MemoryDirectory(
60+
fileSystem, fileSystem._context.join(dirname, name()));
5961
}
6062

6163
@override
@@ -95,24 +97,28 @@ class _MemoryDirectory extends _MemoryFileSystemEntity implements Directory {
9597
}) {
9698
_DirectoryNode node = backing;
9799
List<FileSystemEntity> listing = <FileSystemEntity>[];
98-
Set<_LinkNode> visitedLinks = new Set<_LinkNode>();
99100
List<_PendingListTask> tasks = <_PendingListTask>[
100101
new _PendingListTask(
101102
node,
102103
path.endsWith(_separator) ? path.substring(0, path.length - 1) : path,
104+
new Set<_LinkNode>(),
103105
),
104106
];
105107
while (tasks.isNotEmpty) {
106108
_PendingListTask task = tasks.removeLast();
107109
task.dir.children.forEach((String name, _Node child) {
108-
String childPath = '${task.path}$_separator$name';
109-
if (followLinks && _isLink(child) && visitedLinks.add(child)) {
110-
child = (child as _LinkNode).referent;
110+
Set<_LinkNode> breadcrumbs = new Set<_LinkNode>.from(task.breadcrumbs);
111+
String childPath = fileSystem._context.join(task.path, name);
112+
while (followLinks && _isLink(child) && breadcrumbs.add(child)) {
113+
_Node referent = (child as _LinkNode).referentOrNull;
114+
if (referent != null) {
115+
child = referent;
116+
}
111117
}
112118
if (_isDirectory(child)) {
113119
listing.add(new _MemoryDirectory(fileSystem, childPath));
114120
if (recursive) {
115-
tasks.add(new _PendingListTask(child, childPath));
121+
tasks.add(new _PendingListTask(child, childPath, breadcrumbs));
116122
}
117123
} else if (_isLink(child)) {
118124
listing.add(new _MemoryLink(fileSystem, childPath));
@@ -131,5 +137,6 @@ class _MemoryDirectory extends _MemoryFileSystemEntity implements Directory {
131137
class _PendingListTask {
132138
final _DirectoryNode dir;
133139
final String path;
134-
_PendingListTask(this.dir, this.path);
140+
final Set<_LinkNode> breadcrumbs;
141+
_PendingListTask(this.dir, this.path, this.breadcrumbs);
135142
}

lib/src/backends/memory/memory_file_system.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,19 +209,20 @@ class MemoryFileSystem extends FileSystem {
209209
if (i < finalSegment) {
210210
_PathGenerator subpath = _subpath(parts, 0, i);
211211
_checkExists(child, subpath);
212+
if (pathWithSymlinks != null) {
213+
pathWithSymlinks.add(basename);
214+
}
212215
if (_isLink(child)) {
213216
child = _resolveLinks(child, subpath, ledger: pathWithSymlinks);
214-
} else if (pathWithSymlinks != null) {
215-
pathWithSymlinks..add(_separator)..add(basename);
216217
}
217218
_checkIsDir(child, subpath);
218219
directory = child;
219220
} else if (pathWithSymlinks != null) {
220-
pathWithSymlinks..add(_separator)..add(basename);
221+
pathWithSymlinks.add(basename);
221222
}
222223
}
223224
if (_isLink(child) && resolveTailLink) {
224-
child = _resolveLinks(child, () => path);
225+
child = _resolveLinks(child, () => path, ledger: pathWithSymlinks);
225226
}
226227
return child;
227228
}

lib/src/backends/memory/memory_file_system_entity.dart

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ abstract class _MemoryFileSystemEntity implements FileSystemEntity {
6363
pathWithSymlinks: ledger, resolveTailLink: true);
6464
_checkExists(node, () => path);
6565
String resolved = ledger.join(_separator);
66-
if (!isAbsolute) {
67-
resolved = fileSystem._cwd + resolved;
66+
if (!_isAbsolute(resolved)) {
67+
resolved = fileSystem._cwd + _separator + resolved;
6868
}
6969
return fileSystem._context.normalize(resolved);
7070
}
@@ -88,7 +88,7 @@ abstract class _MemoryFileSystemEntity implements FileSystemEntity {
8888
if (node is _DirectoryNode && node.children.isNotEmpty) {
8989
throw new io.FileSystemException('Directory not empty', path);
9090
}
91-
if (node.type != expectedType) {
91+
if (node.stat.type != expectedType) {
9292
throw new io.FileSystemException(
9393
'Not a ${expectedType.toString().toLowerCase()}', path);
9494
}
@@ -113,7 +113,7 @@ abstract class _MemoryFileSystemEntity implements FileSystemEntity {
113113
FileSystemEntity get absolute {
114114
String absolutePath = path;
115115
if (!_isAbsolute(absolutePath)) {
116-
absolutePath = '${fileSystem._cwd}$_separator$absolutePath';
116+
absolutePath = fileSystem._context.join(fileSystem._cwd, absolutePath);
117117
}
118118
return _clone(absolutePath);
119119
}
@@ -136,11 +136,16 @@ abstract class _MemoryFileSystemEntity implements FileSystemEntity {
136136
/// If an entity already existed at this path, [createChild] will not be
137137
/// invoked at all, and this method will return with the backing node for the
138138
/// existing entity (whose type may differ from this entity's type).
139+
///
140+
/// If [resolveTailLink] is true and the result node is a link, this will
141+
/// resolve it to its target prior to returning it.
139142
_Node _createSync(
140-
_Node createChild(_DirectoryNode parent, bool isFinalSegment),
141-
) {
143+
_Node createChild(_DirectoryNode parent, bool isFinalSegment), {
144+
bool resolveTailLink: false,
145+
}) {
142146
return fileSystem._findNode(
143147
path,
148+
resolveTailLink: resolveTailLink,
144149
segmentVisitor: (
145150
_DirectoryNode parent,
146151
String childName,
@@ -183,6 +188,9 @@ abstract class _MemoryFileSystemEntity implements FileSystemEntity {
183188
_RenameOverwriteValidator<dynamic> validateOverwriteExistingEntity,
184189
}) {
185190
_Node node = backing;
191+
if (node.stat.type != expectedType) {
192+
throw new io.FileSystemException('No such file or directory', path);
193+
}
186194
fileSystem._findNode(
187195
newPath,
188196
segmentVisitor: (

lib/src/backends/memory/node.dart

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,24 @@ class _LinkNode extends _Node {
150150
assert(target != null && target.isNotEmpty);
151151
}
152152

153+
/// Gets the node backing for this link's target. Throws a
154+
/// [io.FileSystemException] if this link references a non-existent file
155+
/// system entity.
156+
_Node get referent {
157+
_Node node = fs._findNode(target, reference: this);
158+
_checkExists(node, () => target);
159+
return node;
160+
}
161+
153162
/// Gets the node backing for this link's target, or null if this link
154163
/// references a non-existent file system entity.
155-
_Node get referent => fs._findNode(target, reference: this);
164+
_Node get referentOrNull {
165+
try {
166+
return referent;
167+
} on io.FileSystemException {
168+
return null;
169+
}
170+
}
156171

157172
@override
158173
io.FileSystemEntityType get type => io.FileSystemEntityType.LINK;
@@ -164,7 +179,7 @@ class _LinkNode extends _Node {
164179
}
165180
reentrant = true;
166181
try {
167-
_Node node = referent;
182+
_Node node = referentOrNull;
168183
return node == null ? _MemoryFileStat._notFound : node.stat;
169184
} finally {
170185
reentrant = false;

lib/src/backends/memory/utils.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ _Node _resolveLinks(
6262
while (_isLink(node)) {
6363
link = node;
6464
if (!breadcrumbs.add(node)) {
65-
throw new io.FileSystemException('Loop found in link chain', path());
65+
throw new io.FileSystemException(
66+
'Too many levels of symbolic links', path());
6667
}
6768
if (ledger != null) {
6869
if (_isAbsolute(link.target)) {

0 commit comments

Comments
 (0)