|
1 /* |
|
2 * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 */ |
|
23 |
|
24 /* @test |
|
25 * @bug 4313887 |
|
26 * @summary Unit test for java.nio.file.SecureDirectoryStream |
|
27 * @library .. |
|
28 */ |
|
29 |
|
30 import java.nio.file.*; |
|
31 import static java.nio.file.StandardOpenOption.*; |
|
32 import static java.nio.file.LinkOption.*; |
|
33 import java.nio.file.attribute.*; |
|
34 import java.nio.channels.*; |
|
35 import java.io.IOException; |
|
36 import java.util.*; |
|
37 |
|
38 public class SecureDS { |
|
39 static boolean supportsLinks; |
|
40 |
|
41 public static void main(String[] args) throws IOException { |
|
42 Path dir = TestUtil.createTemporaryDirectory(); |
|
43 try { |
|
44 DirectoryStream stream = dir.newDirectoryStream(); |
|
45 stream.close(); |
|
46 if (!(stream instanceof SecureDirectoryStream)) { |
|
47 System.out.println("SecureDirectoryStream not supported."); |
|
48 return; |
|
49 } |
|
50 |
|
51 supportsLinks = TestUtil.supportsLinks(dir); |
|
52 |
|
53 // run tests |
|
54 doBasicTests(dir); |
|
55 doMoveTests(dir); |
|
56 miscTests(dir); |
|
57 |
|
58 } finally { |
|
59 TestUtil.removeAll(dir); |
|
60 } |
|
61 } |
|
62 |
|
63 // Exercise each of SecureDirectoryStream's method (except move) |
|
64 static void doBasicTests(Path dir) throws IOException { |
|
65 Path dir1 = dir.resolve("dir1").createDirectory(); |
|
66 Path dir2 = dir.resolve("dir2"); |
|
67 |
|
68 // create a file, directory, and two sym links in the directory |
|
69 Path fileEntry = Paths.get("myfile"); |
|
70 dir1.resolve(fileEntry).createFile(); |
|
71 Path dirEntry = Paths.get("mydir"); |
|
72 dir1.resolve(dirEntry).createDirectory(); |
|
73 // myfilelink -> myfile |
|
74 Path link1Entry = Paths.get("myfilelink"); |
|
75 if (supportsLinks) |
|
76 dir1.resolve(link1Entry).createSymbolicLink(fileEntry); |
|
77 // mydirlink -> mydir |
|
78 Path link2Entry = Paths.get("mydirlink"); |
|
79 if (supportsLinks) |
|
80 dir1.resolve(link2Entry).createSymbolicLink(dirEntry); |
|
81 |
|
82 // open directory and then move it so that it is no longer accessible |
|
83 // via its original path. |
|
84 SecureDirectoryStream stream = |
|
85 (SecureDirectoryStream)dir1.newDirectoryStream(); |
|
86 dir1.moveTo(dir2); |
|
87 |
|
88 // Test: iterate over all entries |
|
89 int count = 0; |
|
90 for (Path entry: stream) { count++; } |
|
91 assertTrue(count == (supportsLinks ? 4 : 2)); |
|
92 |
|
93 // Test: getFileAttributeView to access directory's attributes |
|
94 assertTrue(stream |
|
95 .getFileAttributeView(BasicFileAttributeView.class) |
|
96 .readAttributes() |
|
97 .isDirectory()); |
|
98 |
|
99 // Test: dynamic access to directory's attributes |
|
100 BasicFileAttributeView view = stream. |
|
101 getFileAttributeView(BasicFileAttributeView.class); |
|
102 Map<String,?> attrs = view.readAttributes("*"); |
|
103 assertTrue((Boolean)attrs.get("isDirectory")); |
|
104 attrs = view.readAttributes("isRegularFile", "size"); |
|
105 assertTrue(!(Boolean)attrs.get("isRegularFile")); |
|
106 assertTrue((Long)attrs.get("size") >= 0); |
|
107 int linkCount = (Integer)view.getAttribute("linkCount"); |
|
108 assertTrue(linkCount > 0); |
|
109 view.setAttribute("lastModifiedTime", 0L); |
|
110 |
|
111 // Test: getFileAttributeView to access attributes of entries |
|
112 assertTrue(stream |
|
113 .getFileAttributeView(fileEntry, BasicFileAttributeView.class) |
|
114 .readAttributes() |
|
115 .isRegularFile()); |
|
116 assertTrue(stream |
|
117 .getFileAttributeView(fileEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS) |
|
118 .readAttributes() |
|
119 .isRegularFile()); |
|
120 assertTrue(stream |
|
121 .getFileAttributeView(dirEntry, BasicFileAttributeView.class) |
|
122 .readAttributes() |
|
123 .isDirectory()); |
|
124 assertTrue(stream |
|
125 .getFileAttributeView(dirEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS) |
|
126 .readAttributes() |
|
127 .isDirectory()); |
|
128 if (supportsLinks) { |
|
129 assertTrue(stream |
|
130 .getFileAttributeView(link1Entry, BasicFileAttributeView.class) |
|
131 .readAttributes() |
|
132 .isRegularFile()); |
|
133 assertTrue(stream |
|
134 .getFileAttributeView(link1Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS) |
|
135 .readAttributes() |
|
136 .isSymbolicLink()); |
|
137 assertTrue(stream |
|
138 .getFileAttributeView(link2Entry, BasicFileAttributeView.class) |
|
139 .readAttributes() |
|
140 .isDirectory()); |
|
141 assertTrue(stream |
|
142 .getFileAttributeView(link2Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS) |
|
143 .readAttributes() |
|
144 .isSymbolicLink()); |
|
145 } |
|
146 |
|
147 // Test: dynamic access to entry attributes |
|
148 view = stream |
|
149 .getFileAttributeView(fileEntry, PosixFileAttributeView.class, NOFOLLOW_LINKS); |
|
150 if (view != null) { |
|
151 attrs = view.readAttributes("owner", "size"); |
|
152 UserPrincipal owner = (UserPrincipal)attrs.get("owner"); |
|
153 assertTrue(owner != null); |
|
154 assertTrue((Long)attrs.get("size") >= 0L); |
|
155 view.setAttribute("lastAccessTime", 0L); |
|
156 } |
|
157 |
|
158 // Test: newByteChannel |
|
159 Set<StandardOpenOption> opts = Collections.emptySet(); |
|
160 stream.newByteChannel(fileEntry, opts).close(); |
|
161 if (supportsLinks) { |
|
162 stream.newByteChannel(link1Entry, opts).close(); |
|
163 try { |
|
164 Set<OpenOption> mixed = new HashSet<OpenOption>(); |
|
165 mixed.add(READ); |
|
166 mixed.add(NOFOLLOW_LINKS); |
|
167 stream.newByteChannel(link1Entry, mixed).close(); |
|
168 shouldNotGetHere(); |
|
169 } catch (IOException x) { } |
|
170 } |
|
171 |
|
172 // Test: newDirectoryStream |
|
173 stream.newDirectoryStream(dirEntry, true, null).close(); |
|
174 stream.newDirectoryStream(dirEntry, false, null).close(); |
|
175 if (supportsLinks) { |
|
176 stream.newDirectoryStream(link2Entry, true, null).close(); |
|
177 try { |
|
178 stream.newDirectoryStream(link2Entry, false, null).close(); |
|
179 shouldNotGetHere(); |
|
180 } catch (IOException x) { } |
|
181 } |
|
182 |
|
183 // Test: delete |
|
184 if (supportsLinks) { |
|
185 stream.deleteFile(link1Entry); |
|
186 stream.deleteFile(link2Entry); |
|
187 } |
|
188 stream.deleteDirectory(dirEntry); |
|
189 stream.deleteFile(fileEntry); |
|
190 |
|
191 // Test: remove |
|
192 // (requires resetting environment to get new iterator) |
|
193 stream.close(); |
|
194 dir2.moveTo(dir1); |
|
195 dir1.resolve(fileEntry).createFile(); |
|
196 stream = (SecureDirectoryStream)dir1.newDirectoryStream(); |
|
197 dir1.moveTo(dir2); |
|
198 Iterator<Path> iter = stream.iterator(); |
|
199 int removed = 0; |
|
200 while (iter.hasNext()) { |
|
201 iter.next(); |
|
202 iter.remove(); |
|
203 removed++; |
|
204 } |
|
205 assertTrue(removed == 1); |
|
206 |
|
207 // clean-up |
|
208 stream.close(); |
|
209 dir2.delete(); |
|
210 } |
|
211 |
|
212 // Exercise SecureDirectoryStream's move method |
|
213 static void doMoveTests(Path dir) throws IOException { |
|
214 Path dir1 = dir.resolve("dir1").createDirectory(); |
|
215 Path dir2 = dir.resolve("dir2").createDirectory(); |
|
216 |
|
217 // create dir1/myfile, dir1/mydir, dir1/mylink |
|
218 Path fileEntry = Paths.get("myfile"); |
|
219 dir1.resolve(fileEntry).createFile(); |
|
220 Path dirEntry = Paths.get("mydir"); |
|
221 dir1.resolve(dirEntry).createDirectory(); |
|
222 Path linkEntry = Paths.get("mylink"); |
|
223 if (supportsLinks) |
|
224 dir1.resolve(linkEntry).createSymbolicLink(Paths.get("missing")); |
|
225 |
|
226 // target name |
|
227 Path target = Paths.get("newfile"); |
|
228 |
|
229 // open stream to both directories |
|
230 SecureDirectoryStream stream1 = |
|
231 (SecureDirectoryStream)dir1.newDirectoryStream(); |
|
232 SecureDirectoryStream stream2 = |
|
233 (SecureDirectoryStream)dir2.newDirectoryStream(); |
|
234 |
|
235 // Test: move dir1/myfile -> dir2/newfile |
|
236 stream1.move(fileEntry, stream2, target); |
|
237 assertTrue(dir1.resolve(fileEntry).notExists()); |
|
238 assertTrue(dir2.resolve(target).exists()); |
|
239 stream2.deleteFile(target); |
|
240 |
|
241 // Test: move dir1/mydir -> dir2/newfile |
|
242 stream1.move(dirEntry, stream2, target); |
|
243 assertTrue(dir1.resolve(dirEntry).notExists()); |
|
244 assertTrue(dir2.resolve(target).exists()); |
|
245 stream2.deleteDirectory(target); |
|
246 |
|
247 // Test: move dir1/mylink -> dir2/newfile |
|
248 if (supportsLinks) { |
|
249 stream1.move(linkEntry, stream2, target); |
|
250 assertTrue(dir2.resolve(target) |
|
251 .getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS) |
|
252 .readAttributes() |
|
253 .isSymbolicLink()); |
|
254 stream2.deleteFile(target); |
|
255 } |
|
256 |
|
257 // Test: move between devices |
|
258 String testDirAsString = System.getProperty("test.dir"); |
|
259 if (testDirAsString != null) { |
|
260 Path testDir = Paths.get(testDirAsString); |
|
261 if (!dir1.getFileStore().equals(testDir.getFileStore())) { |
|
262 SecureDirectoryStream ts = |
|
263 (SecureDirectoryStream)testDir.newDirectoryStream(); |
|
264 dir1.resolve(fileEntry).createFile(); |
|
265 try { |
|
266 stream1.move(fileEntry, ts, target); |
|
267 shouldNotGetHere(); |
|
268 } catch (AtomicMoveNotSupportedException x) { } |
|
269 ts.close(); |
|
270 stream1.deleteFile(fileEntry); |
|
271 } |
|
272 } |
|
273 |
|
274 // clean-up |
|
275 dir1.delete(); |
|
276 dir2.delete(); |
|
277 } |
|
278 |
|
279 // null and ClosedDirectoryStreamException |
|
280 static void miscTests(Path dir) throws IOException { |
|
281 Path file = Paths.get("file"); |
|
282 dir.resolve(file).createFile(); |
|
283 |
|
284 SecureDirectoryStream stream = |
|
285 (SecureDirectoryStream)dir.newDirectoryStream(); |
|
286 |
|
287 // NullPointerException |
|
288 try { |
|
289 stream.getFileAttributeView(null); |
|
290 shouldNotGetHere(); |
|
291 } catch (NullPointerException x) { } |
|
292 try { |
|
293 stream.getFileAttributeView(null, BasicFileAttributeView.class); |
|
294 shouldNotGetHere(); |
|
295 } catch (NullPointerException x) { } |
|
296 try { |
|
297 stream.getFileAttributeView(file, null); |
|
298 shouldNotGetHere(); |
|
299 } catch (NullPointerException x) { } |
|
300 try { |
|
301 stream.newByteChannel(null, EnumSet.of(CREATE,WRITE)); |
|
302 shouldNotGetHere(); |
|
303 } catch (NullPointerException x) { } |
|
304 try { |
|
305 stream.newByteChannel(null, EnumSet.of(CREATE,WRITE,null)); |
|
306 shouldNotGetHere(); |
|
307 } catch (NullPointerException x) { } |
|
308 try { |
|
309 stream.newByteChannel(file, null); |
|
310 shouldNotGetHere(); |
|
311 } catch (NullPointerException x) { } |
|
312 try { |
|
313 stream.move(null, stream, file); |
|
314 shouldNotGetHere(); |
|
315 } catch (NullPointerException x) { } |
|
316 try { |
|
317 stream.move(file, null, file); |
|
318 shouldNotGetHere(); |
|
319 } catch (NullPointerException x) { } |
|
320 try { |
|
321 stream.move(file, stream, null); |
|
322 shouldNotGetHere(); |
|
323 } catch (NullPointerException x) { } |
|
324 try { |
|
325 stream.newDirectoryStream(null, true, null); |
|
326 shouldNotGetHere(); |
|
327 } catch (NullPointerException x) { } |
|
328 try { |
|
329 stream.deleteFile(null); |
|
330 shouldNotGetHere(); |
|
331 } catch (NullPointerException x) { } |
|
332 try { |
|
333 stream.deleteDirectory(null); |
|
334 shouldNotGetHere(); |
|
335 } catch (NullPointerException x) { } |
|
336 |
|
337 // close stream |
|
338 stream.close(); |
|
339 stream.close(); // should be no-op |
|
340 |
|
341 // ClosedDirectoryStreamException |
|
342 try { |
|
343 stream.newDirectoryStream(file, true, null); |
|
344 shouldNotGetHere(); |
|
345 } catch (ClosedDirectoryStreamException x) { } |
|
346 try { |
|
347 stream.newByteChannel(file, EnumSet.of(READ)); |
|
348 shouldNotGetHere(); |
|
349 } catch (ClosedDirectoryStreamException x) { } |
|
350 try { |
|
351 stream.move(file, stream, file); |
|
352 shouldNotGetHere(); |
|
353 } catch (ClosedDirectoryStreamException x) { } |
|
354 try { |
|
355 stream.deleteFile(file); |
|
356 shouldNotGetHere(); |
|
357 } catch (ClosedDirectoryStreamException x) { } |
|
358 |
|
359 // clean-up |
|
360 dir.resolve(file).delete(); |
|
361 } |
|
362 |
|
363 static void assertTrue(boolean b) { |
|
364 if (!b) throw new RuntimeException("Assertion failed"); |
|
365 } |
|
366 |
|
367 static void shouldNotGetHere() { |
|
368 assertTrue(false); |
|
369 } |
|
370 } |