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.apache.log4j.Logger
19import org.mockftpserver.core.util.IoUtil
20
21/**
22 * Tests for DefaultFileSystem
23 *
24 * @version $Revision: $ - $Date: $
25 *
26 * @author Chris Mair
27 */
28class DefaultFileSystemTest extends AbstractFileSystemTest {
29
30     static final LOG = Logger.getLogger(DefaultFileSystemTest)
31     static final EXISTING_FILENAME = "TestFile.txt"
32     static final NEW_FILENAME = "NewFile.txt"
33
34     private File newFile
35     private DefaultFileSystem defaultFileSystem
36
37     DefaultFileSystemTest() {
38         EXISTING_DIR = "testdir"
39         EXISTING_FILE = EXISTING_DIR + "/" + EXISTING_FILENAME
40         NEW_DIR = EXISTING_DIR + "/" + AbstractFileSystemTest.NEW_DIRNAME
41         NEW_FILE = EXISTING_DIR + "/" + NEW_FILENAME
42         NO_SUCH_DIR = "x:/xx/yy"
43         NO_SUCH_FILE = "x:/xx/yy/zz.txt"
44     }
45
46     void testExists_WithRoot() {
47         defaultFileSystem.setRoot(EXISTING_DIR)
48         assert defaultFileSystem.exists(EXISTING_FILENAME)
49     }
50
51     void testIsDirectory_WithRoot() {
52         defaultFileSystem.setRoot(EXISTING_DIR)
53         assert defaultFileSystem.isDirectory("")
54     }
55
56     void testIsFile_WithRoot() {
57         defaultFileSystem.setRoot(EXISTING_DIR)
58         assert defaultFileSystem.isFile(EXISTING_FILENAME)
59     }
60
61     void testCreateDirectory_WithRoot() {
62         defaultFileSystem.setRoot(EXISTING_DIR)
63         assert defaultFileSystem.createDirectory(NEW_FILENAME)
64         assert newFile.exists()
65     }
66
67     void testCreateFile_WithRoot() {
68         defaultFileSystem.setRoot(EXISTING_DIR)
69         assert defaultFileSystem.createFile(NEW_FILENAME)
70         assert newFile.exists()
71     }
72
73     void testCreateInputStream_WithRoot() {
74         defaultFileSystem.setRoot(EXISTING_DIR)
75         InputStream input = defaultFileSystem.createInputStream(EXISTING_FILENAME)
76         assert EXISTING_FILE_CONTENTS.getBytes() == IoUtil.readBytes(input)
77     }
78
79     void testCreateOutputStream_WithRoot() {
80         defaultFileSystem.setRoot(EXISTING_DIR)
81         OutputStream out = defaultFileSystem.createOutputStream(NEW_FILENAME, false)
82         out.write(EXISTING_FILE_CONTENTS.getBytes())
83         out.close()
84         assert EXISTING_FILE_CONTENTS.getBytes() == readFileContents(EXISTING_DIR + "/" + NEW_FILENAME)
85     }
86
87     void testListNames_WithRoot() {
88         assert defaultFileSystem.createDirectory(NEW_DIR)
89         assert defaultFileSystem.createFile(p(NEW_DIR, FILENAME1))
90         assert defaultFileSystem.createFile(p(NEW_DIR, FILENAME2))
91
92         defaultFileSystem.setRoot(EXISTING_DIR)
93         LOG.info(defaultFileSystem.listNames(NEW_DIRNAME))
94         assert [FILENAME1, FILENAME2] as Set == defaultFileSystem.listNames(NEW_DIRNAME) as Set
95     }
96
97     void testListFiles_WithRoot() {
98         final DATE = new Date()
99         assert defaultFileSystem.createDirectory(NEW_DIR)
100         assert defaultFileSystem.createFile(p(NEW_DIR,FILENAME1))
101         FileInfo fileInfo1 = FileInfo.forFile(FILENAME1, 0, DATE)
102         assert defaultFileSystem.createFile(p(NEW_DIR, FILENAME2))
103         FileInfo fileInfo2 = FileInfo.forFile(FILENAME2, 0, DATE)
104         defaultFileSystem.setRoot(EXISTING_DIR)
105         assert [fileInfo1, fileInfo2] as Set == defaultFileSystem.listFiles(NEW_DIRNAME) as Set
106     }
107
108     void testDelete_WithRoot() {
109         assert defaultFileSystem.createFile(NEW_FILE)
110         defaultFileSystem.setRoot(EXISTING_DIR)
111         assert defaultFileSystem.delete(NEW_FILENAME)
112     }
113
114     void testRename_WithRoot() {
115         defaultFileSystem.setRoot(EXISTING_DIR)
116         final String FROM_FILE = NEW_FILENAME + "2"
117         assert defaultFileSystem.createFile(FROM_FILE)
118
119         assert defaultFileSystem.rename(FROM_FILE, NEW_FILENAME)
120         assert newFile.exists()
121     }
122
123     //-------------------------------------------------------------------------
124     // Tests for path-related methods
125     //-------------------------------------------------------------------------
126
127     private static final String SEP = File.separator
128
129     void testPath() {
130        assert "" == fileSystem.path(null, null)
131        assert "abc" == fileSystem.path(null, "abc")
132        assert "abc" == fileSystem.path("abc", null)
133        assert "" == fileSystem.path("", "")
134        assert "abc" == fileSystem.path("", "abc")
135        assert "abc" == fileSystem.path("abc", "")
136        assert "abc" + SEP + "def" == fileSystem.path("abc", "def")
137        assert "abc\\def" == fileSystem.path("abc\\", "def")
138        assert "abc/def" == fileSystem.path("abc/", "def")
139        assert "abc\\def" == fileSystem.path("abc", "\\def")
140        assert "abc/def" == fileSystem.path("abc", "/def")
141     }
142
143    void testNormalize() {
144        assertEquals("<empty>", absPath(""), fileSystem.normalize(""))
145        assertEquals("abc", absPath("abc"), fileSystem.normalize("abc"))
146        assertEquals("abc\\def", absPath("abc","def"), fileSystem.normalize("abc\\def"))
147        assertEquals("abc/def", absPath("abc","def"), fileSystem.normalize("abc/def"))
148        assertEquals("abc/def/..", absPath("abc"), fileSystem.normalize("abc/def/.."))
149        assertEquals("abc\\def\\.", absPath("abc","def"), fileSystem.normalize("abc\\def\\."))
150        assertEquals("\\abc", absPath("\\abc"), fileSystem.normalize("\\abc"))
151        assertEquals("/abc", absPath("/abc"), fileSystem.normalize("/abc"))
152        assertEquals("c:\\abc", p("c:","abc"), fileSystem.normalize("c:\\abc").toLowerCase())
153        assertEquals("c:/abc", p("c:","abc"), fileSystem.normalize("c:/abc").toLowerCase())
154        assertEquals("z:/abc", p("z:","abc"), fileSystem.normalize("z:/abc").toLowerCase())
155    }
156
157    void testGetName() {
158        assertEquals("<empty>", "", fileSystem.getName(""))
159        assertEquals("abc", "abc", fileSystem.getName("abc"))
160        assertEquals("abc\\def", "def", fileSystem.getName("abc\\def"))
161        assertEquals("abc/def", "def", fileSystem.getName("abc/def"))
162        assertEquals("\\abc", "abc", fileSystem.getName("\\abc"))
163        assertEquals("/abc", "abc", fileSystem.getName("/abc"))
164        assertEquals("c:\\abc", "abc", fileSystem.getName("c:\\abc"))
165        assertEquals("c:/abc", "abc", fileSystem.getName("c:/abc"))
166        assertEquals("c:\\abc\\def", "def", fileSystem.getName("c:\\abc\\def"))
167        assertEquals("c:/abc/def", "def", fileSystem.getName("c:/abc/def"))
168    }
169
170    void testGetParent() {
171        assertEquals("<empty>", null, fileSystem.getParent(""))
172        assertEquals("abc", null, fileSystem.getParent("abc"))
173        assertEquals("abc\\def", "abc", fileSystem.getParent("abc\\def"))
174        assertEquals("abc/def", "abc", fileSystem.getParent("abc/def"))
175        assertEquals("\\abc", SEP, fileSystem.getParent("\\abc"))
176        assertEquals("/abc", SEP, fileSystem.getParent("/abc"))
177        assertEquals("c:\\abc", "c:" + SEP, fileSystem.getParent("c:\\abc"))
178        assertEquals("c:/abc", "c:" + SEP, fileSystem.getParent("c:/abc"))
179        assertEquals("c:\\abc\\def", "c:" + SEP + "abc", fileSystem.getParent("c:\\abc\\def"))
180        assertEquals("c:/abc/def", "c:" + SEP + "abc", fileSystem.getParent("c:/abc/def"))
181    }
182
183    void testIsAbsolute() {
184        def absPath = new File(".").absolutePath
185        assert fileSystem.isAbsolute(absPath)
186
187        assert !fileSystem.isAbsolute("abc")
188        assert !fileSystem.isAbsolute("c:usr")
189
190        shouldFailWithMessageContaining("path") { fileSystem.isAbsolute(null) }
191    }
192
193    //-------------------------------------------------------------------------
194    // Helper Methods
195    //-------------------------------------------------------------------------
196
197    /**
198     * Return the specified paths concatenated with the system-dependent separator in between
199     * @param p1 - the first path
200     * @param p2 - the second path
201     * @return p1 + SEPARATOR + p2
202     */
203    private String p(String p1, String p2) {
204        return p1 + SEP + p2
205    }
206
207    /**
208     * Return the absolute path for the specified relative path
209     * @param path - the relative path
210     * @return - the absolute path
211     */
212    private String absPath(String path) {
213        return new File(path).getAbsolutePath()
214    }
215
216    /**
217     * Return the absolute path for the specified relative path
218     * @param path - the relative path
219     * @return - the absolute path
220     */
221    private String absPath(String path1, String path2) {
222        return new File(p(path1, path2)).getAbsolutePath()
223    }
224
225
226
227     //-------------------------------------------------------------------------
228     // Test setup and tear-down
229     //-------------------------------------------------------------------------
230
231     /**
232      * @see org.mockftpserver.test.AbstractTest#setUp()
233      */
234     void setUp() {
235         super.setUp()
236         newFile = new File(NEW_FILE)
237         defaultFileSystem = (DefaultFileSystem) fileSystem
238     }
239
240     /**
241      * @see org.mockftpserver.test.AbstractTest#tearDown()
242      */
243     void tearDown() {
244         super.tearDown()
245         deleteDirectory(new File(EXISTING_DIR))
246     }
247
248     //-------------------------------------------------------------------------
249     // Internal Helper Methods
250     //-------------------------------------------------------------------------
251
252     /**
253      * Delete the directory and all its contents (recursively)
254      * @param dirFile - the File representing the directory to delete
255      */
256     private void deleteDirectory(File dirFile) {
257         File[] files = dirFile.listFiles()
258         files.each { file ->
259             if (file.isDirectory()) {
260                 deleteDirectory(file)
261             }
262             else {
263                 boolean deleted = file.delete()
264                 LOG.info("Deleted [" + file.getName() + "]: " + deleted)
265             }
266         }
267         boolean deleted = dirFile.delete()
268         LOG.info("Deleted [" + dirFile.getName() + "]: " + deleted)
269     }
270
271     /**
272      * Return a new instance of the FileSystem implementation class under test
273      * @return a new FileSystem instance
274      * @throws Exception
275      */
276     protected FileSystem createFileSystem() {
277         DefaultFileSystem defaultFileSystem = new DefaultFileSystem()
278         assertTrue("creating " + EXISTING_DIR, new File(EXISTING_DIR).mkdir())
279         writeFileContents(defaultFileSystem, EXISTING_FILE, EXISTING_FILE_CONTENTS.getBytes(), false)
280         return defaultFileSystem
281     }
282
283     /**
284      * Verify the contents of the file at the specified path
285      * @see org.mockftpserver.fake.filesystem.AbstractFileSystemTest#verifyFileContents(FileSystem, String, String)
286      */
287     protected void verifyFileContents(FileSystem fileSystem, String path, String expectedContents) {
288         assertEquals(path, expectedContents.getBytes(), readFileContents(path))
289     }
290
291     /**
292      * Return the contents of the file at the specified path as a byte[].
293      *
294      * @param path - the path of the file
295      * @return the contents of the file as a byte[]
296      *
297      * @throws AssertionError - if path is null
298      */
299     private byte[] readFileContents(String path) {
300         InputStream input = new FileInputStream(path)
301         return IoUtil.readBytes(input)
302     }
303
304     /**
305      * Write the specified byte[] contents to the file at the specified path.
306      * @param fileSystem - the fileSystem instance
307      * @param path - the path of the file
308      * @param contents - the contents to write to the file
309      * @param append - true if the contents should be appended to the end of the file if the file already exists
310      */
311     private void writeFileContents(FileSystem fileSystem, String path, byte[] contents, boolean append) {
312         OutputStream out = fileSystem.createOutputStream(path, append)
313         try {
314             out.write(contents)
315         }
316         finally {
317             out.close()
318         }
319     }
320}