Skip to content

Commit f289ad5

Browse files
authored
Move memory tests to common tests. (flutter#17)
Move memory tests to common tests. This change prepares us to be able to run all file system tests against multiple implementations of the interface. The goal is to be able to test the local file system impl against all tests, and run the exact same tests against the in-memory impl, thus ensuring (a) the in-memory impl has test coverage, and (b) that it behaves identical in its API to the local dart:io variant. This change does not touch any code - just restructures things.
1 parent 653c2fd commit f289ad5

File tree

2 files changed

+363
-356
lines changed

2 files changed

+363
-356
lines changed

test/common_tests.dart

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
import 'dart:io' as io;
2+
3+
import 'package:file/file.dart';
4+
import 'package:test/test.dart';
5+
6+
void runCommonTests(FileSystem fileSystemFactory()) {
7+
group('FileSystem', () {
8+
FileSystem fs;
9+
10+
setUp(() async {
11+
fs = fileSystemFactory();
12+
});
13+
14+
group('currentDirectory', () {
15+
test('defaultsToRoot', () {
16+
expect(fs.currentDirectory.path, '/');
17+
});
18+
19+
test('throwsIfSetToNonExistentPath', () {
20+
expectFileSystemException('No such file or directory', () {
21+
fs.currentDirectory = '/foo';
22+
});
23+
});
24+
25+
test('succeedsWhenSetToValidStringPath', () {
26+
fs.directory('/foo').createSync();
27+
fs.currentDirectory = '/foo';
28+
expect(fs.currentDirectory.path, '/foo');
29+
});
30+
31+
test('succeedsWhenSetToValidDirectory', () {
32+
fs.directory('/foo').createSync();
33+
fs.currentDirectory = new io.Directory('/foo');
34+
expect(fs.currentDirectory.path, '/foo');
35+
});
36+
37+
test('throwsWhenArgumentIsNotStringOrDirectory', () {
38+
expect(() {
39+
fs.currentDirectory = 123;
40+
}, throwsArgumentError);
41+
});
42+
43+
test('succeedsWhenSetToRelativePath', () {
44+
fs.directory('/foo/bar').createSync(recursive: true);
45+
fs.currentDirectory = 'foo';
46+
expect(fs.currentDirectory.path, '/foo');
47+
fs.currentDirectory = 'bar';
48+
expect(fs.currentDirectory.path, '/foo/bar');
49+
});
50+
51+
test('succeedsWhenSetToParentDirectory', () {
52+
fs.directory('/foo').createSync();
53+
fs.currentDirectory = 'foo';
54+
expect(fs.currentDirectory.path, '/foo');
55+
fs.currentDirectory = '..';
56+
expect(fs.currentDirectory.path, '/');
57+
});
58+
59+
test('staysAtRootWhenSetToParentOfRoot', () {
60+
fs.currentDirectory = '../../..';
61+
expect(fs.currentDirectory.path, '/');
62+
});
63+
64+
test('removesTrailingSlashWhenSet', () {
65+
fs.directory('/foo').createSync();
66+
fs.currentDirectory = '/foo/';
67+
expect(fs.currentDirectory.path, '/foo');
68+
});
69+
70+
test('throwsWhenSetToFilePath', () {
71+
fs.file('/foo').createSync();
72+
expectFileSystemException('Not a directory', () {
73+
fs.currentDirectory = '/foo';
74+
});
75+
});
76+
77+
test('resolvesSymlinksWhenEncountered', () {
78+
fs.link('/foo/bar/baz').createSync('/qux', recursive: true);
79+
fs.directory('/qux').createSync();
80+
fs.directory('/quux').createSync();
81+
fs.currentDirectory = '/foo/bar/baz/../quux/';
82+
expect(fs.currentDirectory.path, '/quux');
83+
});
84+
});
85+
86+
group('stat', () {
87+
test('isNotFoundForPathToNonExistentEntityAtTail', () {
88+
io.FileStat stat = fs.statSync('/foo');
89+
expect(stat.type, io.FileSystemEntityType.NOT_FOUND);
90+
});
91+
92+
test('isNotFoundForPathToNonExistentEntityInTraversal', () {
93+
io.FileStat stat = fs.statSync('/foo/bar');
94+
expect(stat.type, io.FileSystemEntityType.NOT_FOUND);
95+
});
96+
97+
test('isDirectoryForDirectory', () {
98+
fs.directory('/foo').createSync();
99+
var stat = fs.statSync('/foo');
100+
expect(stat.type, io.FileSystemEntityType.DIRECTORY);
101+
});
102+
103+
test('isFileForFile', () {
104+
fs.file('/foo').createSync();
105+
var stat = fs.statSync('/foo');
106+
expect(stat.type, io.FileSystemEntityType.FILE);
107+
});
108+
109+
test('isFileForSymlinkToFile', () {
110+
fs.file('/foo').createSync();
111+
fs.link('/bar').createSync('/foo');
112+
var stat = fs.statSync('/bar');
113+
expect(stat.type, io.FileSystemEntityType.FILE);
114+
});
115+
116+
test('isNotFoundForSymlinkWithCircularReference', () {
117+
fs.link('/foo').createSync('/bar');
118+
fs.link('/bar').createSync('/baz');
119+
fs.link('/baz').createSync('/foo');
120+
var stat = fs.statSync('/foo');
121+
expect(stat.type, io.FileSystemEntityType.NOT_FOUND);
122+
});
123+
});
124+
125+
group('identical', () {
126+
test('isTrueForIdenticalPathsToExistentFile', () {
127+
fs.file('/foo').createSync();
128+
expect(fs.identicalSync('/foo', '/foo'), true);
129+
});
130+
131+
test('isFalseForDifferentPathsToDifferentFiles', () {
132+
fs.file('/foo').createSync();
133+
fs.file('/bar').createSync();
134+
expect(fs.identicalSync('/foo', '/bar'), false);
135+
});
136+
137+
test('isTrueForDifferentPathsToSameFileViaLinkInTraversal', () {
138+
fs.file('/foo/file').createSync(recursive: true);
139+
fs.link('/bar').createSync('/foo');
140+
expect(fs.identicalSync('/foo/file', '/bar/file'), true);
141+
});
142+
143+
test('isFalseForDifferentPathsToSameFileViaLinkAtTail', () {
144+
fs.file('/foo').createSync();
145+
fs.link('/bar').createSync('/foo');
146+
expect(fs.identicalSync('/foo', '/bar'), false);
147+
});
148+
149+
test('throwsForDifferentPathsToNonExistentEntities', () {
150+
expectFileSystemException('No such file or directory', () {
151+
fs.identicalSync('/foo', '/bar');
152+
});
153+
});
154+
155+
test('throwsForDifferentPathsToOneFileOneNonExistentEntity', () {
156+
fs.file('/foo').createSync();
157+
expectFileSystemException('No such file or directory', () {
158+
fs.identicalSync('/foo', '/bar');
159+
});
160+
});
161+
});
162+
163+
group('type', () {
164+
test('isFileForFile', () {
165+
fs.file('/foo').createSync();
166+
var type = fs.typeSync('/foo');
167+
expect(type, io.FileSystemEntityType.FILE);
168+
});
169+
170+
test('isDirectoryForDirectory', () {
171+
fs.directory('/foo').createSync();
172+
var type = fs.typeSync('/foo');
173+
expect(type, io.FileSystemEntityType.DIRECTORY);
174+
});
175+
176+
test('isFileForSymlinkToFileAndFollowLinksTrue', () {
177+
fs.file('/foo').createSync();
178+
fs.link('/bar').createSync('/foo');
179+
var type = fs.typeSync('/bar');
180+
expect(type, io.FileSystemEntityType.FILE);
181+
});
182+
183+
test('isLinkForSymlinkToFileAndFollowLinksFalse', () {
184+
fs.file('/foo').createSync();
185+
fs.link('/bar').createSync('/foo');
186+
var type = fs.typeSync('/bar', followLinks: false);
187+
expect(type, io.FileSystemEntityType.LINK);
188+
});
189+
190+
test('isNotFoundForNoEntityAtTail', () {
191+
var type = fs.typeSync('/foo');
192+
expect(type, io.FileSystemEntityType.NOT_FOUND);
193+
});
194+
195+
test('isNotFoundForNoDirectoryInTraversal', () {
196+
var type = fs.typeSync('/foo/bar/baz');
197+
expect(type, io.FileSystemEntityType.NOT_FOUND);
198+
});
199+
});
200+
});
201+
202+
group('Directory', () {
203+
test('uri', () {});
204+
205+
group('exists', () {
206+
test('falseWhenNotExists', () {});
207+
208+
test('trueWhenExistsAsDirectory', () {});
209+
210+
test('falseWhenExistsAsFile', () {});
211+
212+
test('trueWhenExistsAsSymlinkToDirectory', () {});
213+
214+
test('falseWhenExistsAsSymlinkToFile', () {});
215+
});
216+
217+
group('create', () {
218+
test('succeedsWhenAlreadyExistsAsDirectory', () {});
219+
220+
test('failsWhenAlreadyExistsAsFile', () {});
221+
222+
test('succeedsWhenAlreadyExistsAsSymlinkToDirectory', () {});
223+
224+
test('succeedsWhenTailDoesntExist', () {});
225+
226+
test('failsWhenAncestorDoesntExistRecursiveFalse', () {});
227+
228+
test('succeedsWhenAncestorDoesntExistRecursiveTrue', () {});
229+
});
230+
231+
group('rename', () {
232+
test('succeedsWhenDestinationDoesntExist', () {});
233+
234+
test('succeedsWhenDestinationIsEmptyDirectory', () {});
235+
236+
test('failsWhenDestinationIsFile', () {});
237+
238+
test('failsWhenDestinationParentFolderDoesntExist', () {});
239+
240+
test('failsWhenDestinationIsNonEmptyDirectory', () {});
241+
242+
test('failsWhenSourceDoesntExist', () {});
243+
244+
test('failsWhenSourceIsFile', () {});
245+
246+
test('failsWhenSourceIsSymlinkToDirectory', () {});
247+
248+
test('failsWhenDestinationIsSymlinkToEmptyDirectory', () {});
249+
});
250+
251+
group('delete', () {
252+
test('succeedsWhenEmptyDirectoryExistsAndRecursiveFalse', () {});
253+
254+
test('succeedsWhenEmptyDirectoryExistsAndRecursiveTrue', () {});
255+
256+
test('throwsWhenNonEmptyDirectoryExistsAndRecursiveFalse', () {});
257+
258+
test('succeedsWhenNonEmptyDirectoryExistsAndRecursiveTrue', () {});
259+
260+
test('throwsWhenDirectoryDoesntExistAndRecursiveFalse', () {});
261+
262+
test('throwsWhenDirectoryDoesntExistAndRecursiveTrue', () {});
263+
264+
test('succeedsWhenPathReferencesFileAndRecursiveTrue', () {});
265+
266+
test('throwsWhenPathReferencesFileAndRecursiveFalse', () {});
267+
268+
test('succeedsWhenPathReferencesLinkAndRecursiveTrue', () {});
269+
270+
test('throwsWhenPathReferencesLinkAndRecursiveFalse', () {});
271+
});
272+
273+
group('resolveSymbolicLinks', () {
274+
test('throwsIfLoopInLinkChain', () {});
275+
276+
test('throwsPathNotFoundInTraversal', () {});
277+
278+
test('throwsPathNotFoundAtTail', () {});
279+
280+
test('resolvesRelativePathToCurrentDirectory', () {});
281+
282+
test('handlesRelativeSymlinks', () {});
283+
284+
test('handlesAbsoluteSymlinks', () {});
285+
286+
test('handlesParentAndThisFolderReferences', () {});
287+
288+
test('handlesBackToBackSlashesInPath', () {});
289+
290+
test('handlesComplexPathWithMultipleSymlinks', () {});
291+
});
292+
293+
group('absolute', () {
294+
test('returnsSameEntityWhenAlreadyAbsolute', () {});
295+
296+
test('succeedsForRelativePaths', () {});
297+
});
298+
299+
group('parent', () {
300+
test('returnsRootForRoot', () {});
301+
302+
test('succeedsForNonRoot', () {});
303+
});
304+
305+
group('createTemp', () {
306+
test('throwsIfDirectoryDoesntExist', () {});
307+
308+
test('resolvesNameCollisions', () {});
309+
310+
test('succeedsWithoutPrefix', () {});
311+
312+
test('succeedsWithPrefix', () {});
313+
});
314+
315+
group('list', () {
316+
test('returnsEmptyListForEmptyDirectory', () {});
317+
318+
test('listsBasicContents', () {});
319+
320+
test('throwsIfDirectoryDoesntExist', () {});
321+
322+
test('returnsLinkObjectsIfFollowLinksFalse', () {});
323+
324+
test('followsLinksIfFollowLinksTrue', () {});
325+
326+
test('returnsLinkObjectsForSecondLinkEncounterIfFollowLinksTrue', () {});
327+
328+
test('recurseIntoDirectoriesIfRecursiveTrue', () {});
329+
330+
test('recurseIntoDirectorySymlinksIfFollowLinksTrueRecursiveTrue', () {});
331+
});
332+
});
333+
}
334+
335+
Matcher isFileSystemException([String msg]) => new _FileSystemException(msg);
336+
Matcher throwsFileSystemException([String msg]) =>
337+
new Throws(isFileSystemException(msg));
338+
339+
void expectFileSystemException(String msg, void callback()) {
340+
expect(callback, throwsFileSystemException(msg));
341+
}
342+
343+
class _FileSystemException extends Matcher {
344+
final String msg;
345+
const _FileSystemException(this.msg);
346+
347+
Description describe(Description description) =>
348+
description.add('FileSystemException with msg "$msg"');
349+
350+
bool matches(item, Map matchState) {
351+
if (item is io.FileSystemException) {
352+
return (msg == null ||
353+
item.message.contains(msg) ||
354+
item.osError.message.contains(msg));
355+
}
356+
return false;
357+
}
358+
}

0 commit comments

Comments
 (0)