package com.github.marschall.memoryfilesystem;
import static com.github.marschall.memoryfilesystem.FileExistsMatcher.exists;
import static com.github.marschall.memoryfilesystem.IsSameFileMatcher.isSameFile;
import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.DosFileAttributes;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class WindowsFileSystemComptiblityTest {
@Rule
public final WindowsFileSystemRule rule = new WindowsFileSystemRule();
private FileSystem fileSystem;
private final boolean useDefault;
public WindowsFileSystemComptiblityTest(boolean useDefault) {
this.useDefault = useDefault;
}
FileSystem getFileSystem() {
if (this.fileSystem == null) {
if (this.useDefault) {
this.fileSystem = FileSystems.getDefault();
} else {
this.fileSystem = this.rule.getFileSystem();
}
}
return this.fileSystem;
}
@Parameters(name = "navite: {0}")
public static List<Object[]> fileSystems() throws IOException {
FileSystem defaultFileSystem = FileSystems.getDefault();
Set<String> supportedFileAttributeViews = defaultFileSystem.supportedFileAttributeViews();
// a DOS view is faked into the unix file system
boolean isDos = supportedFileAttributeViews.contains("dos") && !supportedFileAttributeViews.contains("unix");
if (isDos) {
return Arrays.asList(new Object[]{true},
new Object[]{false});
} else {
return Collections.singletonList(new Object[]{false});
}
}
@Test
public void isHidden() throws IOException {
Path hidden = this.getFileSystem().getPath("hidden");
Files.createFile(hidden);
try {
Files.setAttribute(hidden, "dos:hidden", true);
assertTrue(Files.isHidden(hidden));
} finally {
Files.delete(hidden);
}
}
@Test
public void isNotHidden() throws IOException {
Path hidden = this.getFileSystem().getPath(".not_hidden");
Files.createFile(hidden);
try {
Files.setAttribute(hidden, "dos:hidden", false);
assertFalse(Files.isHidden(hidden));
} finally {
Files.delete(hidden);
}
}
@Test
public void rootAttributes() throws IOException {
FileSystem fileSystem = this.getFileSystem();
Path root = fileSystem.getPath("C:\\");
BasicFileAttributes attributes = Files.readAttributes(root, BasicFileAttributes.class);
assertTrue(attributes.isDirectory());
assertFalse(attributes.isRegularFile());
DosFileAttributes dosFileAttributes = Files.readAttributes(root, DosFileAttributes.class);
assertFalse(dosFileAttributes.isArchive());
assertTrue(dosFileAttributes.isHidden());
assertTrue(dosFileAttributes.isSystem());
assertFalse(dosFileAttributes.isReadOnly());
}
@Test
@Ignore("not ready")
public void forbiddenFileNames() {
FileSystem fileSystem = this.getFileSystem();
Path root = fileSystem.getPath("C:\\");
List<String> forbidden = asList("CON", "PRN", "AUX", "CLOCK$", "NULL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9");
for (String each : forbidden) {
Path forbiddenPath = root.resolve(each);
try {
Files.createFile(forbiddenPath);
fail(forbiddenPath + " should be forbidden");
} catch (IOException e) {
// should reach here
}
forbiddenPath = root.resolve(each.toLowerCase(Locale.US));
try {
Files.createFile(forbiddenPath);
fail(forbiddenPath + " should be forbidden");
} catch (IOException e) {
// should reach here
}
}
}
@Test
public void caseInsensitiveCasePreserving() throws IOException {
FileSystem fileSystem = this.getFileSystem();
Path testFile = fileSystem.getPath("tesT");
try {
Files.createFile(testFile);
assertEquals("tesT", testFile.toRealPath().getFileName().toString());
Path testFile2 = fileSystem.getPath("Test");
assertThat(testFile2, exists());
assertEquals("tesT", testFile2.toRealPath().getFileName().toString());
} finally {
Files.delete(testFile);
}
}
@Test
public void attributeCapitalization() throws IOException {
FileSystem fileSystem = this.getFileSystem();
Path root = fileSystem.getPath("C:\\");
Map<String, Object> attributes = Files.readAttributes(root, "dos:*");
Set<String> keys = attributes.keySet();
assertThat(keys, hasItem("hidden"));
assertThat(keys, hasItem("archive"));
assertThat(keys, hasItem("system"));
assertThat(keys, not(hasItem("isHidden")));
assertThat(keys, not(hasItem("isArchive")));
assertThat(keys, not(hasItem("isSystem")));
}
@Test
@Ignore
public void windowsNormalization() throws IOException {
FileSystem fileSystem = this.getFileSystem();
String aUmlaut = "\u00C4";
Path aPath = fileSystem.getPath(aUmlaut);
String normalized = Normalizer.normalize(aUmlaut, Form.NFD);
Path nPath = fileSystem.getPath(normalized);
Path createdFile = null;
try {
createdFile = Files.createFile(nPath);
assertEquals(2, createdFile.getFileName().toString().length());
assertEquals(2, createdFile.toAbsolutePath().getFileName().toString().length());
// REVIEW ??
assertEquals(2, createdFile.toRealPath().getFileName().toString().length());
assertThat(aPath, not(exists()));
assertThat(nPath, exists());
//assertTrue(Files.isSameFile(aPath, nPath));
//assertTrue(Files.isSameFile(nPath, aPath));
assertThat(aPath, not(equalTo(nPath)));
} finally {
if (createdFile != null) {
Files.delete(createdFile);
}
}
}
@Test
@Ignore
public void windowsNoNormalization() throws IOException {
/*
* Verifies that Windows does no Unicode normalization and that we can have
* both a NFC and NFD file.
*/
FileSystem fileSystem = this.getFileSystem();
String aUmlaut = "\u00C4";
Path nfcPath = fileSystem.getPath(aUmlaut);
String normalized = Normalizer.normalize(aUmlaut, Form.NFD);
Path nfdPath = fileSystem.getPath(normalized);
Path nfcFile = null;
Path nfdFile = null;
try {
nfcFile = Files.createFile(nfcPath);
assertEquals(1, nfcFile.getFileName().toString().length());
assertEquals(1, nfcFile.toAbsolutePath().getFileName().toString().length());
assertEquals(1, nfcFile.toRealPath().getFileName().toString().length());
assertThat(nfcPath, exists());
assertThat(nfdPath, not(exists()));
nfdFile = Files.createFile(nfdPath);
assertEquals(2, nfdFile.getFileName().toString().length());
assertEquals(2, nfdFile.toAbsolutePath().getFileName().toString().length());
assertEquals(2, nfdFile.toRealPath().getFileName().toString().length());
assertThat(nfcPath, not(equalTo(nfdPath)));
assertThat(nfcPath, not(isSameFile(nfdPath)));
assertThat(nfdPath, not(isSameFile(nfcPath)));
} finally {
if (nfcFile != null) {
Files.delete(nfcFile);
}
if (nfdFile != null) {
Files.delete(nfdFile);
}
}
}
}