1 /*
2  * Copyright (C) 2016 The Android Open Source Project
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  */
16 
17 package libcore.java.nio.file;
18 
19 import org.junit.Before;
20 import org.junit.Rule;
21 import org.junit.Test;
22 
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.nio.ByteBuffer;
27 import java.nio.channels.NonReadableChannelException;
28 import java.nio.channels.NonWritableChannelException;
29 import java.nio.channels.SeekableByteChannel;
30 import java.nio.file.CopyOption;
31 import java.nio.file.DirectoryNotEmptyException;
32 import java.nio.file.DirectoryStream;
33 import java.nio.file.FileAlreadyExistsException;
34 import java.nio.file.Files;
35 import java.nio.file.NoSuchFileException;
36 import java.nio.file.NotDirectoryException;
37 import java.nio.file.OpenOption;
38 import java.nio.file.Path;
39 import java.nio.file.Paths;
40 import java.nio.file.SecureDirectoryStream;
41 import java.nio.file.attribute.FileAttribute;
42 import java.nio.file.attribute.FileTime;
43 import java.nio.file.attribute.PosixFilePermission;
44 import java.nio.file.attribute.PosixFilePermissions;
45 import java.nio.file.spi.FileSystemProvider;
46 import java.util.Arrays;
47 import java.util.HashMap;
48 import java.util.HashSet;
49 import java.util.Map;
50 import java.util.Set;
51 import java.util.concurrent.TimeUnit;
52 
53 import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
54 import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
55 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
56 import static java.nio.file.StandardOpenOption.APPEND;
57 import static java.nio.file.StandardOpenOption.CREATE;
58 import static java.nio.file.StandardOpenOption.CREATE_NEW;
59 import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE;
60 import static java.nio.file.StandardOpenOption.DSYNC;
61 import static java.nio.file.StandardOpenOption.READ;
62 import static java.nio.file.StandardOpenOption.SPARSE;
63 import static java.nio.file.StandardOpenOption.SYNC;
64 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
65 import static java.nio.file.StandardOpenOption.WRITE;
66 import static libcore.java.nio.file.FilesSetup.DATA_FILE;
67 import static libcore.java.nio.file.FilesSetup.NonStandardOption;
68 import static libcore.java.nio.file.FilesSetup.TEST_FILE_DATA;
69 import static libcore.java.nio.file.FilesSetup.TEST_FILE_DATA_2;
70 import static libcore.java.nio.file.FilesSetup.readFromFile;
71 import static libcore.java.nio.file.FilesSetup.readFromInputStream;
72 import static libcore.java.nio.file.FilesSetup.writeToFile;
73 import static org.junit.Assert.assertEquals;
74 import static org.junit.Assert.assertFalse;
75 import static org.junit.Assert.assertTrue;
76 import static org.junit.Assert.fail;
77 
78 public class DefaultFileSystemProviderTest {
79 
80     @Rule
81     public FilesSetup filesSetup = new FilesSetup();
82 
83     private FileSystemProvider provider;
84 
85     @Before
setUp()86     public void setUp() throws Exception {
87         provider = filesSetup.getDataFilePath().getFileSystem().provider();
88     }
89 
90     @Test
test_newInputStream()91     public void test_newInputStream() throws IOException {
92         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath(), READ)) {
93             assertEquals(TEST_FILE_DATA, readFromInputStream(is));
94         }
95     }
96 
97     @Test
test_newInputStream_openOption()98     public void test_newInputStream_openOption() throws IOException {
99         // Write and Append are not supported.
100         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath(), WRITE)) {
101             fail();
102         } catch (UnsupportedOperationException expected) {
103         }
104 
105         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath(), APPEND)) {
106             fail();
107         } catch (UnsupportedOperationException expected) {
108         }
109 
110         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath(),
111                 NonStandardOption.OPTION1)){
112             fail();
113         } catch (UnsupportedOperationException expected) {
114         }
115 
116         // Supported options.
117         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath(), DELETE_ON_CLOSE,
118                 CREATE_NEW, TRUNCATE_EXISTING, SPARSE, SYNC, DSYNC)) {
119             assertEquals(TEST_FILE_DATA, readFromInputStream(is));
120         }
121     }
122 
123     @Test
test_newInputStream_twice()124     public void test_newInputStream_twice() throws IOException {
125         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath(), READ);
126              // Open the same file again.
127              InputStream is2 = provider.newInputStream(filesSetup.getDataFilePath(), READ)) {
128 
129             assertEquals(TEST_FILE_DATA, readFromInputStream(is));
130             assertEquals(TEST_FILE_DATA, readFromInputStream(is2));
131         }
132     }
133 
134     @Test
test_newInputStream_NPE()135     public void test_newInputStream_NPE() throws IOException {
136         try (InputStream is = provider.newInputStream(null)){
137             fail();
138         } catch (NullPointerException expected) {}
139 
140         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath(),
141                 (OpenOption[]) null)) {
142             fail();
143         } catch (NullPointerException expected) {}
144     }
145 
146     @Test
test_newOutputStream()147     public void test_newOutputStream() throws IOException {
148         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath())) {
149             os.write(TEST_FILE_DATA.getBytes());
150         }
151 
152         try (InputStream is = provider.newInputStream(filesSetup.getTestPath())) {
153             assertEquals(TEST_FILE_DATA, readFromInputStream(is));
154         }
155     }
156 
157     @Test
test_newOutputStream_openOption_READ()158     public void test_newOutputStream_openOption_READ() throws IOException {
159         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath(), READ)) {
160             fail();
161         } catch (IllegalArgumentException expected) {
162         }
163     }
164 
165     @Test
test_newOutputStream_openOption_APPEND()166     public void test_newOutputStream_openOption_APPEND() throws IOException {
167         // When file exists and it contains data.
168         try (OutputStream os = provider.newOutputStream(filesSetup.getDataFilePath(), APPEND)) {
169             os.write(TEST_FILE_DATA.getBytes());
170         }
171 
172         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath())) {
173             assertEquals(TEST_FILE_DATA + TEST_FILE_DATA, readFromInputStream(is));
174         }
175 
176         // When file doesn't exist.
177         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath(), APPEND)) {
178             fail();
179         } catch (NoSuchFileException expected) {
180             assertTrue(expected.getMessage().contains(filesSetup.getTestPath().toString()));
181         }
182     }
183 
184     @Test
test_newOutputStream_openOption_TRUNCATE()185     public void test_newOutputStream_openOption_TRUNCATE() throws IOException {
186         // When file exists.
187         try (OutputStream os = provider.newOutputStream(filesSetup.getDataFilePath(),
188                 TRUNCATE_EXISTING)) {
189             os.write(TEST_FILE_DATA_2.getBytes());
190         }
191 
192         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath())) {
193             assertEquals(TEST_FILE_DATA_2, readFromInputStream(is));
194         }
195 
196         // When file doesn't exist.
197         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath(),
198                 TRUNCATE_EXISTING)) {
199             fail();
200         } catch (NoSuchFileException expected) {
201             assertTrue(expected.getMessage().contains(filesSetup.getTestPath().toString()));
202         }
203     }
204 
205     @Test
test_newOutputStream_openOption_WRITE()206     public void test_newOutputStream_openOption_WRITE() throws IOException {
207         // When file exists.
208         try (OutputStream os = provider.newOutputStream(filesSetup.getDataFilePath(), WRITE)) {
209             os.write(TEST_FILE_DATA_2.getBytes());
210         }
211 
212         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath())) {
213             String expectedFileData = TEST_FILE_DATA_2 +
214                     TEST_FILE_DATA.substring(TEST_FILE_DATA_2.length());
215             assertEquals(expectedFileData, readFromInputStream(is));
216         }
217 
218         // When file doesn't exist.
219         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath(), WRITE)) {
220             fail();
221         } catch (NoSuchFileException expected) {
222             assertTrue(expected.getMessage().contains(filesSetup.getTestPath().toString()));
223         }
224     }
225 
226     @Test
test_newOutputStream_openOption_CREATE()227     public void test_newOutputStream_openOption_CREATE() throws IOException {
228         // When file exists.
229         try (OutputStream os = provider.newOutputStream(filesSetup.getDataFilePath(), CREATE)) {
230             os.write(TEST_FILE_DATA_2.getBytes());
231         }
232 
233         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath())) {
234             String expectedFileData = TEST_FILE_DATA_2 +
235                     TEST_FILE_DATA.substring(TEST_FILE_DATA_2.length());
236             assertEquals(expectedFileData, readFromInputStream(is));
237         }
238 
239         // When file doesn't exist.
240         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath(), CREATE)) {
241             os.write(TEST_FILE_DATA.getBytes());
242         }
243 
244         try (InputStream is = provider.newInputStream(filesSetup.getTestPath())) {
245             assertEquals(TEST_FILE_DATA, readFromInputStream(is));
246         }
247     }
248 
249     @Test
test_newOutputStream_openOption_CREATE_NEW()250     public void test_newOutputStream_openOption_CREATE_NEW() throws IOException {
251         // When file exists.
252         try (OutputStream os = provider.newOutputStream(filesSetup.getDataFilePath(), CREATE_NEW)) {
253             fail();
254         } catch (FileAlreadyExistsException expected) {
255         }
256 
257         // When file doesn't exist.
258         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath(), CREATE_NEW)) {
259             os.write(TEST_FILE_DATA.getBytes());
260         }
261 
262         try (InputStream is = provider.newInputStream(filesSetup.getTestPath())) {
263             assertEquals(TEST_FILE_DATA, readFromInputStream(is));
264         }
265     }
266 
267     @Test
test_newOutputStream_openOption_SYNC()268     public void test_newOutputStream_openOption_SYNC() throws IOException {
269         // The data should be written to the file
270         try (OutputStream os = provider.newOutputStream(filesSetup.getTestPath(), CREATE, SYNC);
271              InputStream is = provider.newInputStream(filesSetup.getTestPath(), SYNC)) {
272                 os.write(TEST_FILE_DATA.getBytes());
273                 assertEquals(TEST_FILE_DATA, readFromInputStream(is));
274         }
275     }
276 
277     @Test
test_newOutputStream_NPE()278     public void test_newOutputStream_NPE() throws IOException {
279         try (OutputStream os = provider.newOutputStream(null)) {
280             fail();
281         } catch (NullPointerException expected) {}
282 
283         try (OutputStream os = provider
284                 .newOutputStream(filesSetup.getTestPath(), (OpenOption[]) null)) {
285             fail();
286         } catch (NullPointerException expected) {}
287     }
288 
289     @Test
test_newByteChannel()290     public void test_newByteChannel() throws IOException {
291         Set<OpenOption> set = new HashSet<OpenOption>();
292 
293         // When file doesn't exist
294         try (SeekableByteChannel sbc = provider.newByteChannel(filesSetup.getTestPath(), set)) {
295             fail();
296         } catch (NoSuchFileException expected) {
297             assertTrue(expected.getMessage().contains(filesSetup.getTestPath().toString()));
298         }
299 
300         // When file exists.
301 
302         // File opens in READ mode by default. The channel is non writable by default.
303         try (SeekableByteChannel sbc = provider.newByteChannel(filesSetup.getDataFilePath(), set)) {
304             sbc.write(ByteBuffer.allocate(10));
305             fail();
306         } catch (NonWritableChannelException expected) {
307         }
308 
309         // Read a file.
310         try (SeekableByteChannel sbc = provider.newByteChannel(filesSetup.getDataFilePath(), set)) {
311             ByteBuffer readBuffer = ByteBuffer.allocate(10);
312             int bytesReadCount = sbc.read(readBuffer);
313 
314             String readData = new String(Arrays.copyOf(readBuffer.array(), bytesReadCount),
315                     "UTF-8");
316             assertEquals(TEST_FILE_DATA, readData);
317         }
318     }
319 
320     /**
321      * Behaviour of newByteChannel when called with OpenOption#WRITE.
322      * @throws IOException
323      */
324     @Test
test_newByteChannel_openOption_WRITE()325     public void test_newByteChannel_openOption_WRITE() throws IOException {
326         Set<OpenOption> set = new HashSet<OpenOption>();
327         set.add(WRITE);
328 
329         // When file doesn't exist
330         try (SeekableByteChannel sbc = provider.newByteChannel(filesSetup.getTestPath(), set)) {
331             fail();
332         } catch (NoSuchFileException expected) {
333             assertTrue(expected.getMessage().contains(filesSetup.getTestPath().toString()));
334         }
335 
336 
337         // When file exists.
338         try (SeekableByteChannel sbc = provider.newByteChannel(filesSetup.getDataFilePath(), set)) {
339             sbc.read(ByteBuffer.allocate(10));
340             fail();
341         } catch (NonReadableChannelException expected) {
342         }
343 
344         // Write in file.
345         try (SeekableByteChannel sbc = provider.newByteChannel(filesSetup.getDataFilePath(), set)) {
346             sbc.write(ByteBuffer.wrap(TEST_FILE_DATA_2.getBytes()));
347         }
348 
349         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath())) {
350             String expectedFileData = TEST_FILE_DATA_2 +
351                     TEST_FILE_DATA.substring(TEST_FILE_DATA_2.length());
352             assertEquals(expectedFileData, readFromInputStream(is));
353         }
354     }
355 
356     /**
357      * Check behaviour when newByteChannel is called with WRITE, READ and SYNC.
358      * @throws IOException
359      */
360     @Test
test_newByteChannel_openOption_WRITE_READ()361     public void test_newByteChannel_openOption_WRITE_READ() throws IOException {
362         Set<OpenOption> set = new HashSet<OpenOption>();
363         set.add(WRITE);
364         set.add(READ);
365         set.add(SYNC);
366 
367         try (SeekableByteChannel sbc = provider.newByteChannel(filesSetup.getDataFilePath(), set)) {
368             ByteBuffer readBuffer = ByteBuffer.allocate(10);
369             int bytesReadCount = sbc.read(readBuffer);
370 
371             String readData = new String(Arrays.copyOf(readBuffer.array(), bytesReadCount),
372                     "UTF-8");
373             assertEquals(TEST_FILE_DATA, readData);
374 
375             // Pointer will move to the end of the file after read operation. The write should
376             // append the data at the end of the file.
377             sbc.write(ByteBuffer.wrap(TEST_FILE_DATA_2.getBytes()));
378         }
379 
380         try (InputStream is = provider.newInputStream(filesSetup.getDataFilePath())) {
381             String expectedFileData = TEST_FILE_DATA + TEST_FILE_DATA_2;
382             assertEquals(expectedFileData, readFromInputStream(is));
383         }
384     }
385 
386     @Test
test_newByteChannel_NPE()387     public void test_newByteChannel_NPE() throws IOException {
388         Set<OpenOption> set = new HashSet<OpenOption>();
389         try (SeekableByteChannel sbc = provider.newByteChannel(null, set)) {
390             fail();
391         } catch(NullPointerException expected) {}
392 
393         try (SeekableByteChannel sbc = provider
394                 .newByteChannel(filesSetup.getDataFilePath(), null)) {
395             fail();
396         } catch(NullPointerException expected) {}
397     }
398 
399     @Test
test_createDirectory()400     public void test_createDirectory() throws IOException {
401         // Check if createDirectory is actually creating a directory.
402         Path newDirectory = filesSetup.getPathInTestDir("newDir");
403         assertFalse(Files.exists(newDirectory));
404         assertFalse(Files.isDirectory(newDirectory));
405 
406         provider.createDirectory(newDirectory);
407 
408         assertTrue(Files.exists(newDirectory));
409         assertTrue(Files.isDirectory(newDirectory));
410 
411         // Expecting exception when directory already exists.
412         try {
413             provider.createDirectory(newDirectory);
414             fail();
415         } catch (FileAlreadyExistsException expected) {
416         }
417 
418         // File with unicode name.
419         Path unicodeFilePath = filesSetup.getPathInTestDir("टेस्ट डायरेक्टरी");
420         provider.createDirectory(unicodeFilePath);
421         assertTrue(Files.exists(unicodeFilePath));
422     }
423 
424     @Test
test_createDirectory$String$FileAttr()425     public void test_createDirectory$String$FileAttr() throws IOException {
426         Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
427         FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm);
428         provider.createDirectory(filesSetup.getTestPath(), attr);
429         assertEquals(attr.value(), Files.getAttribute(filesSetup.getTestPath(), attr.name()));
430 
431         // Creating a new file and passing multiple attribute of the same name.
432         perm = PosixFilePermissions.fromString("rw-------");
433         FileAttribute<Set<PosixFilePermission>> attr1 = PosixFilePermissions.asFileAttribute(perm);
434         Path dirPath2 = filesSetup.getPathInTestDir("new_file");
435         provider.createDirectory(dirPath2, attr, attr1);
436         // Value should be equal to the last attribute passed.
437         assertEquals(attr1.value(), Files.getAttribute(dirPath2, attr.name()));
438     }
439 
440     @Test
test_createDirectory$String$FileAttr_NPE()441     public void test_createDirectory$String$FileAttr_NPE() throws IOException {
442         Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
443         FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm);
444         try {
445             provider.createDirectory(null, attr);
446             fail();
447         } catch(NullPointerException expected) {}
448 
449         try {
450             provider.createDirectory(filesSetup.getTestPath(), (FileAttribute<?>[]) null);
451             fail();
452         } catch(NullPointerException expected) {}
453     }
454 
455     @Test
test_createDirectory_NPE()456     public void test_createDirectory_NPE() throws IOException {
457         try {
458             provider.createDirectory(null);
459             fail();
460         } catch (NullPointerException expected) {}
461     }
462 
463     @Test
test_createSymbolicLink()464     public void test_createSymbolicLink() throws IOException {
465         provider.createSymbolicLink(/* Path of the symbolic link */ filesSetup.getTestPath(),
466                 /* Path of the target of the symbolic link */
467                 filesSetup.getDataFilePath().toAbsolutePath());
468         assertTrue(Files.isSymbolicLink(filesSetup.getTestPath()));
469 
470         // When file exists at the sym link location.
471         try {
472             provider.createSymbolicLink(/* Path of the symbolic link */ filesSetup.getTestPath(),
473                     /* Path of the target of the symbolic link */
474                     filesSetup.getDataFilePath().toAbsolutePath());
475             fail();
476         } catch (FileAlreadyExistsException expected) {} finally {
477             Files.deleteIfExists(filesSetup.getTestPath());
478         }
479 
480         // Sym link to itself
481         provider.createSymbolicLink(/* Path of the symbolic link */ filesSetup.getTestPath(),
482                 /* Path of the target of the symbolic link */
483                 filesSetup.getTestPath().toAbsolutePath());
484         assertTrue(Files.isSymbolicLink(filesSetup.getTestPath().toAbsolutePath()));
485     }
486 
487     @Test
test_createSymbolicLink_NPE()488     public void test_createSymbolicLink_NPE() throws IOException {
489         try {
490             provider.createSymbolicLink(null, filesSetup.getDataFilePath().toAbsolutePath());
491             fail();
492         } catch (NullPointerException expected) {}
493 
494         try {
495             provider.createSymbolicLink(filesSetup.getTestPath(), null);
496             fail();
497         } catch (NullPointerException expected) {}
498     }
499 
500     @Test
test_createSymbolicLink$Path$Attr()501     public void test_createSymbolicLink$Path$Attr() throws IOException {
502         try {
503             Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
504             FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions
505                     .asFileAttribute(perm);
506             provider.createSymbolicLink(filesSetup.getTestPath(),
507                     filesSetup.getDataFilePath().toAbsolutePath(), attr);
508             fail();
509         } catch (UnsupportedOperationException expected) {}
510     }
511 
512     @Test
test_createSymbolicLink$Path$Attr_NPE()513     public void test_createSymbolicLink$Path$Attr_NPE() throws IOException {
514         Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
515         FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions
516                 .asFileAttribute(perm);
517 
518         try {
519             provider.createSymbolicLink(null, filesSetup.getDataFilePath().toAbsolutePath(), attr);
520             fail();
521         } catch (NullPointerException expected) {}
522 
523         try {
524             provider.createSymbolicLink(filesSetup.getTestPath(), null, attr);
525             fail();
526 
527         } catch (NullPointerException expected) {}
528 
529         try {
530             provider.createSymbolicLink(filesSetup.getTestPath(), filesSetup.getDataFilePath(),
531                     (FileAttribute<?>[]) null);
532             fail();
533         } catch (NullPointerException expected) {}
534     }
535 
536     @Test
test_delete()537     public void test_delete() throws IOException {
538         // Delete existing file.
539         provider.delete(filesSetup.getDataFilePath());
540         assertFalse(Files.exists(filesSetup.getDataFilePath()));
541 
542         // Delete non existing files.
543         try {
544             provider.delete(filesSetup.getTestPath());
545             fail();
546         } catch (NoSuchFileException expected) {
547             assertTrue(expected.getMessage().contains(filesSetup.getTestPath().toString()));
548         }
549 
550         // Delete a directory.
551         Path dirPath = filesSetup.getPathInTestDir("dir");
552         Files.createDirectory(dirPath);
553         provider.delete(dirPath);
554         assertFalse(Files.exists(dirPath));
555 
556 
557         // Delete a non empty directory.
558         Files.createDirectory(dirPath);
559         Files.createFile(filesSetup.getPathInTestDir("dir/file"));
560         try {
561             provider.delete(dirPath);
562             fail();
563         } catch (DirectoryNotEmptyException expected) {}
564     }
565 
566     @Test
test_delete_NPE()567     public void test_delete_NPE() throws IOException {
568         try {
569             provider.delete(null);
570             fail();
571         } catch(NullPointerException expected) {}
572     }
573 
574     @Test
test_deleteIfExist()575     public void test_deleteIfExist() throws IOException {
576         // Delete existing file.
577         assertTrue(Files.deleteIfExists(filesSetup.getDataFilePath()));
578         assertFalse(Files.exists(filesSetup.getDataFilePath()));
579 
580         // Delete non existing files.
581         assertFalse(Files.deleteIfExists(filesSetup.getTestPath()));
582 
583         // Delete a directory.
584         Path dirPath = filesSetup.getPathInTestDir("dir");
585         Files.createDirectory(dirPath);
586         assertTrue(Files.deleteIfExists(dirPath));
587         assertFalse(Files.exists(dirPath));
588 
589         // Delete a non empty directory.
590         Files.createDirectory(dirPath);
591         Files.createFile(filesSetup.getPathInTestDir("dir/file"));
592         try {
593             provider.deleteIfExists(dirPath);
594             fail();
595         } catch (DirectoryNotEmptyException expected) {}
596     }
597 
598     @Test
test_deleteIfExist_NPE()599     public void test_deleteIfExist_NPE() throws IOException {
600         try {
601             provider.deleteIfExists(null);
602             fail();
603         } catch(NullPointerException expected) {}
604     }
605 
606     @Test
test_copy()607     public void test_copy() throws IOException {
608         provider.copy(filesSetup.getDataFilePath(), filesSetup.getTestPath());
609         assertEquals(TEST_FILE_DATA, readFromFile(filesSetup.getTestPath()));
610         // The original file should also exists.
611         assertEquals(TEST_FILE_DATA, readFromFile(filesSetup.getDataFilePath()));
612 
613         // When target file exists.
614         try {
615             provider.copy(filesSetup.getDataFilePath(), filesSetup.getTestPath());
616             fail();
617         } catch (FileAlreadyExistsException expected) {}
618 
619         // Copy to existing target file with REPLACE_EXISTING copy option.
620         writeToFile(filesSetup.getDataFilePath(), TEST_FILE_DATA_2);
621         provider.copy(filesSetup.getDataFilePath(), filesSetup.getTestPath(), REPLACE_EXISTING);
622         assertEquals(TEST_FILE_DATA_2, readFromFile(filesSetup.getTestPath()));
623 
624 
625         // Copy to the same file. Should not fail.
626         filesSetup.reset();
627         provider.copy(filesSetup.getDataFilePath(), filesSetup.getDataFilePath());
628         assertEquals(TEST_FILE_DATA, readFromFile(filesSetup.getDataFilePath()));
629 
630         // With target is a symbolic link file.
631         try {
632             filesSetup.reset();
633             Path symlink = filesSetup.getPathInTestDir("symlink");
634             Path newFile = filesSetup.getPathInTestDir("newDir");
635             Files.createFile(newFile);
636             assertTrue(Files.exists(newFile));
637             Files.createSymbolicLink(symlink, filesSetup.getDataFilePath());
638             provider.copy(filesSetup.getDataFilePath(), symlink);
639             fail();
640         } catch (FileAlreadyExistsException expected) {}
641 
642         filesSetup.reset();
643         try {
644             provider.copy(filesSetup.getTestPath(), filesSetup.getDataFilePath(), REPLACE_EXISTING);
645             fail();
646         } catch (NoSuchFileException expected) {
647             assertTrue(expected.getMessage().contains(filesSetup.getTestPath().toString()));
648         }
649     }
650 
651     @Test
test_copy_NPE()652     public void test_copy_NPE() throws IOException {
653         try {
654             provider.copy((Path) null, filesSetup.getTestPath());
655             fail();
656         } catch(NullPointerException expected) {}
657 
658         try {
659             provider.copy(filesSetup.getDataFilePath(), (Path) null);
660             fail();
661         } catch(NullPointerException expected) {}
662 
663         try {
664             provider.copy(filesSetup.getDataFilePath(), filesSetup.getTestPath(),
665                     (CopyOption[]) null);
666             fail();
667         } catch(NullPointerException expected) {}
668     }
669 
670     @Test
test_copy_CopyOption()671     public void test_copy_CopyOption() throws IOException {
672         // COPY_ATTRIBUTES
673         FileTime fileTime = FileTime.fromMillis(System.currentTimeMillis() - 10000);
674         Files.setAttribute(filesSetup.getDataFilePath(), "basic:lastModifiedTime", fileTime);
675         provider.copy(filesSetup.getDataFilePath(), filesSetup.getTestPath(), COPY_ATTRIBUTES);
676         assertEquals(fileTime.to(TimeUnit.SECONDS),
677                 ((FileTime) Files.getAttribute(filesSetup.getTestPath(),
678                         "basic:lastModifiedTime")).to(TimeUnit.SECONDS));
679         assertEquals(TEST_FILE_DATA, readFromFile(filesSetup.getTestPath()));
680 
681         // ATOMIC_MOVE
682         Files.deleteIfExists(filesSetup.getTestPath());
683         try {
684             provider.copy(filesSetup.getDataFilePath(), filesSetup.getTestPath(), ATOMIC_MOVE);
685             fail();
686         } catch (UnsupportedOperationException expected) {}
687 
688         Files.deleteIfExists(filesSetup.getTestPath());
689         try {
690             provider.copy(filesSetup.getDataFilePath(), filesSetup.getTestPath(),
691                     NonStandardOption.OPTION1);
692             fail();
693         } catch (UnsupportedOperationException expected) {}
694     }
695 
696     @Test
test_copy_directory()697     public void test_copy_directory() throws IOException {
698         final Path dirPath = filesSetup.getPathInTestDir("dir1");
699         final Path dirPath2 = filesSetup.getPathInTestDir("dir2");
700         // Nested directory.
701         final Path dirPath3 = filesSetup.getPathInTestDir("dir1/dir");
702 
703         // Create dir1 and dir1/dir, and copying dir1/dir to dir2. Copy will create dir2, however,
704         // it will not copy the content of the source directory.
705         Files.createDirectory(dirPath);
706         Files.createDirectory(dirPath3);
707         provider.copy(filesSetup.getDataFilePath(),
708                 filesSetup.getPathInTestDir("dir1/" + DATA_FILE));
709         provider.copy(dirPath, dirPath2);
710         assertTrue(Files.exists(dirPath2));
711 
712         Map<Path, Boolean> pathMap = new HashMap<>();
713         try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(dirPath2)) {
714             directoryStream.forEach(file -> pathMap.put(file, true));
715         }
716 
717         // The files are not copied. The command is equivalent of creating a new directory.
718         assertEquals(0, pathMap.size());
719 
720 
721         // When the target directory is not empty.
722         Path dirPath4 = filesSetup.getPathInTestDir("dir4");
723         Files.createDirectories(dirPath4);
724         Path file = Paths.get("file");
725         Files.createFile(Paths.get(dirPath.toString(), file.toString()));
726         Files.createFile(Paths.get(dirPath4.toString(), file.toString()));
727 
728         try {
729             provider.copy(dirPath, dirPath4, REPLACE_EXISTING);
730             fail();
731         } catch (DirectoryNotEmptyException expected) {}
732     }
733 
734     @Test
test_newDirectoryStream$Path$Filter()735     public void test_newDirectoryStream$Path$Filter() throws IOException {
736 
737         // Initial setup of directory.
738         Path path_root = filesSetup.getPathInTestDir("dir");
739         Path path_dir1 = filesSetup.getPathInTestDir("dir/dir1");
740         Path path_dir2 = filesSetup.getPathInTestDir("dir/dir2");
741         Path path_dir3 = filesSetup.getPathInTestDir("dir/dir3");
742 
743         Path path_f1 = filesSetup.getPathInTestDir("dir/f1");
744         Path path_f2 = filesSetup.getPathInTestDir("dir/f2");
745         Path path_f3 = filesSetup.getPathInTestDir("dir/f3");
746 
747         Files.createDirectory(path_root);
748         Files.createDirectory(path_dir1);
749         Files.createDirectory(path_dir2);
750         Files.createDirectory(path_dir3);
751         Files.createFile(path_f1);
752         Files.createFile(path_f2);
753         Files.createFile(path_f3);
754 
755         HashSet<Path> pathsSet = new HashSet<>();
756         HashSet<Path> expectedPathsSet = new HashSet<>();
757 
758         expectedPathsSet.add(path_dir1);
759         expectedPathsSet.add(path_dir2);
760         expectedPathsSet.add(path_dir3);
761 
762         // Filter all the directories.
763         try (DirectoryStream<Path> directoryStream = provider.newDirectoryStream(path_root,
764                 file -> Files.isDirectory(file))) {
765             assertTrue(directoryStream instanceof SecureDirectoryStream);
766             directoryStream.forEach(path -> pathsSet.add(path));
767 
768             assertEquals(expectedPathsSet, pathsSet);
769         }
770     }
771 
772     /**
773      * Tests exceptions for the newDirectoryStream(Path, DirectoryStream.Filter) method
774      * - NoSuchFileException & NoDirectoryException.
775      * @throws IOException
776      */
777     @Test
test_newDirectoryStream$Filter_Exception()778     public void test_newDirectoryStream$Filter_Exception() throws IOException {
779         // Non existent directory.
780         Path path_dir1 = filesSetup.getPathInTestDir("newDir1");
781         DirectoryStream.Filter<Path> fileFilter = new DirectoryStream.Filter<Path>() {
782             @Override
783             public boolean accept(Path entry) throws IOException {
784                 return Files.isDirectory(entry);
785             }
786         };
787 
788         try (DirectoryStream<Path> directoryStream = provider.newDirectoryStream(path_dir1,
789                 fileFilter)) {
790             fail();
791         } catch (NoSuchFileException expected) {
792             assertTrue(expected.getMessage().contains(path_dir1.toString()));
793         }
794 
795         // File instead of directory.
796         Path path_file1 = filesSetup.getPathInTestDir("newFile1");
797         Files.createFile(path_file1);
798         try (DirectoryStream<Path> directoryStream = provider.newDirectoryStream(path_file1,
799                 fileFilter)) {
800             fail();
801         } catch (NotDirectoryException expected) {
802         }
803     }
804 
805     @Test
test_newDirectoryStream$Filter_NPE()806     public void test_newDirectoryStream$Filter_NPE() throws IOException {
807         DirectoryStream.Filter<Path> fileFilter = new DirectoryStream.Filter<Path>() {
808             @Override
809             public boolean accept(Path entry) throws IOException {
810                 return Files.isDirectory(entry);
811             }
812         };
813         try (DirectoryStream<Path> directoryStream = provider.newDirectoryStream(null,
814                 fileFilter)) {
815             fail();
816         } catch (NullPointerException expected) {
817         }
818 
819         // Non existent directory.
820         Path path_dir1 = filesSetup.getPathInTestDir("newDir1");
821         try (DirectoryStream<Path> directoryStream = provider.newDirectoryStream(path_dir1,
822                 (DirectoryStream.Filter<? super Path>) null)) {
823             fail();
824         } catch (NullPointerException expected) {
825         }
826     }
827 }
828