• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
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 com.google.common.jimfs;
18 
19 import static com.google.common.jimfs.TestUtils.bytes;
20 import static com.google.common.jimfs.TestUtils.permutations;
21 import static com.google.common.jimfs.TestUtils.preFilledBytes;
22 import static com.google.common.primitives.Bytes.concat;
23 import static com.google.common.truth.Truth.assertThat;
24 import static java.nio.charset.StandardCharsets.UTF_8;
25 import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
26 import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
27 import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
28 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
29 import static java.nio.file.StandardOpenOption.APPEND;
30 import static java.nio.file.StandardOpenOption.CREATE;
31 import static java.nio.file.StandardOpenOption.CREATE_NEW;
32 import static java.nio.file.StandardOpenOption.DSYNC;
33 import static java.nio.file.StandardOpenOption.READ;
34 import static java.nio.file.StandardOpenOption.SPARSE;
35 import static java.nio.file.StandardOpenOption.SYNC;
36 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
37 import static java.nio.file.StandardOpenOption.WRITE;
38 import static java.util.concurrent.TimeUnit.MILLISECONDS;
39 import static org.junit.Assert.assertArrayEquals;
40 import static org.junit.Assert.assertEquals;
41 import static org.junit.Assert.assertFalse;
42 import static org.junit.Assert.assertTrue;
43 import static org.junit.Assert.fail;
44 
45 import com.google.common.collect.ImmutableList;
46 import com.google.common.collect.ImmutableSet;
47 import com.google.common.collect.Iterables;
48 import com.google.common.collect.Iterators;
49 import com.google.common.collect.Ordering;
50 import com.google.common.io.ByteStreams;
51 import com.google.common.io.CharStreams;
52 import com.google.common.primitives.Bytes;
53 import com.google.common.util.concurrent.Uninterruptibles;
54 import java.io.ByteArrayInputStream;
55 import java.io.ByteArrayOutputStream;
56 import java.io.IOException;
57 import java.io.InputStream;
58 import java.io.OutputStream;
59 import java.io.Reader;
60 import java.io.Writer;
61 import java.net.URI;
62 import java.nio.ByteBuffer;
63 import java.nio.channels.AsynchronousFileChannel;
64 import java.nio.channels.FileChannel;
65 import java.nio.channels.NonReadableChannelException;
66 import java.nio.channels.NonWritableChannelException;
67 import java.nio.channels.SeekableByteChannel;
68 import java.nio.file.ClosedDirectoryStreamException;
69 import java.nio.file.DirectoryNotEmptyException;
70 import java.nio.file.DirectoryStream;
71 import java.nio.file.FileAlreadyExistsException;
72 import java.nio.file.FileStore;
73 import java.nio.file.FileSystem;
74 import java.nio.file.FileSystemException;
75 import java.nio.file.FileSystems;
76 import java.nio.file.Files;
77 import java.nio.file.NoSuchFileException;
78 import java.nio.file.NotDirectoryException;
79 import java.nio.file.NotLinkException;
80 import java.nio.file.Path;
81 import java.nio.file.Paths;
82 import java.nio.file.SecureDirectoryStream;
83 import java.nio.file.attribute.BasicFileAttributeView;
84 import java.nio.file.attribute.BasicFileAttributes;
85 import java.nio.file.attribute.FileAttribute;
86 import java.nio.file.attribute.FileTime;
87 import java.nio.file.attribute.PosixFilePermission;
88 import java.nio.file.attribute.PosixFilePermissions;
89 import java.nio.file.attribute.UserPrincipal;
90 import java.util.Arrays;
91 import java.util.Iterator;
92 import java.util.Set;
93 import java.util.regex.PatternSyntaxException;
94 import org.junit.Test;
95 import org.junit.runner.RunWith;
96 import org.junit.runners.JUnit4;
97 
98 /**
99  * Tests an in-memory file system through the public APIs in {@link Files}, etc. This also acts as
100  * the tests for {@code FileSystemView}, as each public API method is (mostly) implemented by a
101  * method in {@code FileSystemView}.
102  *
103  * <p>These tests uses a Unix-like file system, but most of what they test applies to any file
104  * system configuration.
105  *
106  * @author Colin Decker
107  */
108 @RunWith(JUnit4.class)
109 public class JimfsUnixLikeFileSystemTest extends AbstractJimfsIntegrationTest {
110 
111   private static final Configuration UNIX_CONFIGURATION =
112       Configuration.unix().toBuilder()
113           .setAttributeViews("basic", "owner", "posix", "unix")
114           .setMaxSize(1024 * 1024 * 1024) // 1 GB
115           .setMaxCacheSize(256 * 1024 * 1024) // 256 MB
116           .build();
117 
118   @Override
createFileSystem()119   protected FileSystem createFileSystem() {
120     return Jimfs.newFileSystem("unix", UNIX_CONFIGURATION);
121   }
122 
123   @Test
testFileSystem()124   public void testFileSystem() {
125     assertThat(fs.getSeparator()).isEqualTo("/");
126     assertThat(fs.getRootDirectories())
127         .containsExactlyElementsIn(ImmutableSet.of(path("/")))
128         .inOrder();
129     assertThat(fs.isOpen()).isTrue();
130     assertThat(fs.isReadOnly()).isFalse();
131     assertThat(fs.supportedFileAttributeViews()).containsExactly("basic", "owner", "posix", "unix");
132     assertThat(fs.provider()).isInstanceOf(JimfsFileSystemProvider.class);
133   }
134 
135   @Test
testFileStore()136   public void testFileStore() throws IOException {
137     FileStore fileStore = Iterables.getOnlyElement(fs.getFileStores());
138     assertThat(fileStore.name()).isEqualTo("jimfs");
139     assertThat(fileStore.type()).isEqualTo("jimfs");
140     assertThat(fileStore.isReadOnly()).isFalse();
141 
142     long totalSpace = 1024 * 1024 * 1024; // 1 GB
143     assertThat(fileStore.getTotalSpace()).isEqualTo(totalSpace);
144     assertThat(fileStore.getUnallocatedSpace()).isEqualTo(totalSpace);
145     assertThat(fileStore.getUsableSpace()).isEqualTo(totalSpace);
146 
147     Files.write(fs.getPath("/foo"), new byte[10000]);
148 
149     assertThat(fileStore.getTotalSpace()).isEqualTo(totalSpace);
150 
151     // We wrote 10000 bytes, but since the file system allocates fixed size blocks, more than 10k
152     // bytes may have been allocated. As such, the unallocated space after the write can be at most
153     // maxUnallocatedSpace.
154     assertThat(fileStore.getUnallocatedSpace() <= totalSpace - 10000).isTrue();
155 
156     // Usable space is at most unallocated space. (In this case, it's currently exactly unallocated
157     // space, but that's not required.)
158     assertThat(fileStore.getUsableSpace() <= fileStore.getUnallocatedSpace()).isTrue();
159 
160     Files.delete(fs.getPath("/foo"));
161     assertThat(fileStore.getTotalSpace()).isEqualTo(totalSpace);
162     assertThat(fileStore.getUnallocatedSpace()).isEqualTo(totalSpace);
163     assertThat(fileStore.getUsableSpace()).isEqualTo(totalSpace);
164   }
165 
166   @Test
testPaths()167   public void testPaths() {
168     assertThatPath("/").isAbsolute().and().hasRootComponent("/").and().hasNoNameComponents();
169     assertThatPath("foo").isRelative().and().hasNameComponents("foo");
170     assertThatPath("foo/bar").isRelative().and().hasNameComponents("foo", "bar");
171     assertThatPath("/foo/bar/baz")
172         .isAbsolute()
173         .and()
174         .hasRootComponent("/")
175         .and()
176         .hasNameComponents("foo", "bar", "baz");
177   }
178 
179   @Test
testPaths_equalityIsCaseSensitive()180   public void testPaths_equalityIsCaseSensitive() {
181     assertThatPath("foo").isNotEqualTo(path("FOO"));
182   }
183 
184   @Test
testPaths_areSortedCaseSensitive()185   public void testPaths_areSortedCaseSensitive() {
186     Path p1 = path("a");
187     Path p2 = path("B");
188     Path p3 = path("c");
189     Path p4 = path("D");
190 
191     assertThat(Ordering.natural().immutableSortedCopy(Arrays.asList(p3, p4, p1, p2)))
192         .isEqualTo(ImmutableList.of(p2, p4, p1, p3));
193 
194     // would be p1, p2, p3, p4 if sorting were case insensitive
195   }
196 
197   @Test
testPaths_resolve()198   public void testPaths_resolve() {
199     assertThatPath(path("/").resolve("foo/bar"))
200         .isAbsolute()
201         .and()
202         .hasRootComponent("/")
203         .and()
204         .hasNameComponents("foo", "bar");
205     assertThatPath(path("foo/bar").resolveSibling("baz"))
206         .isRelative()
207         .and()
208         .hasNameComponents("foo", "baz");
209     assertThatPath(path("foo/bar").resolve("/one/two"))
210         .isAbsolute()
211         .and()
212         .hasRootComponent("/")
213         .and()
214         .hasNameComponents("one", "two");
215   }
216 
217   @Test
testPaths_normalize()218   public void testPaths_normalize() {
219     assertThatPath(path("foo/bar/..").normalize()).isRelative().and().hasNameComponents("foo");
220     assertThatPath(path("foo/./bar/../baz/test/./../stuff").normalize())
221         .isRelative()
222         .and()
223         .hasNameComponents("foo", "baz", "stuff");
224     assertThatPath(path("../../foo/./bar").normalize())
225         .isRelative()
226         .and()
227         .hasNameComponents("..", "..", "foo", "bar");
228     assertThatPath(path("foo/../../bar").normalize())
229         .isRelative()
230         .and()
231         .hasNameComponents("..", "bar");
232     assertThatPath(path(".././..").normalize()).isRelative().and().hasNameComponents("..", "..");
233   }
234 
235   @Test
testPaths_relativize()236   public void testPaths_relativize() {
237     assertThatPath(path("/foo/bar").relativize(path("/foo/bar/baz")))
238         .isRelative()
239         .and()
240         .hasNameComponents("baz");
241     assertThatPath(path("/foo/bar/baz").relativize(path("/foo/bar")))
242         .isRelative()
243         .and()
244         .hasNameComponents("..");
245     assertThatPath(path("/foo/bar/baz").relativize(path("/foo/baz/bar")))
246         .isRelative()
247         .and()
248         .hasNameComponents("..", "..", "baz", "bar");
249     assertThatPath(path("foo/bar").relativize(path("foo")))
250         .isRelative()
251         .and()
252         .hasNameComponents("..");
253     assertThatPath(path("foo").relativize(path("foo/bar")))
254         .isRelative()
255         .and()
256         .hasNameComponents("bar");
257 
258     try {
259       Path unused = path("/foo/bar").relativize(path("bar"));
260       fail();
261     } catch (IllegalArgumentException expected) {
262     }
263 
264     try {
265       Path unused = path("bar").relativize(path("/foo/bar"));
266       fail();
267     } catch (IllegalArgumentException expected) {
268     }
269   }
270 
271   @Test
testPaths_startsWith_endsWith()272   public void testPaths_startsWith_endsWith() {
273     assertThat(path("/foo/bar").startsWith("/")).isTrue();
274     assertThat(path("/foo/bar").startsWith("/foo")).isTrue();
275     assertThat(path("/foo/bar").startsWith("/foo/bar")).isTrue();
276     assertThat(path("/foo/bar").endsWith("bar")).isTrue();
277     assertThat(path("/foo/bar").endsWith("foo/bar")).isTrue();
278     assertThat(path("/foo/bar").endsWith("/foo/bar")).isTrue();
279     assertThat(path("/foo/bar").endsWith("/foo")).isFalse();
280     assertThat(path("/foo/bar").startsWith("foo/bar")).isFalse();
281   }
282 
283   @Test
testPaths_toAbsolutePath()284   public void testPaths_toAbsolutePath() {
285     assertThatPath(path("/foo/bar").toAbsolutePath())
286         .isAbsolute()
287         .and()
288         .hasRootComponent("/")
289         .and()
290         .hasNameComponents("foo", "bar")
291         .and()
292         .isEqualTo(path("/foo/bar"));
293 
294     assertThatPath(path("foo/bar").toAbsolutePath())
295         .isAbsolute()
296         .and()
297         .hasRootComponent("/")
298         .and()
299         .hasNameComponents("work", "foo", "bar")
300         .and()
301         .isEqualTo(path("/work/foo/bar"));
302   }
303 
304   @Test
testPaths_toRealPath()305   public void testPaths_toRealPath() throws IOException {
306     Files.createDirectories(path("/foo/bar"));
307     Files.createSymbolicLink(path("/link"), path("/"));
308 
309     assertThatPath(path("/link/foo/bar").toRealPath()).isEqualTo(path("/foo/bar"));
310 
311     assertThatPath(path("").toRealPath()).isEqualTo(path("/work"));
312     assertThatPath(path(".").toRealPath()).isEqualTo(path("/work"));
313     assertThatPath(path("..").toRealPath()).isEqualTo(path("/"));
314     assertThatPath(path("../..").toRealPath()).isEqualTo(path("/"));
315     assertThatPath(path("./.././..").toRealPath()).isEqualTo(path("/"));
316     assertThatPath(path("./.././../.").toRealPath()).isEqualTo(path("/"));
317   }
318 
319   @Test
testPaths_toUri()320   public void testPaths_toUri() {
321     assertThat(path("/").toUri()).isEqualTo(URI.create("jimfs://unix/"));
322     assertThat(path("/foo").toUri()).isEqualTo(URI.create("jimfs://unix/foo"));
323     assertThat(path("/foo/bar").toUri()).isEqualTo(URI.create("jimfs://unix/foo/bar"));
324     assertThat(path("foo").toUri()).isEqualTo(URI.create("jimfs://unix/work/foo"));
325     assertThat(path("foo/bar").toUri()).isEqualTo(URI.create("jimfs://unix/work/foo/bar"));
326     assertThat(path("").toUri()).isEqualTo(URI.create("jimfs://unix/work/"));
327     assertThat(path("./../.").toUri()).isEqualTo(URI.create("jimfs://unix/work/./.././"));
328   }
329 
330   @Test
testPaths_getFromUri()331   public void testPaths_getFromUri() {
332     assertThatPath(Paths.get(URI.create("jimfs://unix/"))).isEqualTo(path("/"));
333     assertThatPath(Paths.get(URI.create("jimfs://unix/foo"))).isEqualTo(path("/foo"));
334     assertThatPath(Paths.get(URI.create("jimfs://unix/foo%20bar"))).isEqualTo(path("/foo bar"));
335     assertThatPath(Paths.get(URI.create("jimfs://unix/foo/./bar"))).isEqualTo(path("/foo/./bar"));
336     assertThatPath(Paths.get(URI.create("jimfs://unix/foo/bar/"))).isEqualTo(path("/foo/bar"));
337   }
338 
339   @Test
testPathMatchers_regex()340   public void testPathMatchers_regex() {
341     assertThatPath("bar").matches("regex:.*");
342     assertThatPath("bar").matches("regex:bar");
343     assertThatPath("bar").matches("regex:[a-z]+");
344     assertThatPath("/foo/bar").matches("regex:/.*");
345     assertThatPath("/foo/bar").matches("regex:/.*/bar");
346   }
347 
348   @Test
testPathMatchers_glob()349   public void testPathMatchers_glob() {
350     assertThatPath("bar").matches("glob:bar");
351     assertThatPath("bar").matches("glob:*");
352     assertThatPath("/foo").doesNotMatch("glob:*");
353     assertThatPath("/foo/bar").doesNotMatch("glob:*");
354     assertThatPath("/foo/bar").matches("glob:**");
355     assertThatPath("/foo/bar").matches("glob:/**");
356     assertThatPath("foo/bar").doesNotMatch("glob:/**");
357     assertThatPath("/foo/bar/baz/stuff").matches("glob:/foo/**");
358     assertThatPath("/foo/bar/baz/stuff").matches("glob:/**/stuff");
359     assertThatPath("/foo").matches("glob:/[a-z]*");
360     assertThatPath("/Foo").doesNotMatch("glob:/[a-z]*");
361     assertThatPath("/foo/bar/baz/Stuff.java").matches("glob:**/*.java");
362     assertThatPath("/foo/bar/baz/Stuff.java").matches("glob:**/*.{java,class}");
363     assertThatPath("/foo/bar/baz/Stuff.class").matches("glob:**/*.{java,class}");
364     assertThatPath("/foo/bar/baz/Stuff.java").matches("glob:**/*.*");
365 
366     try {
367       fs.getPathMatcher("glob:**/*.{java,class");
368       fail();
369     } catch (PatternSyntaxException expected) {
370     }
371   }
372 
373   @Test
testPathMatchers_invalid()374   public void testPathMatchers_invalid() {
375     try {
376       fs.getPathMatcher("glob");
377       fail();
378     } catch (IllegalArgumentException expected) {
379     }
380 
381     try {
382       fs.getPathMatcher("foo:foo");
383       fail();
384     } catch (UnsupportedOperationException expected) {
385       assertThat(expected.getMessage()).contains("syntax");
386     }
387   }
388 
389   @Test
testNewFileSystem_hasRootAndWorkingDirectory()390   public void testNewFileSystem_hasRootAndWorkingDirectory() throws IOException {
391     assertThatPath("/").hasChildren("work");
392     assertThatPath("/work").hasNoChildren();
393   }
394 
395   @Test
testCreateDirectory_absolute()396   public void testCreateDirectory_absolute() throws IOException {
397     Files.createDirectory(path("/test"));
398 
399     assertThatPath("/test").exists();
400     assertThatPath("/").hasChildren("test", "work");
401 
402     Files.createDirectory(path("/foo"));
403     Files.createDirectory(path("/foo/bar"));
404 
405     assertThatPath("/foo/bar").exists();
406     assertThatPath("/foo").hasChildren("bar");
407   }
408 
409   @Test
testCreateFile_absolute()410   public void testCreateFile_absolute() throws IOException {
411     Files.createFile(path("/test.txt"));
412 
413     assertThatPath("/test.txt").isRegularFile();
414     assertThatPath("/").hasChildren("test.txt", "work");
415 
416     Files.createDirectory(path("/foo"));
417     Files.createFile(path("/foo/test.txt"));
418 
419     assertThatPath("/foo/test.txt").isRegularFile();
420     assertThatPath("/foo").hasChildren("test.txt");
421   }
422 
423   @Test
testCreateSymbolicLink_absolute()424   public void testCreateSymbolicLink_absolute() throws IOException {
425     Files.createSymbolicLink(path("/link.txt"), path("test.txt"));
426 
427     assertThatPath("/link.txt", NOFOLLOW_LINKS).isSymbolicLink().withTarget("test.txt");
428     assertThatPath("/").hasChildren("link.txt", "work");
429 
430     Files.createDirectory(path("/foo"));
431     Files.createSymbolicLink(path("/foo/link.txt"), path("test.txt"));
432 
433     assertThatPath("/foo/link.txt").noFollowLinks().isSymbolicLink().withTarget("test.txt");
434     assertThatPath("/foo").hasChildren("link.txt");
435   }
436 
437   @Test
testCreateLink_absolute()438   public void testCreateLink_absolute() throws IOException {
439     Files.createFile(path("/test.txt"));
440     Files.createLink(path("/link.txt"), path("/test.txt"));
441 
442     // don't assert that the link is the same file here, just that it was created
443     // later tests check that linking works correctly
444     assertThatPath("/link.txt", NOFOLLOW_LINKS).isRegularFile();
445     assertThatPath("/").hasChildren("link.txt", "test.txt", "work");
446 
447     Files.createDirectory(path("/foo"));
448     Files.createLink(path("/foo/link.txt"), path("/test.txt"));
449 
450     assertThatPath("/foo/link.txt", NOFOLLOW_LINKS).isRegularFile();
451     assertThatPath("/foo").hasChildren("link.txt");
452   }
453 
454   @Test
testCreateDirectory_relative()455   public void testCreateDirectory_relative() throws IOException {
456     Files.createDirectory(path("test"));
457 
458     assertThatPath("/work/test", NOFOLLOW_LINKS).isDirectory();
459     assertThatPath("test", NOFOLLOW_LINKS).isDirectory();
460     assertThatPath("/work").hasChildren("test");
461     assertThatPath("test").isSameFileAs("/work/test");
462 
463     Files.createDirectory(path("foo"));
464     Files.createDirectory(path("foo/bar"));
465 
466     assertThatPath("/work/foo/bar", NOFOLLOW_LINKS).isDirectory();
467     assertThatPath("foo/bar", NOFOLLOW_LINKS).isDirectory();
468     assertThatPath("/work/foo").hasChildren("bar");
469     assertThatPath("foo").hasChildren("bar");
470     assertThatPath("foo/bar").isSameFileAs("/work/foo/bar");
471   }
472 
473   @Test
testCreateFile_relative()474   public void testCreateFile_relative() throws IOException {
475     Files.createFile(path("test.txt"));
476 
477     assertThatPath("/work/test.txt", NOFOLLOW_LINKS).isRegularFile();
478     assertThatPath("test.txt", NOFOLLOW_LINKS).isRegularFile();
479     assertThatPath("/work").hasChildren("test.txt");
480     assertThatPath("test.txt").isSameFileAs("/work/test.txt");
481 
482     Files.createDirectory(path("foo"));
483     Files.createFile(path("foo/test.txt"));
484 
485     assertThatPath("/work/foo/test.txt", NOFOLLOW_LINKS).isRegularFile();
486     assertThatPath("foo/test.txt", NOFOLLOW_LINKS).isRegularFile();
487     assertThatPath("/work/foo").hasChildren("test.txt");
488     assertThatPath("foo").hasChildren("test.txt");
489     assertThatPath("foo/test.txt").isSameFileAs("/work/foo/test.txt");
490   }
491 
492   @Test
testCreateSymbolicLink_relative()493   public void testCreateSymbolicLink_relative() throws IOException {
494     Files.createSymbolicLink(path("link.txt"), path("test.txt"));
495 
496     assertThatPath("/work/link.txt", NOFOLLOW_LINKS).isSymbolicLink().withTarget("test.txt");
497     assertThatPath("link.txt", NOFOLLOW_LINKS).isSymbolicLink().withTarget("test.txt");
498     assertThatPath("/work").hasChildren("link.txt");
499 
500     Files.createDirectory(path("foo"));
501     Files.createSymbolicLink(path("foo/link.txt"), path("test.txt"));
502 
503     assertThatPath("/work/foo/link.txt", NOFOLLOW_LINKS).isSymbolicLink().withTarget("test.txt");
504     assertThatPath("foo/link.txt", NOFOLLOW_LINKS).isSymbolicLink().withTarget("test.txt");
505     assertThatPath("/work/foo").hasChildren("link.txt");
506     assertThatPath("foo").hasChildren("link.txt");
507   }
508 
509   @Test
testCreateLink_relative()510   public void testCreateLink_relative() throws IOException {
511     Files.createFile(path("test.txt"));
512     Files.createLink(path("link.txt"), path("test.txt"));
513 
514     // don't assert that the link is the same file here, just that it was created
515     // later tests check that linking works correctly
516     assertThatPath("/work/link.txt", NOFOLLOW_LINKS).isRegularFile();
517     assertThatPath("link.txt", NOFOLLOW_LINKS).isRegularFile();
518     assertThatPath("/work").hasChildren("link.txt", "test.txt");
519 
520     Files.createDirectory(path("foo"));
521     Files.createLink(path("foo/link.txt"), path("test.txt"));
522 
523     assertThatPath("/work/foo/link.txt", NOFOLLOW_LINKS).isRegularFile();
524     assertThatPath("foo/link.txt", NOFOLLOW_LINKS).isRegularFile();
525     assertThatPath("foo").hasChildren("link.txt");
526   }
527 
528   @Test
testCreateFile_existing()529   public void testCreateFile_existing() throws IOException {
530     Files.createFile(path("/test"));
531     try {
532       Files.createFile(path("/test"));
533       fail();
534     } catch (FileAlreadyExistsException expected) {
535       assertEquals("/test", expected.getMessage());
536     }
537 
538     try {
539       Files.createDirectory(path("/test"));
540       fail();
541     } catch (FileAlreadyExistsException expected) {
542       assertEquals("/test", expected.getMessage());
543     }
544 
545     try {
546       Files.createSymbolicLink(path("/test"), path("/foo"));
547       fail();
548     } catch (FileAlreadyExistsException expected) {
549       assertEquals("/test", expected.getMessage());
550     }
551 
552     Files.createFile(path("/foo"));
553     try {
554       Files.createLink(path("/test"), path("/foo"));
555       fail();
556     } catch (FileAlreadyExistsException expected) {
557       assertEquals("/test", expected.getMessage());
558     }
559   }
560 
561   @Test
testCreateFile_parentDoesNotExist()562   public void testCreateFile_parentDoesNotExist() throws IOException {
563     try {
564       Files.createFile(path("/foo/test"));
565       fail();
566     } catch (NoSuchFileException expected) {
567       assertEquals("/foo/test", expected.getMessage());
568     }
569 
570     try {
571       Files.createDirectory(path("/foo/test"));
572       fail();
573     } catch (NoSuchFileException expected) {
574       assertEquals("/foo/test", expected.getMessage());
575     }
576 
577     try {
578       Files.createSymbolicLink(path("/foo/test"), path("/bar"));
579       fail();
580     } catch (NoSuchFileException expected) {
581       assertEquals("/foo/test", expected.getMessage());
582     }
583 
584     Files.createFile(path("/bar"));
585     try {
586       Files.createLink(path("/foo/test"), path("/bar"));
587       fail();
588     } catch (NoSuchFileException expected) {
589       assertEquals("/foo/test", expected.getMessage());
590     }
591   }
592 
593   @Test
testCreateFile_parentIsNotDirectory()594   public void testCreateFile_parentIsNotDirectory() throws IOException {
595     Files.createDirectory(path("/foo"));
596     Files.createFile(path("/foo/bar"));
597 
598     try {
599       Files.createFile(path("/foo/bar/baz"));
600       fail();
601     } catch (NoSuchFileException expected) {
602       assertThat(expected.getFile()).isEqualTo("/foo/bar/baz");
603     }
604   }
605 
606   @Test
testCreateFile_nonDirectoryHigherInPath()607   public void testCreateFile_nonDirectoryHigherInPath() throws IOException {
608     Files.createDirectory(path("/foo"));
609     Files.createFile(path("/foo/bar"));
610 
611     try {
612       Files.createFile(path("/foo/bar/baz/stuff"));
613       fail();
614     } catch (NoSuchFileException expected) {
615       assertThat(expected.getFile()).isEqualTo("/foo/bar/baz/stuff");
616     }
617   }
618 
619   @Test
testCreateFile_parentSymlinkDoesNotExist()620   public void testCreateFile_parentSymlinkDoesNotExist() throws IOException {
621     Files.createDirectory(path("/foo"));
622     Files.createSymbolicLink(path("/foo/bar"), path("/foo/nope"));
623 
624     try {
625       Files.createFile(path("/foo/bar/baz"));
626       fail();
627     } catch (NoSuchFileException expected) {
628       assertThat(expected.getFile()).isEqualTo("/foo/bar/baz");
629     }
630   }
631 
632   @Test
testCreateFile_symlinkHigherInPathDoesNotExist()633   public void testCreateFile_symlinkHigherInPathDoesNotExist() throws IOException {
634     Files.createDirectory(path("/foo"));
635     Files.createSymbolicLink(path("/foo/bar"), path("nope"));
636 
637     try {
638       Files.createFile(path("/foo/bar/baz/stuff"));
639       fail();
640     } catch (NoSuchFileException expected) {
641       assertThat(expected.getFile()).isEqualTo("/foo/bar/baz/stuff");
642     }
643   }
644 
645   @Test
testCreateFile_parentSymlinkDoesPointsToNonDirectory()646   public void testCreateFile_parentSymlinkDoesPointsToNonDirectory() throws IOException {
647     Files.createDirectory(path("/foo"));
648     Files.createFile(path("/foo/file"));
649     Files.createSymbolicLink(path("/foo/bar"), path("/foo/file"));
650 
651     try {
652       Files.createFile(path("/foo/bar/baz"));
653       fail();
654     } catch (NoSuchFileException expected) {
655       assertThat(expected.getFile()).isEqualTo("/foo/bar/baz");
656     }
657   }
658 
659   @Test
testCreateFile_symlinkHigherInPathPointsToNonDirectory()660   public void testCreateFile_symlinkHigherInPathPointsToNonDirectory() throws IOException {
661     Files.createDirectory(path("/foo"));
662     Files.createFile(path("/foo/file"));
663     Files.createSymbolicLink(path("/foo/bar"), path("file"));
664 
665     try {
666       Files.createFile(path("/foo/bar/baz/stuff"));
667       fail();
668     } catch (NoSuchFileException expected) {
669       assertThat(expected.getFile()).isEqualTo("/foo/bar/baz/stuff");
670     }
671   }
672 
673   @Test
testCreateFile_withInitialAttributes()674   public void testCreateFile_withInitialAttributes() throws IOException {
675     Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("rwxrwxrwx");
676     FileAttribute<?> permissionsAttr = PosixFilePermissions.asFileAttribute(permissions);
677 
678     Files.createFile(path("/normal"));
679     Files.createFile(path("/foo"), permissionsAttr);
680 
681     assertThatPath("/normal").attribute("posix:permissions").isNot(permissions);
682     assertThatPath("/foo").attribute("posix:permissions").is(permissions);
683   }
684 
685   @Test
testCreateFile_withInitialAttributes_illegalInitialAttribute()686   public void testCreateFile_withInitialAttributes_illegalInitialAttribute() throws IOException {
687     try {
688       Files.createFile(
689           path("/foo"),
690           new BasicFileAttribute<>("basic:lastModifiedTime", FileTime.fromMillis(0L)));
691       fail();
692     } catch (UnsupportedOperationException expected) {
693     }
694 
695     assertThatPath("/foo").doesNotExist();
696 
697     try {
698       Files.createFile(path("/foo"), new BasicFileAttribute<>("basic:noSuchAttribute", "foo"));
699       fail();
700     } catch (UnsupportedOperationException expected) {
701     }
702 
703     assertThatPath("/foo").doesNotExist();
704   }
705 
706   @Test
testOpenChannel_withInitialAttributes_createNewFile()707   public void testOpenChannel_withInitialAttributes_createNewFile() throws IOException {
708     FileAttribute<Set<PosixFilePermission>> permissions =
709         PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwxrwxrwx"));
710     Files.newByteChannel(path("/foo"), ImmutableSet.of(WRITE, CREATE), permissions).close();
711 
712     assertThatPath("/foo")
713         .isRegularFile()
714         .and()
715         .attribute("posix:permissions")
716         .is(permissions.value());
717   }
718 
719   @Test
testOpenChannel_withInitialAttributes_fileExists()720   public void testOpenChannel_withInitialAttributes_fileExists() throws IOException {
721     Files.createFile(path("/foo"));
722 
723     FileAttribute<Set<PosixFilePermission>> permissions =
724         PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwxrwxrwx"));
725     Files.newByteChannel(path("/foo"), ImmutableSet.of(WRITE, CREATE), permissions).close();
726 
727     assertThatPath("/foo")
728         .isRegularFile()
729         .and()
730         .attribute("posix:permissions")
731         .isNot(permissions.value());
732   }
733 
734   @Test
testCreateDirectory_withInitialAttributes()735   public void testCreateDirectory_withInitialAttributes() throws IOException {
736     FileAttribute<Set<PosixFilePermission>> permissions =
737         PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwxrwxrwx"));
738 
739     Files.createDirectory(path("/foo"), permissions);
740 
741     assertThatPath("/foo")
742         .isDirectory()
743         .and()
744         .attribute("posix:permissions")
745         .is(permissions.value());
746 
747     Files.createDirectory(path("/normal"));
748 
749     assertThatPath("/normal")
750         .isDirectory()
751         .and()
752         .attribute("posix:permissions")
753         .isNot(permissions.value());
754   }
755 
756   @Test
testCreateSymbolicLink_withInitialAttributes()757   public void testCreateSymbolicLink_withInitialAttributes() throws IOException {
758     FileAttribute<Set<PosixFilePermission>> permissions =
759         PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwxrwxrwx"));
760 
761     Files.createSymbolicLink(path("/foo"), path("bar"), permissions);
762 
763     assertThatPath("/foo", NOFOLLOW_LINKS)
764         .isSymbolicLink()
765         .and()
766         .attribute("posix:permissions")
767         .is(permissions.value());
768 
769     Files.createSymbolicLink(path("/normal"), path("bar"));
770 
771     assertThatPath("/normal", NOFOLLOW_LINKS)
772         .isSymbolicLink()
773         .and()
774         .attribute("posix:permissions")
775         .isNot(permissions.value());
776   }
777 
778   @Test
testCreateDirectories()779   public void testCreateDirectories() throws IOException {
780     Files.createDirectories(path("/foo/bar/baz"));
781 
782     assertThatPath("/foo").isDirectory();
783     assertThatPath("/foo/bar").isDirectory();
784     assertThatPath("/foo/bar/baz").isDirectory();
785 
786     Files.createDirectories(path("/foo/asdf/jkl"));
787 
788     assertThatPath("/foo/asdf").isDirectory();
789     assertThatPath("/foo/asdf/jkl").isDirectory();
790 
791     Files.createDirectories(path("bar/baz"));
792 
793     assertThatPath("bar/baz").isDirectory();
794     assertThatPath("/work/bar/baz").isDirectory();
795   }
796 
797   @Test
testDirectories_newlyCreatedDirectoryHasTwoLinks()798   public void testDirectories_newlyCreatedDirectoryHasTwoLinks() throws IOException {
799     // one link from its parent to it; one from it to itself
800 
801     Files.createDirectory(path("/foo"));
802 
803     assertThatPath("/foo").hasLinkCount(2);
804   }
805 
806   @Test
testDirectories_creatingDirectoryAddsOneLinkToParent()807   public void testDirectories_creatingDirectoryAddsOneLinkToParent() throws IOException {
808     // from the .. direntry
809 
810     Files.createDirectory(path("/foo"));
811     Files.createDirectory(path("/foo/bar"));
812 
813     assertThatPath("/foo").hasLinkCount(3);
814 
815     Files.createDirectory(path("/foo/baz"));
816 
817     assertThatPath("/foo").hasLinkCount(4);
818   }
819 
820   @Test
testDirectories_creatingNonDirectoryDoesNotAddLinkToParent()821   public void testDirectories_creatingNonDirectoryDoesNotAddLinkToParent() throws IOException {
822     Files.createDirectory(path("/foo"));
823     Files.createFile(path("/foo/file"));
824     Files.createSymbolicLink(path("/foo/fileSymlink"), path("file"));
825     Files.createLink(path("/foo/link"), path("/foo/file"));
826     Files.createSymbolicLink(path("/foo/fooSymlink"), path("/foo"));
827 
828     assertThatPath("/foo").hasLinkCount(2);
829   }
830 
831   @Test
testSize_forNewFile_isZero()832   public void testSize_forNewFile_isZero() throws IOException {
833     Files.createFile(path("/test"));
834 
835     assertThatPath("/test").hasSize(0);
836   }
837 
838   @Test
testRead_forNewFile_isEmpty()839   public void testRead_forNewFile_isEmpty() throws IOException {
840     Files.createFile(path("/test"));
841 
842     assertThatPath("/test").containsNoBytes();
843   }
844 
845   @Test
testWriteFile_succeeds()846   public void testWriteFile_succeeds() throws IOException {
847     Files.createFile(path("/test"));
848     Files.write(path("/test"), new byte[] {0, 1, 2, 3});
849   }
850 
851   @Test
testSize_forFileAfterWrite_isNumberOfBytesWritten()852   public void testSize_forFileAfterWrite_isNumberOfBytesWritten() throws IOException {
853     Files.write(path("/test"), new byte[] {0, 1, 2, 3});
854 
855     assertThatPath("/test").hasSize(4);
856   }
857 
858   @Test
testRead_forFileAfterWrite_isBytesWritten()859   public void testRead_forFileAfterWrite_isBytesWritten() throws IOException {
860     byte[] bytes = {0, 1, 2, 3};
861     Files.write(path("/test"), bytes);
862 
863     assertThatPath("/test").containsBytes(bytes);
864   }
865 
866   @Test
testWriteFile_withStandardOptions()867   public void testWriteFile_withStandardOptions() throws IOException {
868     Path test = path("/test");
869     byte[] bytes = {0, 1, 2, 3};
870 
871     try {
872       // CREATE and CREATE_NEW not specified
873       Files.write(test, bytes, WRITE);
874       fail();
875     } catch (NoSuchFileException expected) {
876       assertEquals(test.toString(), expected.getMessage());
877     }
878 
879     Files.write(test, bytes, CREATE_NEW); // succeeds, file does not exist
880     assertThatPath("/test").containsBytes(bytes);
881 
882     try {
883       Files.write(test, bytes, CREATE_NEW); // CREATE_NEW requires file not exist
884       fail();
885     } catch (FileAlreadyExistsException expected) {
886       assertEquals(test.toString(), expected.getMessage());
887     }
888 
889     Files.write(test, new byte[] {4, 5}, CREATE); // succeeds, ok for file to already exist
890     assertThatPath("/test").containsBytes(4, 5, 2, 3); // did not truncate or append, so overwrote
891 
892     Files.write(test, bytes, WRITE, CREATE, TRUNCATE_EXISTING); // default options
893     assertThatPath("/test").containsBytes(bytes);
894 
895     Files.write(test, bytes, WRITE, APPEND);
896     assertThatPath("/test").containsBytes(0, 1, 2, 3, 0, 1, 2, 3);
897 
898     Files.write(test, bytes, WRITE, CREATE, TRUNCATE_EXISTING, APPEND, SPARSE, DSYNC, SYNC);
899     assertThatPath("/test").containsBytes(bytes);
900 
901     try {
902       Files.write(test, bytes, READ, WRITE); // READ not allowed
903       fail();
904     } catch (UnsupportedOperationException expected) {
905     }
906   }
907 
908   @Test
testWriteLines_succeeds()909   public void testWriteLines_succeeds() throws IOException {
910     Files.write(path("/test.txt"), ImmutableList.of("hello", "world"), UTF_8);
911   }
912 
913   @Test
testOpenFile_withReadAndTruncateExisting_doesNotTruncateFile()914   public void testOpenFile_withReadAndTruncateExisting_doesNotTruncateFile() throws IOException {
915     byte[] bytes = bytes(1, 2, 3, 4);
916     Files.write(path("/test"), bytes);
917 
918     try (FileChannel channel = FileChannel.open(path("/test"), READ, TRUNCATE_EXISTING)) {
919       // TRUNCATE_EXISTING ignored when opening for read
920       byte[] readBytes = new byte[4];
921       channel.read(ByteBuffer.wrap(readBytes));
922 
923       assertThat(Bytes.asList(readBytes)).isEqualTo(Bytes.asList(bytes));
924     }
925   }
926 
927   @Test
testRead_forFileAfterWriteLines_isLinesWritten()928   public void testRead_forFileAfterWriteLines_isLinesWritten() throws IOException {
929     Files.write(path("/test.txt"), ImmutableList.of("hello", "world"), UTF_8);
930 
931     assertThatPath("/test.txt").containsLines("hello", "world");
932   }
933 
934   @Test
testWriteLines_withStandardOptions()935   public void testWriteLines_withStandardOptions() throws IOException {
936     Path test = path("/test.txt");
937     ImmutableList<String> lines = ImmutableList.of("hello", "world");
938 
939     try {
940       // CREATE and CREATE_NEW not specified
941       Files.write(test, lines, UTF_8, WRITE);
942       fail();
943     } catch (NoSuchFileException expected) {
944       assertEquals(test.toString(), expected.getMessage());
945     }
946 
947     Files.write(test, lines, UTF_8, CREATE_NEW); // succeeds, file does not exist
948     assertThatPath(test).containsLines(lines);
949 
950     try {
951       Files.write(test, lines, UTF_8, CREATE_NEW); // CREATE_NEW requires file not exist
952       fail();
953     } catch (FileAlreadyExistsException expected) {
954     }
955 
956     // succeeds, ok for file to already exist
957     Files.write(test, ImmutableList.of("foo"), UTF_8, CREATE);
958     // did not truncate or append, so overwrote
959     if (System.getProperty("line.separator").length() == 2) {
960       // on Windows, an extra character is overwritten by the \r\n line separator
961       assertThatPath(test).containsLines("foo", "", "world");
962     } else {
963       assertThatPath(test).containsLines("foo", "o", "world");
964     }
965 
966     Files.write(test, lines, UTF_8, WRITE, CREATE, TRUNCATE_EXISTING); // default options
967     assertThatPath(test).containsLines(lines);
968 
969     Files.write(test, lines, UTF_8, WRITE, APPEND);
970     assertThatPath(test).containsLines("hello", "world", "hello", "world");
971 
972     Files.write(test, lines, UTF_8, WRITE, CREATE, TRUNCATE_EXISTING, APPEND, SPARSE, DSYNC, SYNC);
973     assertThatPath(test).containsLines(lines);
974 
975     try {
976       Files.write(test, lines, UTF_8, READ, WRITE); // READ not allowed
977       fail();
978     } catch (UnsupportedOperationException expected) {
979     }
980   }
981 
982   @Test
testWrite_fileExistsButIsNotRegularFile()983   public void testWrite_fileExistsButIsNotRegularFile() throws IOException {
984     Files.createDirectory(path("/foo"));
985 
986     try {
987       // non-CREATE mode
988       Files.write(path("/foo"), preFilledBytes(10), WRITE);
989       fail();
990     } catch (FileSystemException expected) {
991       assertThat(expected.getFile()).isEqualTo("/foo");
992       assertThat(expected.getMessage()).contains("regular file");
993     }
994 
995     try {
996       // CREATE mode
997       Files.write(path("/foo"), preFilledBytes(10));
998       fail();
999     } catch (FileSystemException expected) {
1000       assertThat(expected.getFile()).isEqualTo("/foo");
1001       assertThat(expected.getMessage()).contains("regular file");
1002     }
1003   }
1004 
1005   @Test
testDelete_file()1006   public void testDelete_file() throws IOException {
1007     try {
1008       Files.delete(path("/test"));
1009       fail();
1010     } catch (NoSuchFileException expected) {
1011       assertEquals("/test", expected.getMessage());
1012     }
1013 
1014     try {
1015       Files.delete(path("/foo/bar"));
1016       fail();
1017     } catch (NoSuchFileException expected) {
1018       assertEquals("/foo/bar", expected.getMessage());
1019     }
1020 
1021     assertFalse(Files.deleteIfExists(path("/test")));
1022     assertFalse(Files.deleteIfExists(path("/foo/bar")));
1023 
1024     Files.createFile(path("/test"));
1025     assertThatPath("/test").isRegularFile();
1026 
1027     Files.delete(path("/test"));
1028     assertThatPath("/test").doesNotExist();
1029 
1030     Files.createFile(path("/test"));
1031 
1032     assertTrue(Files.deleteIfExists(path("/test")));
1033     assertThatPath("/test").doesNotExist();
1034   }
1035 
1036   @Test
testDelete_file_whenOpenReferencesRemain()1037   public void testDelete_file_whenOpenReferencesRemain() throws IOException {
1038     // the open streams should continue to function normally despite the deletion
1039 
1040     Path foo = path("/foo");
1041     byte[] bytes = preFilledBytes(100);
1042     Files.write(foo, bytes);
1043 
1044     InputStream in = Files.newInputStream(foo);
1045     OutputStream out = Files.newOutputStream(foo, APPEND);
1046     FileChannel channel = FileChannel.open(foo, READ, WRITE);
1047 
1048     assertThat(channel.size()).isEqualTo(100L);
1049 
1050     Files.delete(foo);
1051     assertThatPath("/foo").doesNotExist();
1052 
1053     assertThat(channel.size()).isEqualTo(100L);
1054 
1055     ByteBuffer buf = ByteBuffer.allocate(100);
1056     while (buf.hasRemaining()) {
1057       channel.read(buf);
1058     }
1059 
1060     assertArrayEquals(bytes, buf.array());
1061 
1062     byte[] moreBytes = {1, 2, 3, 4, 5};
1063     out.write(moreBytes);
1064 
1065     assertThat(channel.size()).isEqualTo(105L);
1066     buf.clear();
1067     assertThat(channel.read(buf)).isEqualTo(5);
1068 
1069     buf.flip();
1070     byte[] b = new byte[5];
1071     buf.get(b);
1072     assertArrayEquals(moreBytes, b);
1073 
1074     byte[] allBytes = new byte[105];
1075     int off = 0;
1076     int read;
1077     while ((read = in.read(allBytes, off, allBytes.length - off)) != -1) {
1078       off += read;
1079     }
1080     assertArrayEquals(concat(bytes, moreBytes), allBytes);
1081 
1082     channel.close();
1083     out.close();
1084     in.close();
1085   }
1086 
1087   @Test
testDelete_directory()1088   public void testDelete_directory() throws IOException {
1089     Files.createDirectories(path("/foo/bar"));
1090     assertThatPath("/foo").isDirectory();
1091     assertThatPath("/foo/bar").isDirectory();
1092 
1093     Files.delete(path("/foo/bar"));
1094     assertThatPath("/foo/bar").doesNotExist();
1095 
1096     assertTrue(Files.deleteIfExists(path("/foo")));
1097     assertThatPath("/foo").doesNotExist();
1098   }
1099 
1100   @Test
testDelete_pathPermutations()1101   public void testDelete_pathPermutations() throws IOException {
1102     Path bar = path("/work/foo/bar");
1103     Files.createDirectories(bar);
1104     for (Path path : permutations(bar)) {
1105       Files.createDirectories(bar);
1106       assertThatPath(path).isSameFileAs(bar);
1107       Files.delete(path);
1108       assertThatPath(bar).doesNotExist();
1109       assertThatPath(path).doesNotExist();
1110     }
1111 
1112     Path baz = path("/test/baz");
1113     Files.createDirectories(baz);
1114     Path hello = baz.resolve("hello.txt");
1115     for (Path path : permutations(hello)) {
1116       Files.createFile(hello);
1117       assertThatPath(path).isSameFileAs(hello);
1118       Files.delete(path);
1119       assertThatPath(hello).doesNotExist();
1120       assertThatPath(path).doesNotExist();
1121     }
1122   }
1123 
1124   @Test
testDelete_directory_cantDeleteNonEmptyDirectory()1125   public void testDelete_directory_cantDeleteNonEmptyDirectory() throws IOException {
1126     Files.createDirectories(path("/foo/bar"));
1127 
1128     try {
1129       Files.delete(path("/foo"));
1130       fail();
1131     } catch (DirectoryNotEmptyException expected) {
1132       assertThat(expected.getFile()).isEqualTo("/foo");
1133     }
1134 
1135     try {
1136       Files.deleteIfExists(path("/foo"));
1137       fail();
1138     } catch (DirectoryNotEmptyException expected) {
1139       assertThat(expected.getFile()).isEqualTo("/foo");
1140     }
1141   }
1142 
1143   @Test
testDelete_directory_canDeleteWorkingDirectoryByAbsolutePath()1144   public void testDelete_directory_canDeleteWorkingDirectoryByAbsolutePath() throws IOException {
1145     assertThatPath("/work").exists();
1146     assertThatPath("").exists();
1147     assertThatPath(".").exists();
1148 
1149     Files.delete(path("/work"));
1150 
1151     assertThatPath("/work").doesNotExist();
1152     assertThatPath("").exists();
1153     assertThatPath(".").exists();
1154   }
1155 
1156   @Test
testDelete_directory_cantDeleteWorkingDirectoryByRelativePath()1157   public void testDelete_directory_cantDeleteWorkingDirectoryByRelativePath() throws IOException {
1158     try {
1159       Files.delete(path(""));
1160       fail();
1161     } catch (FileSystemException expected) {
1162       assertThat(expected.getFile()).isEqualTo("");
1163     }
1164 
1165     try {
1166       Files.delete(path("."));
1167       fail();
1168     } catch (FileSystemException expected) {
1169       assertThat(expected.getFile()).isEqualTo(".");
1170     }
1171 
1172     try {
1173       Files.delete(path("../../work"));
1174       fail();
1175     } catch (FileSystemException expected) {
1176       assertThat(expected.getFile()).isEqualTo("../../work");
1177     }
1178 
1179     try {
1180       Files.delete(path("./../work/.././../work/."));
1181       fail();
1182     } catch (FileSystemException expected) {
1183       assertThat(expected.getFile()).isEqualTo("./../work/.././../work/.");
1184     }
1185   }
1186 
1187   @Test
testDelete_directory_cantDeleteRoot()1188   public void testDelete_directory_cantDeleteRoot() throws IOException {
1189     // delete working directory so that root is empty
1190     // don't want to just be testing the "can't delete when not empty" logic
1191     Files.delete(path("/work"));
1192 
1193     try {
1194       Files.delete(path("/"));
1195       fail();
1196     } catch (IOException expected) {
1197       assertThat(expected.getMessage()).contains("root");
1198     }
1199 
1200     Files.createDirectories(path("/foo/bar"));
1201 
1202     try {
1203       Files.delete(path("/foo/bar/../.."));
1204       fail();
1205     } catch (IOException expected) {
1206       assertThat(expected.getMessage()).contains("root");
1207     }
1208 
1209     try {
1210       Files.delete(path("/foo/./../foo/bar/./../bar/.././../../.."));
1211       fail();
1212     } catch (IOException expected) {
1213       assertThat(expected.getMessage()).contains("root");
1214     }
1215   }
1216 
1217   @Test
testSymbolicLinks()1218   public void testSymbolicLinks() throws IOException {
1219     Files.createSymbolicLink(path("/link.txt"), path("/file.txt"));
1220     assertThatPath("/link.txt", NOFOLLOW_LINKS).isSymbolicLink().withTarget("/file.txt");
1221     assertThatPath("/link.txt").doesNotExist(); // following the link; target doesn't exist
1222 
1223     try {
1224       Files.createFile(path("/link.txt"));
1225       fail();
1226     } catch (FileAlreadyExistsException expected) {
1227     }
1228 
1229     try {
1230       Files.readAllBytes(path("/link.txt"));
1231       fail();
1232     } catch (NoSuchFileException expected) {
1233     }
1234 
1235     Files.createFile(path("/file.txt"));
1236     assertThatPath("/link.txt").isRegularFile(); // following the link; target does exist
1237     assertThatPath("/link.txt").containsNoBytes();
1238 
1239     Files.createSymbolicLink(path("/foo"), path("/bar/baz"));
1240     assertThatPath("/foo", NOFOLLOW_LINKS).isSymbolicLink().withTarget("/bar/baz");
1241     assertThatPath("/foo").doesNotExist(); // following the link; target doesn't exist
1242 
1243     Files.createDirectories(path("/bar/baz"));
1244     assertThatPath("/foo").isDirectory(); // following the link; target does exist
1245 
1246     Files.createFile(path("/bar/baz/test.txt"));
1247     assertThatPath("/foo/test.txt", NOFOLLOW_LINKS).isRegularFile(); // follow intermediate link
1248 
1249     try {
1250       Files.readSymbolicLink(path("/none"));
1251       fail();
1252     } catch (NoSuchFileException expected) {
1253       assertEquals("/none", expected.getMessage());
1254     }
1255 
1256     try {
1257       Files.readSymbolicLink(path("/file.txt"));
1258       fail();
1259     } catch (NotLinkException expected) {
1260       assertEquals("/file.txt", expected.getMessage());
1261     }
1262   }
1263 
1264   @Test
testSymbolicLinks_symlinkCycle()1265   public void testSymbolicLinks_symlinkCycle() throws IOException {
1266     Files.createDirectory(path("/foo"));
1267     Files.createSymbolicLink(path("/foo/bar"), path("baz"));
1268     Files.createSymbolicLink(path("/foo/baz"), path("bar"));
1269 
1270     try {
1271       Files.createFile(path("/foo/bar/file"));
1272       fail();
1273     } catch (IOException expected) {
1274       assertThat(expected.getMessage()).contains("symbolic link");
1275     }
1276 
1277     try {
1278       Files.write(path("/foo/bar"), preFilledBytes(10));
1279       fail();
1280     } catch (IOException expected) {
1281       assertThat(expected.getMessage()).contains("symbolic link");
1282     }
1283   }
1284 
1285   @Test
testSymbolicLinks_lookupOfAbsoluteSymlinkPathFromRelativePath()1286   public void testSymbolicLinks_lookupOfAbsoluteSymlinkPathFromRelativePath() throws IOException {
1287     // relative path lookups are in the FileSystemView for the working directory
1288     // this tests that when an absolute path is encountered, the lookup handles it correctly
1289 
1290     Files.createDirectories(path("/foo/bar/baz"));
1291     Files.createFile(path("/foo/bar/baz/file"));
1292     Files.createDirectories(path("one/two/three"));
1293     Files.createSymbolicLink(path("/work/one/two/three/link"), path("/foo/bar"));
1294 
1295     assertThatPath("one/two/three/link/baz/file").isSameFileAs("/foo/bar/baz/file");
1296   }
1297 
1298   @Test
testLink()1299   public void testLink() throws IOException {
1300     Files.createFile(path("/file.txt"));
1301     // checking link count requires "unix" attribute support, which we're using here
1302     assertThatPath("/file.txt").hasLinkCount(1);
1303 
1304     Files.createLink(path("/link.txt"), path("/file.txt"));
1305 
1306     assertThatPath("/link.txt").isSameFileAs("/file.txt");
1307 
1308     assertThatPath("/file.txt").hasLinkCount(2);
1309     assertThatPath("/link.txt").hasLinkCount(2);
1310 
1311     assertThatPath("/file.txt").containsNoBytes();
1312     assertThatPath("/link.txt").containsNoBytes();
1313 
1314     byte[] bytes = {0, 1, 2, 3};
1315     Files.write(path("/file.txt"), bytes);
1316 
1317     assertThatPath("/file.txt").containsBytes(bytes);
1318     assertThatPath("/link.txt").containsBytes(bytes);
1319 
1320     Files.write(path("/link.txt"), bytes, APPEND);
1321 
1322     assertThatPath("/file.txt").containsBytes(0, 1, 2, 3, 0, 1, 2, 3);
1323     assertThatPath("/link.txt").containsBytes(0, 1, 2, 3, 0, 1, 2, 3);
1324 
1325     Files.delete(path("/file.txt"));
1326     assertThatPath("/link.txt").hasLinkCount(1);
1327 
1328     assertThatPath("/link.txt").containsBytes(0, 1, 2, 3, 0, 1, 2, 3);
1329   }
1330 
1331   @Test
testLink_forSymbolicLink_usesSymbolicLinkTarget()1332   public void testLink_forSymbolicLink_usesSymbolicLinkTarget() throws IOException {
1333     Files.createFile(path("/file"));
1334     Files.createSymbolicLink(path("/symlink"), path("/file"));
1335 
1336     Object key = getFileKey("/file");
1337 
1338     Files.createLink(path("/link"), path("/symlink"));
1339 
1340     assertThatPath("/link")
1341         .isRegularFile()
1342         .and()
1343         .hasLinkCount(2)
1344         .and()
1345         .attribute("fileKey")
1346         .is(key);
1347   }
1348 
1349   @Test
testLink_failsWhenTargetDoesNotExist()1350   public void testLink_failsWhenTargetDoesNotExist() throws IOException {
1351     try {
1352       Files.createLink(path("/link"), path("/foo"));
1353       fail();
1354     } catch (NoSuchFileException expected) {
1355       assertEquals("/foo", expected.getFile());
1356     }
1357 
1358     Files.createSymbolicLink(path("/foo"), path("/bar"));
1359 
1360     try {
1361       Files.createLink(path("/link"), path("/foo"));
1362       fail();
1363     } catch (NoSuchFileException expected) {
1364       assertEquals("/foo", expected.getFile());
1365     }
1366   }
1367 
1368   @Test
testLink_failsForNonRegularFile()1369   public void testLink_failsForNonRegularFile() throws IOException {
1370     Files.createDirectory(path("/dir"));
1371 
1372     try {
1373       Files.createLink(path("/link"), path("/dir"));
1374       fail();
1375     } catch (FileSystemException expected) {
1376       assertEquals("/link", expected.getFile());
1377       assertEquals("/dir", expected.getOtherFile());
1378     }
1379 
1380     assertThatPath("/link").doesNotExist();
1381   }
1382 
1383   @Test
testLinks_failsWhenTargetFileAlreadyExists()1384   public void testLinks_failsWhenTargetFileAlreadyExists() throws IOException {
1385     Files.createFile(path("/file"));
1386     Files.createFile(path("/link"));
1387 
1388     try {
1389       Files.createLink(path("/link"), path("/file"));
1390       fail();
1391     } catch (FileAlreadyExistsException expected) {
1392       assertEquals("/link", expected.getFile());
1393     }
1394   }
1395 
1396   @Test
testStreams()1397   public void testStreams() throws IOException {
1398     try (OutputStream out = Files.newOutputStream(path("/test"))) {
1399       for (int i = 0; i < 100; i++) {
1400         out.write(i);
1401       }
1402     }
1403 
1404     byte[] expected = new byte[100];
1405     for (byte i = 0; i < 100; i++) {
1406       expected[i] = i;
1407     }
1408 
1409     try (InputStream in = Files.newInputStream(path("/test"))) {
1410       byte[] bytes = new byte[100];
1411       ByteStreams.readFully(in, bytes);
1412       assertArrayEquals(expected, bytes);
1413     }
1414 
1415     try (Writer writer = Files.newBufferedWriter(path("/test.txt"), UTF_8)) {
1416       writer.write("hello");
1417     }
1418 
1419     try (Reader reader = Files.newBufferedReader(path("/test.txt"), UTF_8)) {
1420       assertEquals("hello", CharStreams.toString(reader));
1421     }
1422 
1423     try (Writer writer = Files.newBufferedWriter(path("/test.txt"), UTF_8, APPEND)) {
1424       writer.write(" world");
1425     }
1426 
1427     try (Reader reader = Files.newBufferedReader(path("/test.txt"), UTF_8)) {
1428       assertEquals("hello world", CharStreams.toString(reader));
1429     }
1430   }
1431 
1432   @Test
testOutputStream_withTruncateExistingAndNotWrite_truncatesFile()1433   public void testOutputStream_withTruncateExistingAndNotWrite_truncatesFile() throws IOException {
1434     // https://github.com/google/jimfs/pull/77
1435     Path path = path("/test");
1436     Files.write(path, new byte[] {1, 2, 3});
1437     assertThatPath(path).containsBytes(1, 2, 3);
1438 
1439     try (OutputStream out = Files.newOutputStream(path, CREATE, TRUNCATE_EXISTING)) {
1440       out.write(new byte[] {1, 2});
1441     }
1442 
1443     assertThatPath(path).containsBytes(1, 2);
1444   }
1445 
1446   @Test
testChannels()1447   public void testChannels() throws IOException {
1448     try (FileChannel channel = FileChannel.open(path("/test.txt"), CREATE_NEW, WRITE)) {
1449       ByteBuffer buf1 = UTF_8.encode("hello");
1450       ByteBuffer buf2 = UTF_8.encode(" world");
1451       while (buf1.hasRemaining() || buf2.hasRemaining()) {
1452         channel.write(new ByteBuffer[] {buf1, buf2});
1453       }
1454 
1455       assertEquals(11, channel.position());
1456       assertEquals(11, channel.size());
1457 
1458       channel.write(UTF_8.encode("!"));
1459 
1460       assertEquals(12, channel.position());
1461       assertEquals(12, channel.size());
1462     }
1463 
1464     try (SeekableByteChannel channel = Files.newByteChannel(path("/test.txt"), READ)) {
1465       assertEquals(0, channel.position());
1466       assertEquals(12, channel.size());
1467 
1468       ByteBuffer buffer = ByteBuffer.allocate(100);
1469       while (channel.read(buffer) != -1) {}
1470       buffer.flip();
1471       assertEquals("hello world!", UTF_8.decode(buffer).toString());
1472     }
1473 
1474     byte[] bytes = preFilledBytes(100);
1475 
1476     Files.write(path("/test"), bytes);
1477 
1478     try (SeekableByteChannel channel = Files.newByteChannel(path("/test"), READ, WRITE)) {
1479       ByteBuffer buffer = ByteBuffer.wrap(preFilledBytes(50));
1480 
1481       channel.position(50);
1482       channel.write(buffer);
1483       buffer.flip();
1484       channel.write(buffer);
1485 
1486       channel.position(0);
1487       ByteBuffer readBuffer = ByteBuffer.allocate(150);
1488       while (readBuffer.hasRemaining()) {
1489         channel.read(readBuffer);
1490       }
1491 
1492       byte[] expected = Bytes.concat(preFilledBytes(50), preFilledBytes(50), preFilledBytes(50));
1493 
1494       assertArrayEquals(expected, readBuffer.array());
1495     }
1496 
1497     try (FileChannel channel = FileChannel.open(path("/test"), READ, WRITE)) {
1498       assertEquals(150, channel.size());
1499 
1500       channel.truncate(10);
1501       assertEquals(10, channel.size());
1502 
1503       ByteBuffer buffer = ByteBuffer.allocate(20);
1504       assertEquals(10, channel.read(buffer));
1505       buffer.flip();
1506 
1507       byte[] expected = new byte[20];
1508       System.arraycopy(preFilledBytes(10), 0, expected, 0, 10);
1509       assertArrayEquals(expected, buffer.array());
1510     }
1511   }
1512 
1513   @Test
testCopy_inputStreamToFile()1514   public void testCopy_inputStreamToFile() throws IOException {
1515     byte[] bytes = preFilledBytes(512);
1516 
1517     Files.copy(new ByteArrayInputStream(bytes), path("/test"));
1518     assertThatPath("/test").containsBytes(bytes);
1519 
1520     try {
1521       Files.copy(new ByteArrayInputStream(bytes), path("/test"));
1522       fail();
1523     } catch (FileAlreadyExistsException expected) {
1524       assertEquals("/test", expected.getMessage());
1525     }
1526 
1527     Files.copy(new ByteArrayInputStream(bytes), path("/test"), REPLACE_EXISTING);
1528     assertThatPath("/test").containsBytes(bytes);
1529 
1530     Files.copy(new ByteArrayInputStream(bytes), path("/foo"), REPLACE_EXISTING);
1531     assertThatPath("/foo").containsBytes(bytes);
1532   }
1533 
1534   @Test
testCopy_fileToOutputStream()1535   public void testCopy_fileToOutputStream() throws IOException {
1536     byte[] bytes = preFilledBytes(512);
1537     Files.write(path("/test"), bytes);
1538 
1539     ByteArrayOutputStream out = new ByteArrayOutputStream();
1540     Files.copy(path("/test"), out);
1541     assertArrayEquals(bytes, out.toByteArray());
1542   }
1543 
1544   @Test
testCopy_fileToPath()1545   public void testCopy_fileToPath() throws IOException {
1546     byte[] bytes = preFilledBytes(512);
1547     Files.write(path("/foo"), bytes);
1548 
1549     assertThatPath("/bar").doesNotExist();
1550     Files.copy(path("/foo"), path("/bar"));
1551     assertThatPath("/bar").containsBytes(bytes);
1552 
1553     byte[] moreBytes = preFilledBytes(2048);
1554     Files.write(path("/baz"), moreBytes);
1555 
1556     Files.copy(path("/baz"), path("/bar"), REPLACE_EXISTING);
1557     assertThatPath("/bar").containsBytes(moreBytes);
1558 
1559     try {
1560       Files.copy(path("/none"), path("/bar"));
1561       fail();
1562     } catch (NoSuchFileException expected) {
1563       assertEquals("/none", expected.getMessage());
1564     }
1565   }
1566 
1567   @Test
testCopy_withCopyAttributes()1568   public void testCopy_withCopyAttributes() throws IOException {
1569     Path foo = path("/foo");
1570     Files.createFile(foo);
1571 
1572     Files.getFileAttributeView(foo, BasicFileAttributeView.class)
1573         .setTimes(FileTime.fromMillis(100), FileTime.fromMillis(1000), FileTime.fromMillis(10000));
1574 
1575     assertThat(Files.getAttribute(foo, "lastModifiedTime")).isEqualTo(FileTime.fromMillis(100));
1576 
1577     UserPrincipal zero = fs.getUserPrincipalLookupService().lookupPrincipalByName("zero");
1578     Files.setAttribute(foo, "owner:owner", zero);
1579 
1580     Path bar = path("/bar");
1581     Files.copy(foo, bar, COPY_ATTRIBUTES);
1582 
1583     BasicFileAttributes attributes = Files.readAttributes(bar, BasicFileAttributes.class);
1584     assertThat(attributes.lastModifiedTime()).isEqualTo(FileTime.fromMillis(100));
1585     assertThat(attributes.lastAccessTime()).isEqualTo(FileTime.fromMillis(1000));
1586     assertThat(attributes.creationTime()).isEqualTo(FileTime.fromMillis(10000));
1587     assertThat(Files.getAttribute(bar, "owner:owner")).isEqualTo(zero);
1588 
1589     Path baz = path("/baz");
1590     Files.copy(foo, baz);
1591 
1592     // test that attributes are not copied when COPY_ATTRIBUTES is not specified
1593     attributes = Files.readAttributes(baz, BasicFileAttributes.class);
1594     assertThat(attributes.lastModifiedTime()).isNotEqualTo(FileTime.fromMillis(100));
1595     assertThat(attributes.lastAccessTime()).isNotEqualTo(FileTime.fromMillis(1000));
1596     assertThat(attributes.creationTime()).isNotEqualTo(FileTime.fromMillis(10000));
1597     assertThat(Files.getAttribute(baz, "owner:owner")).isNotEqualTo(zero);
1598   }
1599 
1600   @Test
testCopy_doesNotSupportAtomicMove()1601   public void testCopy_doesNotSupportAtomicMove() throws IOException {
1602     try {
1603       Files.copy(path("/foo"), path("/bar"), ATOMIC_MOVE);
1604       fail();
1605     } catch (UnsupportedOperationException expected) {
1606     }
1607   }
1608 
1609   @Test
testCopy_directoryToPath()1610   public void testCopy_directoryToPath() throws IOException {
1611     Files.createDirectory(path("/foo"));
1612 
1613     assertThatPath("/bar").doesNotExist();
1614     Files.copy(path("/foo"), path("/bar"));
1615     assertThatPath("/bar").isDirectory();
1616   }
1617 
1618   @Test
testCopy_withoutReplaceExisting_failsWhenTargetExists()1619   public void testCopy_withoutReplaceExisting_failsWhenTargetExists() throws IOException {
1620     Files.createFile(path("/bar"));
1621     Files.createDirectory(path("/foo"));
1622 
1623     // dir -> file
1624     try {
1625       Files.copy(path("/foo"), path("/bar"));
1626       fail();
1627     } catch (FileAlreadyExistsException expected) {
1628       assertEquals("/bar", expected.getMessage());
1629     }
1630 
1631     Files.delete(path("/foo"));
1632     Files.createFile(path("/foo"));
1633 
1634     // file -> file
1635     try {
1636       Files.copy(path("/foo"), path("/bar"));
1637       fail();
1638     } catch (FileAlreadyExistsException expected) {
1639       assertEquals("/bar", expected.getMessage());
1640     }
1641 
1642     Files.delete(path("/bar"));
1643     Files.createDirectory(path("/bar"));
1644 
1645     // file -> dir
1646     try {
1647       Files.copy(path("/foo"), path("/bar"));
1648       fail();
1649     } catch (FileAlreadyExistsException expected) {
1650       assertEquals("/bar", expected.getMessage());
1651     }
1652 
1653     Files.delete(path("/foo"));
1654     Files.createDirectory(path("/foo"));
1655 
1656     // dir -> dir
1657     try {
1658       Files.copy(path("/foo"), path("/bar"));
1659       fail();
1660     } catch (FileAlreadyExistsException expected) {
1661       assertEquals("/bar", expected.getMessage());
1662     }
1663   }
1664 
1665   @Test
testCopy_withReplaceExisting()1666   public void testCopy_withReplaceExisting() throws IOException {
1667     Files.createFile(path("/bar"));
1668     Files.createDirectory(path("/test"));
1669 
1670     assertThatPath("/bar").isRegularFile();
1671 
1672     // overwrite regular file w/ directory
1673     Files.copy(path("/test"), path("/bar"), REPLACE_EXISTING);
1674 
1675     assertThatPath("/bar").isDirectory();
1676 
1677     byte[] bytes = {0, 1, 2, 3};
1678     Files.write(path("/baz"), bytes);
1679 
1680     // overwrite directory w/ regular file
1681     Files.copy(path("/baz"), path("/bar"), REPLACE_EXISTING);
1682 
1683     assertThatPath("/bar").containsSameBytesAs("/baz");
1684   }
1685 
1686   @Test
testCopy_withReplaceExisting_cantReplaceNonEmptyDirectory()1687   public void testCopy_withReplaceExisting_cantReplaceNonEmptyDirectory() throws IOException {
1688     Files.createDirectory(path("/foo"));
1689     Files.createDirectory(path("/foo/bar"));
1690     Files.createFile(path("/foo/baz"));
1691 
1692     Files.createDirectory(path("/test"));
1693 
1694     try {
1695       Files.copy(path("/test"), path("/foo"), REPLACE_EXISTING);
1696       fail();
1697     } catch (DirectoryNotEmptyException expected) {
1698       assertEquals("/foo", expected.getMessage());
1699     }
1700 
1701     Files.delete(path("/test"));
1702     Files.createFile(path("/test"));
1703 
1704     try {
1705       Files.copy(path("/test"), path("/foo"), REPLACE_EXISTING);
1706       fail();
1707     } catch (DirectoryNotEmptyException expected) {
1708       assertEquals("/foo", expected.getMessage());
1709     }
1710 
1711     Files.delete(path("/foo/baz"));
1712     Files.delete(path("/foo/bar"));
1713 
1714     Files.copy(path("/test"), path("/foo"), REPLACE_EXISTING);
1715     assertThatPath("/foo").isRegularFile(); // replaced
1716   }
1717 
1718   @Test
testCopy_directoryToPath_doesNotCopyDirectoryContents()1719   public void testCopy_directoryToPath_doesNotCopyDirectoryContents() throws IOException {
1720     Files.createDirectory(path("/foo"));
1721     Files.createDirectory(path("/foo/baz"));
1722     Files.createFile(path("/foo/test"));
1723 
1724     Files.copy(path("/foo"), path("/bar"));
1725     assertThatPath("/bar").hasNoChildren();
1726   }
1727 
1728   @Test
testCopy_symbolicLinkToPath()1729   public void testCopy_symbolicLinkToPath() throws IOException {
1730     byte[] bytes = preFilledBytes(128);
1731     Files.write(path("/test"), bytes);
1732     Files.createSymbolicLink(path("/link"), path("/test"));
1733 
1734     assertThatPath("/bar").doesNotExist();
1735     Files.copy(path("/link"), path("/bar"));
1736     assertThatPath("/bar", NOFOLLOW_LINKS).containsBytes(bytes);
1737 
1738     Files.delete(path("/bar"));
1739 
1740     Files.copy(path("/link"), path("/bar"), NOFOLLOW_LINKS);
1741     assertThatPath("/bar", NOFOLLOW_LINKS).isSymbolicLink().withTarget("/test");
1742     assertThatPath("/bar").isRegularFile();
1743     assertThatPath("/bar").containsBytes(bytes);
1744 
1745     Files.delete(path("/test"));
1746     assertThatPath("/bar", NOFOLLOW_LINKS).isSymbolicLink();
1747     assertThatPath("/bar").doesNotExist();
1748   }
1749 
1750   @Test
testCopy_toDifferentFileSystem()1751   public void testCopy_toDifferentFileSystem() throws IOException {
1752     try (FileSystem fs2 = Jimfs.newFileSystem(UNIX_CONFIGURATION)) {
1753       Path foo = fs.getPath("/foo");
1754       byte[] bytes = {0, 1, 2, 3, 4};
1755       Files.write(foo, bytes);
1756 
1757       Path foo2 = fs2.getPath("/foo");
1758       Files.copy(foo, foo2);
1759 
1760       assertThatPath(foo).exists();
1761       assertThatPath(foo2).exists().and().containsBytes(bytes);
1762     }
1763   }
1764 
1765   @Test
testCopy_toDifferentFileSystem_copyAttributes()1766   public void testCopy_toDifferentFileSystem_copyAttributes() throws IOException {
1767     try (FileSystem fs2 = Jimfs.newFileSystem(UNIX_CONFIGURATION)) {
1768       Path foo = fs.getPath("/foo");
1769       byte[] bytes = {0, 1, 2, 3, 4};
1770       Files.write(foo, bytes);
1771       Files.getFileAttributeView(foo, BasicFileAttributeView.class)
1772           .setTimes(FileTime.fromMillis(0), FileTime.fromMillis(1), FileTime.fromMillis(2));
1773 
1774       UserPrincipal owner = fs.getUserPrincipalLookupService().lookupPrincipalByName("foobar");
1775       Files.setOwner(foo, owner);
1776 
1777       assertThatPath(foo).attribute("owner:owner").is(owner);
1778 
1779       Path foo2 = fs2.getPath("/foo");
1780       Files.copy(foo, foo2, COPY_ATTRIBUTES);
1781 
1782       assertThatPath(foo).exists();
1783 
1784       // when copying with COPY_ATTRIBUTES to a different FileSystem, only basic attributes (that
1785       // is, file times) can actually be copied
1786       assertThatPath(foo2)
1787           .exists()
1788           .and()
1789           .attribute("lastModifiedTime")
1790           .is(FileTime.fromMillis(0))
1791           .and()
1792           .attribute("lastAccessTime")
1793           .is(FileTime.fromMillis(1))
1794           .and()
1795           .attribute("creationTime")
1796           .is(FileTime.fromMillis(2))
1797           .and()
1798           .attribute("owner:owner")
1799           .isNot(owner)
1800           .and()
1801           .attribute("owner:owner")
1802           .isNot(fs2.getUserPrincipalLookupService().lookupPrincipalByName("foobar"))
1803           .and()
1804           .containsBytes(bytes); // do this last; it updates the access time
1805     }
1806   }
1807 
1808   @Test
testMove()1809   public void testMove() throws IOException {
1810     byte[] bytes = preFilledBytes(100);
1811     Files.write(path("/foo"), bytes);
1812 
1813     Object fooKey = getFileKey("/foo");
1814 
1815     Files.move(path("/foo"), path("/bar"));
1816     assertThatPath("/foo").doesNotExist();
1817     assertThatPath("/bar").containsBytes(bytes).and().attribute("fileKey").is(fooKey);
1818 
1819     Files.createDirectory(path("/foo"));
1820     Files.move(path("/bar"), path("/foo/bar"));
1821 
1822     assertThatPath("/bar").doesNotExist();
1823     assertThatPath("/foo/bar").isRegularFile();
1824 
1825     Files.move(path("/foo"), path("/baz"));
1826     assertThatPath("/foo").doesNotExist();
1827     assertThatPath("/baz").isDirectory();
1828     assertThatPath("/baz/bar").isRegularFile();
1829   }
1830 
1831   @Test
testMove_movesSymbolicLinkNotTarget()1832   public void testMove_movesSymbolicLinkNotTarget() throws IOException {
1833     byte[] bytes = preFilledBytes(100);
1834     Files.write(path("/foo.txt"), bytes);
1835 
1836     Files.createSymbolicLink(path("/link"), path("foo.txt"));
1837 
1838     Files.move(path("/link"), path("/link.txt"));
1839 
1840     assertThatPath("/foo.txt").noFollowLinks().isRegularFile().and().containsBytes(bytes);
1841 
1842     assertThatPath(path("/link")).doesNotExist();
1843 
1844     assertThatPath(path("/link.txt")).noFollowLinks().isSymbolicLink();
1845 
1846     assertThatPath(path("/link.txt")).isRegularFile().and().containsBytes(bytes);
1847   }
1848 
1849   @Test
testMove_cannotMoveDirIntoOwnSubtree()1850   public void testMove_cannotMoveDirIntoOwnSubtree() throws IOException {
1851     Files.createDirectories(path("/foo"));
1852 
1853     try {
1854       Files.move(path("/foo"), path("/foo/bar"));
1855       fail();
1856     } catch (IOException expected) {
1857       assertThat(expected.getMessage()).contains("sub");
1858     }
1859 
1860     Files.createDirectories(path("/foo/bar/baz/stuff"));
1861     Files.createDirectories(path("/hello/world"));
1862     Files.createSymbolicLink(path("/hello/world/link"), path("../../foo/bar/baz"));
1863 
1864     try {
1865       Files.move(path("/foo/bar"), path("/hello/world/link/bar"));
1866       fail();
1867     } catch (IOException expected) {
1868       assertThat(expected.getMessage()).contains("sub");
1869     }
1870   }
1871 
1872   @Test
testMove_withoutReplaceExisting_failsWhenTargetExists()1873   public void testMove_withoutReplaceExisting_failsWhenTargetExists() throws IOException {
1874     byte[] bytes = preFilledBytes(50);
1875     Files.write(path("/test"), bytes);
1876 
1877     Object testKey = getFileKey("/test");
1878 
1879     Files.createFile(path("/bar"));
1880 
1881     try {
1882       Files.move(path("/test"), path("/bar"), ATOMIC_MOVE);
1883       fail();
1884     } catch (FileAlreadyExistsException expected) {
1885       assertEquals("/bar", expected.getMessage());
1886     }
1887 
1888     assertThatPath("/test").containsBytes(bytes).and().attribute("fileKey").is(testKey);
1889 
1890     Files.delete(path("/bar"));
1891     Files.createDirectory(path("/bar"));
1892 
1893     try {
1894       Files.move(path("/test"), path("/bar"), ATOMIC_MOVE);
1895       fail();
1896     } catch (FileAlreadyExistsException expected) {
1897       assertEquals("/bar", expected.getMessage());
1898     }
1899 
1900     assertThatPath("/test").containsBytes(bytes).and().attribute("fileKey").is(testKey);
1901   }
1902 
1903   @Test
testMove_toDifferentFileSystem()1904   public void testMove_toDifferentFileSystem() throws IOException {
1905     try (FileSystem fs2 = Jimfs.newFileSystem(Configuration.unix())) {
1906       Path foo = fs.getPath("/foo");
1907       byte[] bytes = {0, 1, 2, 3, 4};
1908       Files.write(foo, bytes);
1909       Files.getFileAttributeView(foo, BasicFileAttributeView.class)
1910           .setTimes(FileTime.fromMillis(0), FileTime.fromMillis(1), FileTime.fromMillis(2));
1911 
1912       Path foo2 = fs2.getPath("/foo");
1913       Files.move(foo, foo2);
1914 
1915       assertThatPath(foo).doesNotExist();
1916       assertThatPath(foo2)
1917           .exists()
1918           .and()
1919           .attribute("lastModifiedTime")
1920           .is(FileTime.fromMillis(0))
1921           .and()
1922           .attribute("lastAccessTime")
1923           .is(FileTime.fromMillis(1))
1924           .and()
1925           .attribute("creationTime")
1926           .is(FileTime.fromMillis(2))
1927           .and()
1928           .containsBytes(bytes); // do this last; it updates the access time
1929     }
1930   }
1931 
1932   @Test
testIsSameFile()1933   public void testIsSameFile() throws IOException {
1934     Files.createDirectory(path("/foo"));
1935     Files.createSymbolicLink(path("/bar"), path("/foo"));
1936     Files.createFile(path("/bar/test"));
1937 
1938     assertThatPath("/foo").isSameFileAs("/foo");
1939     assertThatPath("/bar").isSameFileAs("/bar");
1940     assertThatPath("/foo/test").isSameFileAs("/foo/test");
1941     assertThatPath("/bar/test").isSameFileAs("/bar/test");
1942     assertThatPath("/foo").isNotSameFileAs("test");
1943     assertThatPath("/bar").isNotSameFileAs("/test");
1944     assertThatPath("/foo").isSameFileAs("/bar");
1945     assertThatPath("/foo/test").isSameFileAs("/bar/test");
1946 
1947     Files.createSymbolicLink(path("/baz"), path("bar")); // relative path
1948     assertThatPath("/baz").isSameFileAs("/foo");
1949     assertThatPath("/baz/test").isSameFileAs("/foo/test");
1950   }
1951 
1952   @Test
testIsSameFile_forPathFromDifferentFileSystemProvider()1953   public void testIsSameFile_forPathFromDifferentFileSystemProvider() throws IOException {
1954     Path defaultFileSystemRoot = FileSystems.getDefault().getRootDirectories().iterator().next();
1955 
1956     assertThat(Files.isSameFile(path("/"), defaultFileSystemRoot)).isFalse();
1957   }
1958 
1959   @Test
testPathLookups()1960   public void testPathLookups() throws IOException {
1961     assertThatPath("/").isSameFileAs("/");
1962     assertThatPath("/..").isSameFileAs("/");
1963     assertThatPath("/../../..").isSameFileAs("/");
1964     assertThatPath("../../../..").isSameFileAs("/");
1965     assertThatPath("").isSameFileAs("/work");
1966 
1967     Files.createDirectories(path("/foo/bar/baz"));
1968     Files.createSymbolicLink(path("/foo/bar/link1"), path("../link2"));
1969     Files.createSymbolicLink(path("/foo/link2"), path("/"));
1970 
1971     assertThatPath("/foo/bar/link1/foo/bar/link1/foo").isSameFileAs("/foo");
1972   }
1973 
1974   @Test
testSecureDirectoryStream()1975   public void testSecureDirectoryStream() throws IOException {
1976     Files.createDirectories(path("/foo/bar"));
1977     Files.createFile(path("/foo/a"));
1978     Files.createFile(path("/foo/b"));
1979     Files.createSymbolicLink(path("/foo/barLink"), path("bar"));
1980 
1981     try (DirectoryStream<Path> stream = Files.newDirectoryStream(path("/foo"))) {
1982       if (!(stream instanceof SecureDirectoryStream)) {
1983         fail("should be a secure directory stream");
1984       }
1985 
1986       SecureDirectoryStream<Path> secureStream = (SecureDirectoryStream<Path>) stream;
1987 
1988       assertThat(ImmutableList.copyOf(secureStream))
1989           .isEqualTo(
1990               ImmutableList.of(
1991                   path("/foo/a"), path("/foo/b"), path("/foo/bar"), path("/foo/barLink")));
1992 
1993       secureStream.deleteFile(path("b"));
1994       assertThatPath("/foo/b").doesNotExist();
1995 
1996       secureStream.newByteChannel(path("b"), ImmutableSet.of(WRITE, CREATE_NEW)).close();
1997       assertThatPath("/foo/b").isRegularFile();
1998 
1999       assertThatPath("/foo").hasChildren("a", "b", "bar", "barLink");
2000 
2001       Files.createDirectory(path("/baz"));
2002       Files.move(path("/foo"), path("/baz/stuff"));
2003 
2004       assertThatPath(path("/foo")).doesNotExist();
2005 
2006       assertThatPath("/baz/stuff").hasChildren("a", "b", "bar", "barLink");
2007 
2008       secureStream.deleteFile(path("b"));
2009 
2010       assertThatPath("/baz/stuff/b").doesNotExist();
2011       assertThatPath("/baz/stuff").hasChildren("a", "bar", "barLink");
2012 
2013       assertThat(
2014               secureStream
2015                   .getFileAttributeView(BasicFileAttributeView.class)
2016                   .readAttributes()
2017                   .isDirectory())
2018           .isTrue();
2019 
2020       assertThat(
2021               secureStream
2022                   .getFileAttributeView(path("a"), BasicFileAttributeView.class)
2023                   .readAttributes()
2024                   .isRegularFile())
2025           .isTrue();
2026 
2027       try {
2028         secureStream.deleteFile(path("bar"));
2029         fail();
2030       } catch (FileSystemException expected) {
2031         assertThat(expected.getFile()).isEqualTo("bar");
2032       }
2033 
2034       try {
2035         secureStream.deleteDirectory(path("a"));
2036         fail();
2037       } catch (FileSystemException expected) {
2038         assertThat(expected.getFile()).isEqualTo("a");
2039       }
2040 
2041       try (SecureDirectoryStream<Path> barStream = secureStream.newDirectoryStream(path("bar"))) {
2042         barStream.newByteChannel(path("stuff"), ImmutableSet.of(WRITE, CREATE_NEW)).close();
2043         assertThat(
2044                 barStream
2045                     .getFileAttributeView(path("stuff"), BasicFileAttributeView.class)
2046                     .readAttributes()
2047                     .isRegularFile())
2048             .isTrue();
2049 
2050         assertThat(
2051                 secureStream
2052                     .getFileAttributeView(path("bar/stuff"), BasicFileAttributeView.class)
2053                     .readAttributes()
2054                     .isRegularFile())
2055             .isTrue();
2056       }
2057 
2058       try (SecureDirectoryStream<Path> barLinkStream =
2059           secureStream.newDirectoryStream(path("barLink"))) {
2060         assertThat(
2061                 barLinkStream
2062                     .getFileAttributeView(path("stuff"), BasicFileAttributeView.class)
2063                     .readAttributes()
2064                     .isRegularFile())
2065             .isTrue();
2066 
2067         assertThat(
2068                 barLinkStream
2069                     .getFileAttributeView(path(".."), BasicFileAttributeView.class)
2070                     .readAttributes()
2071                     .isDirectory())
2072             .isTrue();
2073       }
2074 
2075       try {
2076         secureStream.newDirectoryStream(path("barLink"), NOFOLLOW_LINKS);
2077         fail();
2078       } catch (NotDirectoryException expected) {
2079         assertThat(expected.getFile()).isEqualTo("barLink");
2080       }
2081 
2082       try (SecureDirectoryStream<Path> barStream = secureStream.newDirectoryStream(path("bar"))) {
2083         secureStream.move(path("a"), barStream, path("moved"));
2084 
2085         assertThatPath(path("/baz/stuff/a")).doesNotExist();
2086         assertThatPath(path("/baz/stuff/bar/moved")).isRegularFile();
2087 
2088         assertThat(
2089                 barStream
2090                     .getFileAttributeView(path("moved"), BasicFileAttributeView.class)
2091                     .readAttributes()
2092                     .isRegularFile())
2093             .isTrue();
2094       }
2095     }
2096   }
2097 
2098   @Test
testSecureDirectoryStreamBasedOnRelativePath()2099   public void testSecureDirectoryStreamBasedOnRelativePath() throws IOException {
2100     Files.createDirectories(path("foo"));
2101     Files.createFile(path("foo/a"));
2102     Files.createFile(path("foo/b"));
2103     Files.createDirectory(path("foo/c"));
2104     Files.createFile(path("foo/c/d"));
2105     Files.createFile(path("foo/c/e"));
2106 
2107     try (DirectoryStream<Path> stream = Files.newDirectoryStream(path("foo"))) {
2108       SecureDirectoryStream<Path> secureStream = (SecureDirectoryStream<Path>) stream;
2109 
2110       assertThat(ImmutableList.copyOf(secureStream))
2111           .containsExactly(path("foo/a"), path("foo/b"), path("foo/c"));
2112 
2113       try (DirectoryStream<Path> stream2 = secureStream.newDirectoryStream(path("c"))) {
2114         assertThat(ImmutableList.copyOf(stream2)).containsExactly(path("foo/c/d"), path("foo/c/e"));
2115       }
2116     }
2117   }
2118 
2119   @SuppressWarnings("StreamResourceLeak")
2120   @Test
testClosedSecureDirectoryStream()2121   public void testClosedSecureDirectoryStream() throws IOException {
2122     Files.createDirectory(path("/foo"));
2123     SecureDirectoryStream<Path> stream =
2124         (SecureDirectoryStream<Path>) Files.newDirectoryStream(path("/foo"));
2125 
2126     stream.close();
2127 
2128     try {
2129       stream.iterator();
2130       fail("expected ClosedDirectoryStreamException");
2131     } catch (ClosedDirectoryStreamException expected) {
2132     }
2133 
2134     try {
2135       stream.deleteDirectory(fs.getPath("a"));
2136       fail("expected ClosedDirectoryStreamException");
2137     } catch (ClosedDirectoryStreamException expected) {
2138     }
2139 
2140     try {
2141       stream.deleteFile(fs.getPath("a"));
2142       fail("expected ClosedDirectoryStreamException");
2143     } catch (ClosedDirectoryStreamException expected) {
2144     }
2145 
2146     try {
2147       stream.newByteChannel(fs.getPath("a"), ImmutableSet.of(CREATE, WRITE));
2148       fail("expected ClosedDirectoryStreamException");
2149     } catch (ClosedDirectoryStreamException expected) {
2150     }
2151 
2152     try {
2153       stream.newDirectoryStream(fs.getPath("a"));
2154       fail("expected ClosedDirectoryStreamException");
2155     } catch (ClosedDirectoryStreamException expected) {
2156     }
2157 
2158     try {
2159       stream.move(fs.getPath("a"), stream, fs.getPath("b"));
2160       fail("expected ClosedDirectoryStreamException");
2161     } catch (ClosedDirectoryStreamException expected) {
2162     }
2163 
2164     try {
2165       stream.getFileAttributeView(BasicFileAttributeView.class);
2166       fail("expected ClosedDirectoryStreamException");
2167     } catch (ClosedDirectoryStreamException expected) {
2168     }
2169 
2170     try {
2171       stream.getFileAttributeView(fs.getPath("a"), BasicFileAttributeView.class);
2172       fail("expected ClosedDirectoryStreamException");
2173     } catch (ClosedDirectoryStreamException expected) {
2174     }
2175   }
2176 
2177   @SuppressWarnings("StreamResourceLeak")
2178   @Test
testClosedSecureDirectoryStreamAttributeViewAndIterator()2179   public void testClosedSecureDirectoryStreamAttributeViewAndIterator() throws IOException {
2180     Files.createDirectory(path("/foo"));
2181     Files.createDirectory(path("/foo/bar"));
2182     SecureDirectoryStream<Path> stream =
2183         (SecureDirectoryStream<Path>) Files.newDirectoryStream(path("/foo"));
2184 
2185     Iterator<Path> iter = stream.iterator();
2186     BasicFileAttributeView view1 = stream.getFileAttributeView(BasicFileAttributeView.class);
2187     BasicFileAttributeView view2 =
2188         stream.getFileAttributeView(path("bar"), BasicFileAttributeView.class);
2189 
2190     try {
2191       stream.iterator();
2192       fail("expected IllegalStateException");
2193     } catch (IllegalStateException expected) {
2194     }
2195 
2196     stream.close();
2197 
2198     try {
2199       iter.next();
2200       fail("expected ClosedDirectoryStreamException");
2201     } catch (ClosedDirectoryStreamException expected) {
2202     }
2203 
2204     try {
2205       view1.readAttributes();
2206       fail("expected ClosedDirectoryStreamException");
2207     } catch (ClosedDirectoryStreamException expected) {
2208     }
2209 
2210     try {
2211       view2.readAttributes();
2212       fail("expected ClosedDirectoryStreamException");
2213     } catch (ClosedDirectoryStreamException expected) {
2214     }
2215 
2216     try {
2217       view1.setTimes(null, null, null);
2218       fail("expected ClosedDirectoryStreamException");
2219     } catch (ClosedDirectoryStreamException expected) {
2220     }
2221 
2222     try {
2223       view2.setTimes(null, null, null);
2224       fail("expected ClosedDirectoryStreamException");
2225     } catch (ClosedDirectoryStreamException expected) {
2226     }
2227   }
2228 
2229   @Test
testDirectoryAccessAndModifiedTimeUpdates()2230   public void testDirectoryAccessAndModifiedTimeUpdates() throws IOException {
2231     Files.createDirectories(path("/foo/bar"));
2232     FileTimeTester tester = new FileTimeTester(path("/foo/bar"));
2233     tester.assertAccessTimeDidNotChange();
2234     tester.assertModifiedTimeDidNotChange();
2235 
2236     // TODO(cgdecker): Use a Clock for file times so I can test this reliably without sleeping
2237     Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2238     Files.createFile(path("/foo/bar/baz.txt"));
2239 
2240     tester.assertAccessTimeDidNotChange();
2241     tester.assertModifiedTimeChanged();
2242 
2243     Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2244     // access time is updated by reading the full contents of the directory
2245     // not just by doing a lookup in it
2246     try (DirectoryStream<Path> stream = Files.newDirectoryStream(path("/foo/bar"))) {
2247       // iterate the stream, forcing the directory to actually be read
2248       Iterators.advance(stream.iterator(), Integer.MAX_VALUE);
2249     }
2250 
2251     tester.assertAccessTimeChanged();
2252     tester.assertModifiedTimeDidNotChange();
2253 
2254     Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2255     Files.move(path("/foo/bar/baz.txt"), path("/foo/bar/baz2.txt"));
2256 
2257     tester.assertAccessTimeDidNotChange();
2258     tester.assertModifiedTimeChanged();
2259 
2260     Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2261     Files.delete(path("/foo/bar/baz2.txt"));
2262 
2263     tester.assertAccessTimeDidNotChange();
2264     tester.assertModifiedTimeChanged();
2265   }
2266 
2267   @Test
testRegularFileAccessAndModifiedTimeUpdates()2268   public void testRegularFileAccessAndModifiedTimeUpdates() throws IOException {
2269     Path foo = path("foo");
2270     Files.createFile(foo);
2271 
2272     FileTimeTester tester = new FileTimeTester(foo);
2273     tester.assertAccessTimeDidNotChange();
2274     tester.assertModifiedTimeDidNotChange();
2275 
2276     Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2277     try (FileChannel channel = FileChannel.open(foo, READ)) {
2278       // opening READ channel does not change times
2279       tester.assertAccessTimeDidNotChange();
2280       tester.assertModifiedTimeDidNotChange();
2281 
2282       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2283       channel.read(ByteBuffer.allocate(100));
2284 
2285       // read call on channel does
2286       tester.assertAccessTimeChanged();
2287       tester.assertModifiedTimeDidNotChange();
2288 
2289       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2290       channel.read(ByteBuffer.allocate(100));
2291 
2292       tester.assertAccessTimeChanged();
2293       tester.assertModifiedTimeDidNotChange();
2294 
2295       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2296       try {
2297         channel.write(ByteBuffer.wrap(new byte[] {0, 1, 2, 3}));
2298       } catch (NonWritableChannelException ignore) {
2299       }
2300 
2301       // failed write on non-readable channel does not change times
2302       tester.assertAccessTimeDidNotChange();
2303       tester.assertModifiedTimeDidNotChange();
2304 
2305       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2306     }
2307 
2308     // closing channel does not change times
2309     tester.assertAccessTimeDidNotChange();
2310     tester.assertModifiedTimeDidNotChange();
2311 
2312     Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2313     try (FileChannel channel = FileChannel.open(foo, WRITE)) {
2314       // opening WRITE channel does not change times
2315       tester.assertAccessTimeDidNotChange();
2316       tester.assertModifiedTimeDidNotChange();
2317 
2318       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2319       channel.write(ByteBuffer.wrap(new byte[] {0, 1, 2, 3}));
2320 
2321       // write call on channel does
2322       tester.assertAccessTimeDidNotChange();
2323       tester.assertModifiedTimeChanged();
2324 
2325       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2326       channel.write(ByteBuffer.wrap(new byte[] {4, 5, 6, 7}));
2327 
2328       tester.assertAccessTimeDidNotChange();
2329       tester.assertModifiedTimeChanged();
2330 
2331       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2332       try {
2333         channel.read(ByteBuffer.allocate(100));
2334       } catch (NonReadableChannelException ignore) {
2335       }
2336 
2337       // failed read on non-readable channel does not change times
2338       tester.assertAccessTimeDidNotChange();
2339       tester.assertModifiedTimeDidNotChange();
2340 
2341       Uninterruptibles.sleepUninterruptibly(1, MILLISECONDS);
2342     }
2343 
2344     // closing channel does not change times
2345     tester.assertAccessTimeDidNotChange();
2346     tester.assertModifiedTimeDidNotChange();
2347   }
2348 
2349   @Test
testUnsupportedFeatures()2350   public void testUnsupportedFeatures() throws IOException {
2351     FileSystem fileSystem =
2352         Jimfs.newFileSystem(
2353             Configuration.unix().toBuilder()
2354                 .setSupportedFeatures() // none
2355                 .build());
2356 
2357     Path foo = fileSystem.getPath("foo");
2358     Path bar = foo.resolveSibling("bar");
2359 
2360     try {
2361       Files.createLink(foo, bar);
2362       fail();
2363     } catch (UnsupportedOperationException expected) {
2364     }
2365 
2366     try {
2367       Files.createSymbolicLink(foo, bar);
2368       fail();
2369     } catch (UnsupportedOperationException expected) {
2370     }
2371 
2372     try {
2373       Files.readSymbolicLink(foo);
2374       fail();
2375     } catch (UnsupportedOperationException expected) {
2376     }
2377 
2378     try {
2379       FileChannel.open(foo);
2380       fail();
2381     } catch (UnsupportedOperationException expected) {
2382     }
2383 
2384     try {
2385       AsynchronousFileChannel.open(foo);
2386       fail();
2387     } catch (UnsupportedOperationException expected) {
2388     }
2389 
2390     Files.createDirectory(foo);
2391     Files.createFile(bar);
2392 
2393     try (DirectoryStream<Path> stream = Files.newDirectoryStream(foo)) {
2394       assertThat(stream).isNotInstanceOf(SecureDirectoryStream.class);
2395     }
2396 
2397     try (SeekableByteChannel channel = Files.newByteChannel(bar)) {
2398       assertThat(channel).isNotInstanceOf(FileChannel.class);
2399     }
2400   }
2401 }
2402