AbstractFileSystemTestCase.groovy revision 5303c6ae1dde5f399fe48803e677942fc4326344
1/*
2 * Copyright 2008 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.mockftpserver.fake.filesystem
17
18import org.mockftpserver.test.AbstractGroovyTestCase
19
20/**
21 * Abstract superclass for tests of FileSystem implementation classes. Contains common
22 * tests and test infrastructure.
23 *
24 * @version $Revision$ - $Date$
25 *
26 * @author Chris Mair
27 */
28abstract class AbstractFileSystemTestCase extends AbstractGroovyTestCase {
29
30    public static final FILENAME1 = "File1.txt"
31    public static final FILENAME2 = "file2.txt"
32    public static final DIR1 = "dir1"
33    public static final NEW_DIRNAME = "testDir"
34    public static final ILLEGAL_FILE = "xx/yy////z!<>?*z.txt"
35    public static final EXISTING_FILE_CONTENTS = "abc 123 %^& xxx"
36    public static final DATE = new Date()
37
38    // These must be set by the concrete subclass (in its constructor)
39    protected String NEW_DIR = null
40    protected String NEW_FILE = null
41    protected String EXISTING_DIR = null
42    protected String EXISTING_FILE = null
43    protected NO_SUCH_DIR = null
44    protected NO_SUCH_FILE = null
45
46    protected FileSystem fileSystem
47
48    //-------------------------------------------------------------------------
49    // Common Tests
50    //-------------------------------------------------------------------------
51
52    void testExists() {
53        assert !fileSystem.exists(NEW_FILE)
54        assert !fileSystem.exists(NEW_DIR)
55        assert !fileSystem.exists(ILLEGAL_FILE)
56        assert fileSystem.exists(EXISTING_FILE)
57        assert fileSystem.exists(EXISTING_DIR)
58
59        shouldFailWithMessageContaining("path") { fileSystem.exists(null) }
60    }
61
62    void testIsDirectory() {
63        assert fileSystem.isDirectory(EXISTING_DIR)
64        assert !fileSystem.isDirectory(EXISTING_FILE)
65        assert !fileSystem.isDirectory(NO_SUCH_DIR)
66        assert !fileSystem.isDirectory(NO_SUCH_FILE)
67        assert !fileSystem.isDirectory(ILLEGAL_FILE)
68
69        shouldFailWithMessageContaining("path") { fileSystem.isDirectory(null) }
70    }
71
72    void testIsFile() {
73        assert fileSystem.isFile(EXISTING_FILE)
74        assert !fileSystem.isFile(EXISTING_DIR)
75        assert !fileSystem.isFile(NO_SUCH_DIR)
76        assert !fileSystem.isFile(NO_SUCH_FILE)
77        assert !fileSystem.isFile(ILLEGAL_FILE)
78
79        shouldFailWithMessageContaining("path") { fileSystem.isFile(null) }
80    }
81
82    void testAdd_Directory() {
83        assert !fileSystem.exists(NEW_DIR), "Before createDirectory"
84        fileSystem.add(new DirectoryEntry(NEW_DIR))
85        assert fileSystem.exists(NEW_DIR), "After createDirectory"
86
87        // Duplicate directory
88        shouldFail(FileSystemException) { fileSystem.add(new DirectoryEntry(NEW_DIR)) }
89
90        // The parent of the path does not exist
91        shouldFail(FileSystemException) { fileSystem.add(new DirectoryEntry(NEW_DIR + "/abc/def")) }
92
93        shouldFail(InvalidFilenameException) { fileSystem.add(new DirectoryEntry(ILLEGAL_FILE)) }
94        shouldFailWithMessageContaining("path") { fileSystem.add(new DirectoryEntry(null)) }
95    }
96
97    void testAdd_File() {
98        assert !fileSystem.exists(NEW_FILE), "Before createFile"
99        fileSystem.add(new FileEntry(NEW_FILE))
100        assert fileSystem.exists(NEW_FILE), "After createFile"
101
102        // File already exists
103        shouldFail(FileSystemException) { fileSystem.add(new FileEntry(NEW_FILE)) }
104
105        // The parent of the path does not exist
106        shouldFail(FileSystemException) { fileSystem.add(new FileEntry(NEW_DIR + "/abc/def")) }
107
108        shouldFail(FileSystemException) { fileSystem.add(new FileEntry(NO_SUCH_DIR)) }
109        shouldFail(InvalidFilenameException) { fileSystem.add(new FileEntry(ILLEGAL_FILE)) }
110
111        shouldFailWithMessageContaining("path") { fileSystem.add(new FileEntry(null)) }
112    }
113
114    void testRename_NullFromPath() {
115        shouldFailWithMessageContaining("fromPath") { fileSystem.rename(null, FILENAME1) }
116    }
117
118    void testRename_NullToPath() {
119        shouldFailWithMessageContaining("toPath") { fileSystem.rename(FILENAME1, null) }
120    }
121
122    void testListNames() {
123        fileSystem.add(new DirectoryEntry(NEW_DIR))
124        assert fileSystem.listNames(NEW_DIR) == []
125
126        fileSystem.add(new FileEntry(p(NEW_DIR, FILENAME1)))
127        fileSystem.add(new FileEntry(p(NEW_DIR, FILENAME2)))
128        fileSystem.add(new DirectoryEntry(p(NEW_DIR, DIR1)))
129        fileSystem.add(new FileEntry(p(NEW_DIR, DIR1, "/abc.def")))
130
131        List filenames = fileSystem.listNames(NEW_DIR)
132        LOG.info("filenames=" + filenames)
133        assertSameIgnoringOrder(filenames, [FILENAME1, FILENAME2, DIR1])
134
135        // Specify a filename instead of a directory name
136        assert [FILENAME1] == fileSystem.listNames(p(NEW_DIR, FILENAME1))
137
138        assert [] == fileSystem.listNames(NO_SUCH_DIR)
139
140        shouldFailWithMessageContaining("path") { fileSystem.listNames(null) }
141    }
142
143    void testListNames_Wildcards() {
144        fileSystem.add(new DirectoryEntry(NEW_DIR))
145        fileSystem.add(new FileEntry(p(NEW_DIR, 'abc.txt')))
146        fileSystem.add(new FileEntry(p(NEW_DIR, 'def.txt')))
147
148        assertSameIgnoringOrder(fileSystem.listNames(p(NEW_DIR, '*.txt')), ['abc.txt', 'def.txt'])
149        assertSameIgnoringOrder(fileSystem.listNames(p(NEW_DIR, '*')), ['abc.txt', 'def.txt'])
150        assertSameIgnoringOrder(fileSystem.listNames(p(NEW_DIR, '???.???')), ['abc.txt', 'def.txt'])
151        assertSameIgnoringOrder(fileSystem.listNames(p(NEW_DIR, '*.exe')), [])
152        assertSameIgnoringOrder(fileSystem.listNames(p(NEW_DIR, 'abc.???')), ['abc.txt'])
153        assertSameIgnoringOrder(fileSystem.listNames(p(NEW_DIR, 'a?c.?xt')), ['abc.txt'])
154        assertSameIgnoringOrder(fileSystem.listNames(p(NEW_DIR, 'd?f.*')), ['def.txt'])
155    }
156
157    void testListFiles() {
158        fileSystem.add(new DirectoryEntry(NEW_DIR))
159        assert [] == fileSystem.listFiles(NEW_DIR)
160
161        def path1 = p(NEW_DIR, FILENAME1)
162        def fileEntry1 = new FileEntry(path1)
163        fileSystem.add(fileEntry1)
164        assert fileSystem.listFiles(NEW_DIR) == [fileEntry1]
165
166        // Specify a filename instead of a directory name
167        assert fileSystem.listFiles(p(NEW_DIR, FILENAME1)) == [fileEntry1]
168
169        def fileEntry2 = new FileEntry(p(NEW_DIR, FILENAME2))
170        fileSystem.add(fileEntry2)
171        assert fileSystem.listFiles(NEW_DIR) as Set == [fileEntry1, fileEntry2] as Set
172
173        // Write to the file to get a non-zero length
174        final byte[] CONTENTS = "1234567890".getBytes()
175        OutputStream out = fileEntry1.createOutputStream(false)
176        out.write(CONTENTS)
177        out.close()
178        assert fileSystem.listFiles(NEW_DIR) as Set == [fileEntry1, fileEntry2] as Set
179
180        def dirEntry3 = new DirectoryEntry(p(NEW_DIR, DIR1))
181        fileSystem.add(dirEntry3)
182        assert fileSystem.listFiles(NEW_DIR) as Set == [fileEntry1, fileEntry2, dirEntry3] as Set
183
184        assert fileSystem.listFiles(NO_SUCH_DIR) == []
185
186        shouldFailWithMessageContaining("path") { fileSystem.listFiles(null) }
187    }
188
189    void testListFiles_Wildcards() {
190        def dirEntry = new DirectoryEntry(NEW_DIR)
191        def fileEntry1 = new FileEntry(p(NEW_DIR, 'abc.txt'))
192        def fileEntry2 = new FileEntry(p(NEW_DIR, 'def.txt'))
193
194        fileSystem.add(dirEntry)
195        fileSystem.add(fileEntry1)
196        fileSystem.add(fileEntry2)
197
198        assert fileSystem.listFiles(p(NEW_DIR, '*.txt')) as Set == [fileEntry1, fileEntry2] as Set
199        assert fileSystem.listFiles(p(NEW_DIR, '*')) as Set == [fileEntry1, fileEntry2] as Set
200        assert fileSystem.listFiles(p(NEW_DIR, '???.???')) as Set == [fileEntry1, fileEntry2] as Set
201        assert fileSystem.listFiles(p(NEW_DIR, '*.exe')) as Set == [] as Set
202        assert fileSystem.listFiles(p(NEW_DIR, 'abc.???')) as Set == [fileEntry1] as Set
203        assert fileSystem.listFiles(p(NEW_DIR, 'a?c.?xt')) as Set == [fileEntry1] as Set
204        assert fileSystem.listFiles(p(NEW_DIR, 'd?f.*')) as Set == [fileEntry2] as Set
205    }
206
207    void testDelete() {
208        fileSystem.add(new FileEntry(NEW_FILE))
209        assert fileSystem.delete(NEW_FILE)
210        assert !fileSystem.exists(NEW_FILE)
211
212        assert !fileSystem.delete(NO_SUCH_FILE)
213
214        fileSystem.add(new DirectoryEntry(NEW_DIR))
215        assert fileSystem.delete(NEW_DIR)
216        assert !fileSystem.exists(NEW_DIR)
217
218        fileSystem.add(new DirectoryEntry(NEW_DIR))
219        fileSystem.add(new FileEntry(NEW_DIR + "/abc.txt"))
220
221        assert !fileSystem.delete(NEW_DIR), "Directory containing files"
222        assert fileSystem.exists(NEW_DIR)
223
224        shouldFailWithMessageContaining("path") { fileSystem.delete(null) }
225    }
226
227    void testRename() {
228        final String FROM_FILE = NEW_FILE + "2"
229        fileSystem.add(new FileEntry(FROM_FILE))
230
231        fileSystem.rename(FROM_FILE, NEW_FILE)
232        assert fileSystem.exists(NEW_FILE)
233
234        fileSystem.add(new DirectoryEntry(NEW_DIR))
235
236        // Rename existing directory
237        final String TO_DIR = NEW_DIR + "2"
238        fileSystem.rename(NEW_DIR, TO_DIR)
239        assert !fileSystem.exists(NEW_DIR)
240        assert fileSystem.exists(TO_DIR)
241    }
242
243    void testRename_FromPathDoesNotExist() {
244        final String TO_FILE2 = NEW_FILE + "2"
245        shouldFail(FileSystemException) { fileSystem.rename(NO_SUCH_FILE, TO_FILE2) }
246        assert !fileSystem.exists(TO_FILE2), "After failed rename"
247    }
248
249    void testRename_DirectoryContainsFiles() {
250        fileSystem.add(new DirectoryEntry(NEW_DIR))
251        fileSystem.add(new FileEntry(NEW_DIR + "/a.txt"))
252        fileSystem.add(new FileEntry(NEW_DIR + "/b.txt"))
253        fileSystem.add(new DirectoryEntry(NEW_DIR + "/subdir"))
254
255        final String TO_DIR = NEW_DIR + "2"
256        fileSystem.rename(NEW_DIR, TO_DIR)
257        assert !fileSystem.exists(NEW_DIR)
258        assert !fileSystem.exists(NEW_DIR + "/a.txt")
259        assert !fileSystem.exists(NEW_DIR + "/b.txt")
260        assert !fileSystem.exists(NEW_DIR + "/subdir")
261
262        assert fileSystem.exists(TO_DIR)
263        assert fileSystem.exists(TO_DIR + "/a.txt")
264        assert fileSystem.exists(TO_DIR + "/b.txt")
265        assert fileSystem.exists(TO_DIR + "/subdir")
266    }
267
268    void testRename_ParentOfToPathDoesNotExist() throws Exception {
269        final String FROM_FILE = NEW_FILE
270        final String TO_FILE = fileSystem.path(NO_SUCH_DIR, "abc")
271        fileSystem.add(new FileEntry(FROM_FILE))
272
273        shouldFail(FileSystemException) { fileSystem.rename(FROM_FILE, TO_FILE) }
274        assert fileSystem.exists(FROM_FILE)
275        assert !fileSystem.exists(TO_FILE)
276    }
277
278    void testGetParent_Null() {
279        shouldFailWithMessageContaining("path") { fileSystem.getParent(null) }
280    }
281
282    //-------------------------------------------------------------------------
283    // Test setup
284    //-------------------------------------------------------------------------
285
286    void setUp() {
287        super.setUp()
288        fileSystem = createFileSystem()
289    }
290
291    //-------------------------------------------------------------------------
292    // Helper Methods
293    //-------------------------------------------------------------------------
294
295    private verifyEntries(List expected, List actual) {
296        expected.eachWithIndex {entry, index ->
297            def entryStr = entry.toString()
298            LOG.info("expected=$entryStr")
299            assert actual.find {actualEntry -> actualEntry.toString() == entryStr }
300        }
301    }
302
303    protected void assertSameIgnoringOrder(list1, list2) {
304        LOG.info("Comparing $list1 to $list2")
305        assert list1 as Set == list2 as Set, "list1=$list1  list2=$list2"
306    }
307
308    /**
309     * Return a new instance of the FileSystem implementation class under test
310     * @return a new FileSystem instance
311     * @throws Exception
312     */
313    protected abstract FileSystem createFileSystem()
314
315    /**
316     * Verify the contents of the file at the specified path read from its InputSteam
317     *
318     * @param fileSystem - the FileSystem instance
319     * @param expectedContents - the expected contents
320     * @throws IOException
321     */
322    protected abstract void verifyFileContents(FileSystem fileSystem, String path, String contents) throws Exception
323
324}