package com.github.marschall.memoryfilesystem; import static com.github.marschall.memoryfilesystem.FileExistsMatcher.exists; import static com.github.marschall.memoryfilesystem.IsAbsoluteMatcher.isAbsolute; import static com.github.marschall.memoryfilesystem.IsAbsoluteMatcher.isRelative; import static com.github.marschall.memoryfilesystem.IsHiddenMatcher.isHidden; import static java.nio.file.AccessMode.EXECUTE; import static java.nio.file.AccessMode.READ; import static java.nio.file.AccessMode.WRITE; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.channels.ByteChannel; import java.nio.file.AccessDeniedException; import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystemException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.DosFileAttributeView; import java.nio.file.attribute.DosFileAttributes; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileTime; import java.nio.file.spi.FileSystemProvider; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; public class WindowsMemoryFileSystemTest { @Rule public final WindowsFileSystemRule rule = new WindowsFileSystemRule(); @Test public void setAttributes() throws IOException, ParseException { FileSystem fileSystem = this.rule.getFileSystem(); FileAttribute<?> hiddenAttribute = new StubFileAttribute<>("dos:hidden", true); Path hiddenPath = fileSystem.getPath("hidden"); Files.createFile(hiddenPath, hiddenAttribute); DosFileAttributeView dosAttributeView = Files.getFileAttributeView(hiddenPath, DosFileAttributeView.class); assertTrue(dosAttributeView.readAttributes().isHidden()); } @Test public void pathToUri() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path path = fileSystem.getPath("C:\\file.txt"); URI uri = path.toUri(); assertEquals(uri, URI.create("memory:WindowsFileSystemRule:///C:/file.txt")); Path back = Paths.get(uri); assertEquals(path, back); } @Test public void uriSingleSlash() throws IOException, URISyntaxException { FileSystem fileSystem = this.rule.getFileSystem(); Path path = fileSystem.getPath("C:\\file.txt"); URI uri = URI.create("memory:WindowsFileSystemRule:/C:/file.txt"); Path back = Paths.get(uri); assertEquals(path, back); } @Test public void pathToWhiteSpace() throws IOException, URISyntaxException { FileSystem fileSystem = this.rule.getFileSystem(); Path path = fileSystem.getPath("C:\\z z"); URI uri = path.toUri(); Path back = Paths.get(uri); assertEquals(path, back); } @Test public void dosAttributeNames() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path path = fileSystem.getPath("C:\\file.txt"); Files.createFile(path); Map<String, Object> attributes = Files.readAttributes(path, "dos:*"); List<String> expectedAttributeNames = Arrays.asList("readonly", "hidden", "system", "archive", // dos // basic "lastModifiedTime", "lastAccessTime", "creationTime", "size", "isRegularFile", "isDirectory", "isSymbolicLink", "isOther", "fileKey"); assertEquals(new HashSet<>(expectedAttributeNames), attributes.keySet()); } @Test public void readAttributes() throws IOException, ParseException { FileSystem fileSystem = this.rule.getFileSystem(); Path path = fileSystem.getPath("C:\\file.txt"); Files.createFile(path); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); FileTime lastModifiedTime = FileTime.fromMillis(format.parse("2012-11-07T20:30:22").getTime()); FileTime lastAccessTime = FileTime.fromMillis(format.parse("2012-10-07T20:30:22").getTime()); FileTime createTime = FileTime.fromMillis(format.parse("2012-09-07T20:30:22").getTime()); BasicFileAttributeView basicFileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class); basicFileAttributeView.setTimes(lastModifiedTime, lastAccessTime, createTime); DosFileAttributeView dosFileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class); dosFileAttributeView.setHidden(true); Map<String, Object> attributes = Files.readAttributes(path, "dos:lastModifiedTime,lastAccessTime,size,hidden"); Map<String, Object> expected = new HashMap<String, Object>(4); expected.put("size", 0L); expected.put("lastModifiedTime", lastModifiedTime); expected.put("lastAccessTime", lastAccessTime); expected.put("hidden", true); assertEquals(expected, attributes); } @Test public void windows() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path c1 = fileSystem.getPath("C:\\"); Path c2 = fileSystem.getPath("c:\\"); assertEquals("C:\\", c1.toString()); assertEquals(c1.hashCode(), c2.hashCode()); assertTrue(c1.startsWith(c2)); assertTrue(c1.startsWith("c:\\")); assertEquals(c1, c2); c1 = fileSystem.getPath("C:\\TEMP"); c2 = fileSystem.getPath("c:\\temp"); assertEquals("C:\\TEMP", c1.toString()); assertTrue(c1.startsWith(c2)); assertTrue(c1.startsWith("c:\\")); } @Test public void windowsDiffrentFileSystems() throws IOException { URI uri1 = URI.create("memory:uri1"); URI uri2 = URI.create("memory:uri2"); Map<String, ?> env = MemoryFileSystemBuilder.newWindows().buildEnvironment(); try ( FileSystem fileSystem1 = FileSystems.newFileSystem(uri1, env); FileSystem fileSystem2 = FileSystems.newFileSystem(uri2, env)) { Path c1 = fileSystem1.getPath("C:\\"); Path c2 = fileSystem2.getPath("C:\\\\"); assertThat(c1, equalTo(c1)); assertThat(c2, equalTo(c2)); // different file systems assertThat(c1, not(equalTo(c2))); assertThat(c2, not(equalTo(c1))); } } @Test public void forbiddenCharacters() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); for (char c : "\\/:?\"<>|".toCharArray()) { try { fileSystem.getPath(Character.toString(c) + ".txt"); fail(c + " should be forbidden"); } catch (InvalidPathException e) { // should reach here } } } @Test public void windowsQuirky() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path c1 = fileSystem.getPath("C:\\"); Path c2 = fileSystem.getPath("c:\\"); assertEquals("c:\\", c2.toString()); c1 = fileSystem.getPath("C:\\TEMP"); c2 = fileSystem.getPath("c:\\temp"); assertEquals("c:\\temp", c2.toString()); assertEquals(c1.hashCode(), c2.hashCode()); } @Test public void checkAccess() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path file = fileSystem.getPath("file.txt"); Files.createFile(file); DosFileAttributeView attributeView = Files.getFileAttributeView(file, DosFileAttributeView.class); DosFileAttributes attributes = attributeView.readAttributes(); assertFalse("is read only", attributes.isReadOnly()); FileSystemProvider provider = file.getFileSystem().provider(); provider.checkAccess(file, READ); provider.checkAccess(file, WRITE); provider.checkAccess(file, EXECUTE); attributeView.setReadOnly(true); provider.checkAccess(file, READ); provider.checkAccess(file, EXECUTE); try { provider.checkAccess(file, WRITE); fail("write should not be permitted"); } catch (AccessDeniedException e) { // should reach here } } @Test public void copyAttributes() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path source = fileSystem.getPath("source.txt"); Path target = fileSystem.getPath("target.txt"); Files.createFile(source); DosFileAttributeView sourceDosFileAttributeView = Files.getFileAttributeView(source, DosFileAttributeView.class); DosFileAttributes sourceDosAttributes = sourceDosFileAttributeView.readAttributes(); assertFalse(sourceDosAttributes.isArchive()); assertFalse(sourceDosAttributes.isHidden()); assertFalse(sourceDosAttributes.isReadOnly()); assertFalse(sourceDosAttributes.isSystem()); sourceDosFileAttributeView.setArchive(true); sourceDosFileAttributeView.setHidden(true); sourceDosFileAttributeView.setReadOnly(true); sourceDosFileAttributeView.setSystem(true); Files.copy(source, target, StandardCopyOption.COPY_ATTRIBUTES); DosFileAttributeView targetDosFileAttributeView = Files.getFileAttributeView(target, DosFileAttributeView.class); DosFileAttributes targetDosAttributes = targetDosFileAttributeView.readAttributes(); assertTrue(targetDosAttributes.isArchive()); assertTrue(targetDosAttributes.isHidden()); assertTrue(targetDosAttributes.isReadOnly()); assertTrue(targetDosAttributes.isSystem()); } @Test public void dontCopyAttributes() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path source = fileSystem.getPath("source.txt"); Path target = fileSystem.getPath("target.txt"); Files.createFile(source); DosFileAttributeView sourceDosFileAttributeView = Files.getFileAttributeView(source, DosFileAttributeView.class); DosFileAttributes sourceDosAttributes = sourceDosFileAttributeView.readAttributes(); assertFalse(sourceDosAttributes.isArchive()); assertFalse(sourceDosAttributes.isHidden()); assertFalse(sourceDosAttributes.isReadOnly()); assertFalse(sourceDosAttributes.isSystem()); sourceDosFileAttributeView.setArchive(true); sourceDosFileAttributeView.setHidden(true); sourceDosFileAttributeView.setReadOnly(true); sourceDosFileAttributeView.setSystem(true); Files.copy(source, target); DosFileAttributeView targetDosFileAttributeView = Files.getFileAttributeView(target, DosFileAttributeView.class); DosFileAttributes targetDosAttributes = targetDosFileAttributeView.readAttributes(); assertFalse(targetDosAttributes.isArchive()); assertFalse(targetDosAttributes.isHidden()); assertFalse(targetDosAttributes.isReadOnly()); assertFalse(targetDosAttributes.isSystem()); } @Test public void isHiddenPathResolution() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path hidden = fileSystem.getPath("hidden.txt"); Files.createFile(hidden); DosFileAttributeView attributeView = Files.getFileAttributeView(hidden, DosFileAttributeView.class); attributeView.setHidden(true); assertThat(hidden, isHidden()); hidden = fileSystem.getPath("hidden.txt/.././hidden.txt"); assertThat(hidden, isHidden()); } @Test public void pathOrdering() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path lowerA = fileSystem.getPath("a"); Path upperA = fileSystem.getPath("A"); assertEquals(0, lowerA.compareTo(lowerA)); assertEquals(0, upperA.compareTo(lowerA)); assertEquals(0, lowerA.compareTo(upperA)); assertEquals(0, upperA.compareTo(upperA)); assertEquals(lowerA, lowerA); assertEquals(lowerA, upperA); assertEquals(upperA, lowerA); assertEquals(upperA, upperA); Path c = fileSystem.getPath("C:\\"); Path d = fileSystem.getPath("D:\\"); assertThat(c, lessThan(d)); assertThat(d, greaterThan(c)); } // https://bugs.openjdk.java.net/browse/JDK-8066915 @Test public void jdk8066915() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path directory = fileSystem.getPath("directory"); directory = Files.createDirectory(directory); try (ByteChannel channel = Files.newByteChannel(directory)) { fail("should not be able to create channel on directory"); } catch (FileSystemException e) { // should reach here assertEquals("file", directory.toAbsolutePath().toString(), e.getFile()); } try (ByteChannel channel = Files.newByteChannel(directory, StandardOpenOption.READ)) { fail("should not be able to create channel on directory"); } catch (FileSystemException e) { // should reach here assertEquals("file", directory.toAbsolutePath().toString(), e.getFile()); } try (ByteChannel channel = Files.newByteChannel(directory, StandardOpenOption.WRITE)) { fail("should not be able to create channel on directory"); } catch (FileSystemException e) { // should reach here assertEquals("file", directory.toAbsolutePath().toString(), e.getFile()); } } // https://bugs.openjdk.java.net/browse/JDK-8072495 @Test public void jdk8072495() { FileSystem fileSystem = this.rule.getFileSystem(); Path x = fileSystem.getPath("x"); Path empty = fileSystem.getPath(""); Path actual = empty.relativize(x); assertEquals(x, actual); } @Test public void preserveCase() throws IOException { FileSystem fileSystem = this.rule.getFileSystem(); Path originalPath = fileSystem.getPath("C:\\File0.txt"); Files.createFile(originalPath); assertThat(fileSystem.getPath("C:\\file0.txt"), exists()); boolean found = false; try (DirectoryStream<Path> stream = Files.newDirectoryStream(originalPath.getParent())) { for (Path each : stream) { if ("File0.txt".equals(each.getFileName().toString())) { found = true; break; } } } assertTrue(found); } @Test public void testPathMatherGlob() throws Exception { FileSystem fileSystem = this.rule.getFileSystem(); PathMatcher matcher = fileSystem.getPathMatcher("glob:*.{java,class}"); assertTrue(matcher.matches(fileSystem.getPath("Test.java"))); assertTrue(matcher.matches(fileSystem.getPath("Test.class"))); assertFalse(matcher.matches(fileSystem.getPath("Test.cpp"))); matcher = fileSystem.getPathMatcher("glob:*"); assertTrue(matcher.matches(fileSystem.getPath("Test.java"))); assertTrue(matcher.matches(fileSystem.getPath("Test.class"))); assertTrue(matcher.matches(fileSystem.getPath("Test.cpp"))); } @Test @Ignore public void relativePaths() { FileSystem fileSystem = this.rule.getFileSystem(); Path relative = fileSystem.getPath("C:folder\file.txt"); Path absolute = fileSystem.getPath("C:\folder\file.txt"); assertThat(relative, isRelative()); assertThat(absolute, isAbsolute()); } }