View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2;
18  
19  import org.junit.Test;
20  
21  /**
22   * Test cases for file naming.
23   * <p>
24   * TODO - Add tests for all FileName methods.
25   */
26  public class NamingTests extends AbstractProviderTestCase {
27  
28      /**
29       * Asserts that a particular relative name is invalid for a particular scope.
30       */
31      private void assertBadName(final FileName name, final String relName, final NameScope scope) {
32          try {
33              getManager().resolveName(name, relName, scope);
34              fail("expected failure");
35          } catch (final FileSystemException e) {
36              // TODO - should check error message
37          }
38      }
39  
40      /**
41       * Checks that a relative name resolves to the expected absolute path. Tests both forward and back slashes.
42       */
43      private void assertSameName(final String expectedPath, final FileName baseName, final String relName)
44              throws Exception {
45          assertSameName(expectedPath, baseName, relName, NameScope.FILE_SYSTEM);
46      }
47  
48      /**
49       * Checks that a relative name resolves to the expected absolute path. Tests both forward and back slashes.
50       */
51      private void assertSameName(final String expectedPath, final FileName baseName, final String relName,
52              final NameScope scope) throws Exception {
53          // Try the supplied name
54          FileName name = getManager().resolveName(baseName, relName, scope);
55          assertEquals(expectedPath, name.getPath());
56  
57          String temp;
58  
59          // Replace the separators
60          temp = relName.replace('\\', '/');
61          name = getManager().resolveName(baseName, temp, scope);
62          assertEquals(expectedPath, name.getPath());
63  
64          // And again
65          temp = relName.replace('/', '\\');
66          name = getManager().resolveName(baseName, temp, scope);
67          assertEquals(expectedPath, name.getPath());
68      }
69  
70      /**
71       * Tests resolution of absolute names.
72       */
73      private void checkAbsoluteNames(final FileName name) throws Exception {
74          // Root
75          assertSameName("/", name, "/");
76          assertSameName("/", name, "//");
77          assertSameName("/", name, "/.");
78          assertSameName("/", name, "/some file/..");
79  
80          // Some absolute names
81          assertSameName("/a", name, "/a");
82          assertSameName("/a", name, "/./a");
83          assertSameName("/a", name, "/a/.");
84          assertSameName("/a/b", name, "/a/b");
85  
86          // Some bad names
87          assertBadName(name, "/..", NameScope.FILE_SYSTEM);
88          assertBadName(name, "/a/../..", NameScope.FILE_SYSTEM);
89      }
90  
91      /**
92       * Name resolution tests that are common for CHILD or DESCENDENT scope.
93       */
94      private void checkDescendentNames(final FileName name, final NameScope scope) throws Exception {
95          // Make some assumptions about the name
96          assertFalse(name.getPath().equals("/"));
97          assertFalse(name.getPath().endsWith("/a"));
98          assertFalse(name.getPath().endsWith("/a/b"));
99  
100         // Test names with the same prefix
101         final String path = name.getPath() + "/a";
102         assertSameName(path, name, path, scope);
103         assertSameName(path, name, "../" + name.getBaseName() + "/a", scope);
104 
105         // Test an empty name
106         assertBadName(name, "", scope);
107 
108         // Test . name
109         assertBadName(name, ".", scope);
110         assertBadName(name, "./", scope);
111 
112         // Test ancestor names
113         assertBadName(name, "..", scope);
114         assertBadName(name, "../a", scope);
115         assertBadName(name, "../" + name.getBaseName() + "a", scope);
116         assertBadName(name, "a/..", scope);
117 
118         // Test absolute names
119         assertBadName(name, "/", scope);
120         assertBadName(name, "/a", scope);
121         assertBadName(name, "/a/b", scope);
122         assertBadName(name, name.getPath(), scope);
123         assertBadName(name, name.getPath() + "a", scope);
124     }
125 
126     /**
127      * Tests conversion from absolute to relative names.
128      */
129     @Test
130     public void testAbsoluteNameConvert() throws Exception {
131         final FileName baseName = getReadFolder().getName();
132 
133         String path = "/test1/test2";
134         FileName name = getManager().resolveName(baseName, path);
135         assertEquals(path, name.getPath());
136 
137         // Try child and descendent names
138         testRelName(name, "child");
139         testRelName(name, "child1/child2");
140 
141         // Try own name
142         testRelName(name, ".");
143 
144         // Try parent, and root
145         testRelName(name, "..");
146         testRelName(name, "../..");
147 
148         // Try sibling and descendent of sibling
149         testRelName(name, "../sibling");
150         testRelName(name, "../sibling/child");
151 
152         // Try siblings with similar names
153         testRelName(name, "../test2_not");
154         testRelName(name, "../test2_not/child");
155         testRelName(name, "../test");
156         testRelName(name, "../test/child");
157 
158         // Try unrelated
159         testRelName(name, "../../unrelated");
160         testRelName(name, "../../test");
161         testRelName(name, "../../test/child");
162 
163         // Test against root
164         path = "/";
165         name = getManager().resolveName(baseName, path);
166         assertEquals(path, name.getPath());
167 
168         // Try child and descendent names (against root)
169         testRelName(name, "child");
170         testRelName(name, "child1/child2");
171 
172         // Try own name (against root)
173         testRelName(name, ".");
174     }
175 
176     /**
177      * Tests resolution of absolute names.
178      */
179     @Test
180     public void testAbsoluteNames() throws Exception {
181         // Test against the base folder
182         FileName name = getReadFolder().getName();
183         checkAbsoluteNames(name);
184 
185         // Test against the root
186         name = getReadFolder().getFileSystem().getRoot().getName();
187         checkAbsoluteNames(name);
188 
189         // Test against some unknown file
190         name = getManager().resolveName(name, "a/b/unknown");
191         checkAbsoluteNames(name);
192     }
193 
194     /**
195      * Tests child file names.
196      */
197     @Test
198     public void testChildName() throws Exception {
199         final FileName baseName = getReadFolder().getName();
200         final String basePath = baseName.getPath();
201         final FileName name = getManager().resolveName(baseName, "some-child", NameScope.CHILD);
202 
203         // Test path is absolute
204         assertTrue("is absolute", basePath.startsWith("/"));
205 
206         // Test base name
207         assertEquals("base name", "some-child", name.getBaseName());
208 
209         // Test absolute path
210         assertEquals("absolute path", basePath + "/some-child", name.getPath());
211 
212         // Test parent path
213         assertEquals("parent absolute path", basePath, name.getParent().getPath());
214 
215         // Try using a compound name to find a child
216         assertBadName(name, "a/b", NameScope.CHILD);
217 
218         // Check other invalid names
219         checkDescendentNames(name, NameScope.CHILD);
220     }
221 
222     /**
223      * Tests descendent name resolution.
224      */
225     @Test
226     public void testDescendentName() throws Exception {
227         final FileName baseName = getReadFolder().getName();
228 
229         // Test direct child
230         String path = baseName.getPath() + "/some-child";
231         assertSameName(path, baseName, "some-child", NameScope.DESCENDENT);
232 
233         // Test compound name
234         path = path + "/grand-child";
235         assertSameName(path, baseName, "some-child/grand-child", NameScope.DESCENDENT);
236 
237         // Test relative names
238         assertSameName(path, baseName, "./some-child/grand-child", NameScope.DESCENDENT);
239         assertSameName(path, baseName, "./nada/../some-child/grand-child", NameScope.DESCENDENT);
240         assertSameName(path, baseName, "some-child/./grand-child", NameScope.DESCENDENT);
241 
242         // Test badly formed descendent names
243         checkDescendentNames(baseName, NameScope.DESCENDENT);
244     }
245 
246     /**
247      * Tests relative name resolution, relative to the base folder.
248      */
249     @Test
250     public void testNameResolution() throws Exception {
251         final FileName baseName = getReadFolder().getName();
252         final String parentPath = baseName.getParent().getPath();
253         final String path = baseName.getPath();
254         final String childPath = path + "/some-child";
255 
256         // Test empty relative path
257         assertSameName(path, baseName, "");
258 
259         // Test . relative path
260         assertSameName(path, baseName, ".");
261 
262         // Test ./ relative path
263         assertSameName(path, baseName, "./");
264 
265         // Test .// relative path
266         assertSameName(path, baseName, ".//");
267 
268         // Test .///.///. relative path
269         assertSameName(path, baseName, ".///.///.");
270         assertSameName(path, baseName, "./\\/.\\//.");
271 
272         // Test <elem>/.. relative path
273         assertSameName(path, baseName, "a/..");
274 
275         // Test .. relative path
276         assertSameName(parentPath, baseName, "..");
277 
278         // Test ../ relative path
279         assertSameName(parentPath, baseName, "../");
280 
281         // Test ..//./ relative path
282         assertSameName(parentPath, baseName, "..//./");
283         assertSameName(parentPath, baseName, "..//.\\");
284 
285         // Test <elem>/../.. relative path
286         assertSameName(parentPath, baseName, "a/../..");
287 
288         // Test <elem> relative path
289         assertSameName(childPath, baseName, "some-child");
290 
291         // Test ./<elem> relative path
292         assertSameName(childPath, baseName, "./some-child");
293 
294         // Test ./<elem>/ relative path
295         assertSameName(childPath, baseName, "./some-child/");
296 
297         // Test <elem>/././././ relative path
298         assertSameName(childPath, baseName, "./some-child/././././");
299 
300         // Test <elem>/../<elem> relative path
301         assertSameName(childPath, baseName, "a/../some-child");
302 
303         // Test <elem>/<elem>/../../<elem> relative path
304         assertSameName(childPath, baseName, "a/b/../../some-child");
305     }
306 
307     /**
308      * Tests resolution of relative file names via the FS manager
309      */
310     @Test
311     public void testRelativeURI() throws Exception {
312         // Build base dir
313         getManager().setBaseFile(getReadFolder());
314 
315         // Locate the base dir
316         FileObject file = getManager().resolveFile(".");
317         assertSame("file object", getReadFolder(), file);
318 
319         // Locate a child
320         file = getManager().resolveFile("some-child");
321         assertSame("file object", getReadFolder(), file.getParent());
322 
323         // Locate a descendent
324         file = getManager().resolveFile("some-folder/some-file");
325         assertSame("file object", getReadFolder(), file.getParent().getParent());
326 
327         // Locate parent
328         file = getManager().resolveFile("..");
329         assertSame("file object", getReadFolder().getParent(), file);
330 
331         // free basefile
332         getManager().setBaseFile((FileObject) null);
333     }
334 
335     /**
336      * Tests encoding of relative URI.
337      */
338     @Test
339     public void testRelativeUriEncoding() throws Exception {
340         // Build base dir
341         getManager().setBaseFile(getReadFolder());
342         final String path = getReadFolder().getName().getPath();
343 
344         // §1 Encode "some file"
345         FileObject file = getManager().resolveFile("%73%6f%6d%65%20%66%69%6c%65");
346         assertEquals(path + "/some file", file.getName().getPathDecoded());
347 
348         // §2 Encode "."
349         file = getManager().resolveFile("%2e");
350         // 18-6-2005 imario@apache.org: no need to keep the "current directory"
351         // assertEquals(path + "/.", file.getName().getPathDecoded());
352         assertEquals(path, file.getName().getPathDecoded());
353 
354         // §3 Encode '%'
355         file = getManager().resolveFile("a%25");
356         assertEquals(path + "/a%", file.getName().getPathDecoded());
357 
358         // §4 Encode /
359         file = getManager().resolveFile("dir%2fchild");
360         assertEquals(path + "/dir/child", file.getName().getPathDecoded());
361 
362         // §5 Encode \
363         file = getManager().resolveFile("dir%5cchild");
364         // 18-6-2005 imario@apache.org: all file separators normalized to "/"
365         // decided to do this to get the same behavior as in §4 on windows
366         // platforms
367         // assertEquals(path + "/dir\\child", file.getName().getPathDecoded());
368         assertEquals(path + "/dir/child", file.getName().getPathDecoded());
369 
370         // §6 Use "%" literal
371         try {
372             getManager().resolveFile("%");
373             fail();
374         } catch (final FileSystemException e) {
375         }
376 
377         // §7 Not enough digits in encoded char
378         try {
379             getManager().resolveFile("%5");
380             fail();
381         } catch (final FileSystemException e) {
382         }
383 
384         // §8 Invalid digit in encoded char
385         try {
386             getManager().resolveFile("%q");
387             fail();
388         } catch (final FileSystemException e) {
389         }
390 
391         // free basefile
392         getManager().setBaseFile((FileObject) null);
393     }
394 
395     /**
396      * Checks that a file name converts to an expected relative path
397      */
398     private void testRelName(final FileName baseName, final String relPath) throws Exception {
399         final FileName expectedName = getManager().resolveName(baseName, relPath);
400 
401         // Convert to relative path, and check
402         final String actualRelPath = baseName.getRelativeName(expectedName);
403         assertEquals(relPath, actualRelPath);
404     }
405 
406     /**
407      * Tests the root file name.
408      */
409     @Test
410     public void testRootFileName() throws Exception {
411         // Locate the root file
412         final FileName rootName = getReadFolder().getFileSystem().getRoot().getName();
413 
414         // Test that the root path is "/"
415         assertEquals("root path", "/", rootName.getPath());
416 
417         // Test that the root basname is ""
418         assertEquals("root base name", "", rootName.getBaseName());
419 
420         // Test that the root name has no parent
421         assertNull("root parent", rootName.getParent());
422     }
423 }