blob: 752dec025ae0c24a6bdd0badc1e9eff0a50bc7d1 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.util.io;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.win32.FileInfo;
import com.intellij.openapi.util.io.win32.IdeaWin32;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.TimeoutUtil;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.util.Arrays;
import static com.intellij.openapi.util.io.IoTestUtil.assertTimestampsEqual;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeTrue;
public class FileAttributesReadingTest {
private final byte[] myTestData = new byte[]{'t', 'e', 's', 't'};
private File myTempDirectory;
@BeforeClass
public static void checkMediator() throws Exception {
final String expectedName = SystemInfo.isWindows ? "IdeaWin32" : "JnaUnix";
assertEquals(expectedName, FileSystemUtil.getMediatorName());
}
@Before
public void setUp() throws Exception {
myTempDirectory = FileUtil.createTempDirectory(getClass().getSimpleName() + ".", ".tmp");
}
@After
public void tearDown() throws Exception {
if (myTempDirectory != null) {
FileUtil.delete(myTempDirectory);
}
}
@Test
public void missingFile() throws Exception {
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", false);
final FileAttributes attributes = FileSystemUtil.getAttributes(file);
assertNull(attributes);
final String target = FileSystemUtil.resolveSymLink(file);
assertNull(target);
}
@Test
public void regularFile() throws Exception {
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt");
FileUtil.writeToFile(file, myTestData);
assertFileAttributes(file);
final String target = FileSystemUtil.resolveSymLink(file);
assertEquals(file.getPath(), target);
}
@Test
public void directory() throws Exception {
final File file = FileUtil.createTempDirectory(myTempDirectory, "test.", ".tmp");
final FileAttributes attributes = getAttributes(file);
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
assertEquals(0, attributes.flags);
assertEquals(file.length(), attributes.length);
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
assertTrue(attributes.isWritable());
if (SystemInfo.isWindows) {
assertDirectoriesEqual(file);
}
final String target = FileSystemUtil.resolveSymLink(file);
assertEquals(file.getPath(), target);
}
@Test
public void root() throws Exception {
final File file = new File(SystemInfo.isWindows ? "C:\\" : "/");
final FileAttributes attributes = getAttributes(file);
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
if (SystemInfo.isWindows) {
assertDirectoriesEqual(file);
}
}
@Test
public void badNames() throws Exception {
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt");
FileUtil.writeToFile(file, myTestData);
assertFileAttributes(new File(file.getPath() + StringUtil.repeat(File.separator, 3)));
assertFileAttributes(new File(file.getPath().replace(File.separator, StringUtil.repeat(File.separator, 3))));
assertFileAttributes(new File(file.getPath().replace(File.separator, File.separator + "." + File.separator)));
assertFileAttributes(
new File(myTempDirectory, File.separator + ".." + File.separator + myTempDirectory.getName() + File.separator + file.getName()));
if (SystemInfo.isUnix) {
final File backSlashFile = FileUtil.createTempFile(myTempDirectory, "test\\", "\\txt");
FileUtil.writeToFile(backSlashFile, myTestData);
assertFileAttributes(backSlashFile);
}
}
@Test
public void special() throws Exception {
assumeTrue(SystemInfo.isUnix);
final File file = new File("/dev/null");
final FileAttributes attributes = getAttributes(file);
assertEquals(FileAttributes.Type.SPECIAL, attributes.type);
assertEquals(0, attributes.flags);
assertEquals(0, attributes.length);
assertTrue(attributes.isWritable());
final String target = FileSystemUtil.resolveSymLink(file);
assertEquals(file.getPath(), target);
}
@Test
public void linkToFile() throws Exception {
assumeTrue(SystemInfo.areSymLinksSupported);
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt");
FileUtil.writeToFile(file, myTestData);
assertTrue(file.setLastModified(file.lastModified() - 5000));
assertTrue(file.setWritable(false, false));
final File link = IoTestUtil.createSymLink(file.getPath(), new File(myTempDirectory, "link").getPath());
final FileAttributes attributes = getAttributes(link);
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(FileAttributes.SYM_LINK | FileAttributes.READ_ONLY, attributes.flags);
assertEquals(myTestData.length, attributes.length);
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
assertFalse(attributes.isWritable());
final String target = FileSystemUtil.resolveSymLink(link);
assertEquals(file.getPath(), target);
}
@Test
public void doubleLink() throws Exception {
assumeTrue(SystemInfo.areSymLinksSupported);
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt");
FileUtil.writeToFile(file, myTestData);
assertTrue(file.setLastModified(file.lastModified() - 5000));
assertTrue(file.setWritable(false, false));
final File link1 = IoTestUtil.createSymLink(file.getPath(), new File(myTempDirectory, "link1").getPath());
final File link2 = IoTestUtil.createSymLink(link1.getPath(), new File(myTempDirectory, "link2").getPath());
final FileAttributes attributes = getAttributes(link2);
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(FileAttributes.SYM_LINK | FileAttributes.READ_ONLY, attributes.flags);
assertEquals(myTestData.length, attributes.length);
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
assertFalse(attributes.isWritable());
final String target = FileSystemUtil.resolveSymLink(link2);
assertEquals(file.getPath(), target);
}
@Test
public void linkToDirectory() throws Exception {
assumeTrue(SystemInfo.areSymLinksSupported);
final File file = FileUtil.createTempDirectory(myTempDirectory, "test.", ".tmp");
if (SystemInfo.isUnix) assertTrue(file.setWritable(false, false));
assertTrue(file.setLastModified(file.lastModified() - 5000));
final File link = IoTestUtil.createSymLink(file.getPath(), new File(myTempDirectory, "link").getPath());
final FileAttributes attributes = getAttributes(link);
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
assertEquals(SystemInfo.isUnix ? FileAttributes.SYM_LINK | FileAttributes.READ_ONLY : FileAttributes.SYM_LINK, attributes.flags);
assertEquals(file.length(), attributes.length);
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
if (SystemInfo.isUnix) assertFalse(attributes.isWritable());
final String target = FileSystemUtil.resolveSymLink(link);
assertEquals(file.getPath(), target);
}
@Test
public void missingLink() throws Exception {
assumeTrue(SystemInfo.areSymLinksSupported);
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", false);
final File link = IoTestUtil.createSymLink(file.getPath(), new File(myTempDirectory, "link").getPath(), false);
final FileAttributes attributes = getAttributes(link);
assertNull(attributes.type);
assertEquals(FileAttributes.SYM_LINK, attributes.flags);
assertEquals(0, attributes.length);
final String target = FileSystemUtil.resolveSymLink(link);
assertNull(target, target);
}
@Test
public void selfLink() throws Exception {
assumeTrue(SystemInfo.areSymLinksSupported);
final File dir = FileUtil.createTempDirectory(myTempDirectory, "test.", ".dir");
final File link = IoTestUtil.createSymLink(dir.getPath(), new File(dir, "link").getPath());
final FileAttributes attributes = getAttributes(link);
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
assertEquals(FileAttributes.SYM_LINK, attributes.flags);
assertTimestampsEqual(dir.lastModified(), attributes.lastModified);
final String target = FileSystemUtil.resolveSymLink(link);
assertEquals(dir.getPath(), target);
}
@Test
public void junction() throws Exception {
assumeTrue(SystemInfo.isWindows);
final File target = FileUtil.createTempDirectory(myTempDirectory, "temp.", ".dir");
final File path = FileUtil.createTempFile(myTempDirectory, "junction.", ".dir", false);
final File junction = IoTestUtil.createJunction(target.getPath(), path.getAbsolutePath());
FileAttributes attributes = getAttributes(junction);
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
assertEquals(0, attributes.flags);
assertTrue(attributes.isWritable());
final String resolved1 = FileSystemUtil.resolveSymLink(junction);
assertEquals(SystemInfo.isWinVistaOrNewer ? target.getPath() : junction.getPath(), resolved1);
FileUtil.delete(target);
attributes = getAttributes(junction);
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
assertEquals(0, attributes.flags);
assertTrue(attributes.isWritable());
final String resolved2 = FileSystemUtil.resolveSymLink(junction);
assertEquals(SystemInfo.isWinVistaOrNewer ? null : junction.getPath(), resolved2);
}
@Test
public void hiddenDir() throws Exception {
assumeTrue(SystemInfo.isWindows);
File dir = IoTestUtil.createTestDir(myTempDirectory, "dir");
FileAttributes attributes = getAttributes(dir);
assertFalse(attributes.isHidden());
IoTestUtil.setHidden(dir.getPath(), true);
attributes = getAttributes(dir);
assertTrue(attributes.isHidden());
}
@Test
public void hiddenFile() throws Exception {
assumeTrue(SystemInfo.isWindows);
File file = IoTestUtil.createTestFile(myTempDirectory, "file");
FileAttributes attributes = getAttributes(file);
assertFalse(attributes.isHidden());
IoTestUtil.setHidden(file.getPath(), true);
attributes = getAttributes(file);
assertTrue(attributes.isHidden());
}
@Test
public void notSoHiddenRoot() throws Exception {
if (SystemInfo.isWindows) {
File absRoot = new File("C:\\");
FileAttributes absAttributes = getAttributes(absRoot);
assertFalse(absAttributes.isHidden());
File relRoot = new File("C:");
FileAttributes relAttributes = getAttributes(relRoot);
assertFalse(relAttributes.isHidden());
}
else {
File absRoot = new File("/");
FileAttributes absAttributes = getAttributes(absRoot);
assertFalse(absAttributes.isHidden());
}
}
@Test
public void wellHiddenFile() throws Exception {
assumeTrue(SystemInfo.isWindows);
final File file = new File("C:\\Documents and Settings\\desktop.ini");
assumeTrue(file.exists());
final FileAttributes attributes = getAttributes(file, false);
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(FileAttributes.HIDDEN, attributes.flags);
assertEquals(file.length(), attributes.length);
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
}
@Test
public void extraLongName() throws Exception {
String prefix = StringUtil.repeatSymbol('a', 128) + ".";
File dir = FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
myTempDirectory, prefix, ".dir"),
prefix, ".dir"),
prefix, ".dir"),
prefix, ".dir");
File file = FileUtil.createTempFile(dir, prefix, ".txt");
assertTrue(file.exists());
FileUtil.writeToFile(file, myTestData);
assertFileAttributes(file);
if (SystemInfo.isWindows) {
assertDirectoriesEqual(dir);
}
String target = FileSystemUtil.resolveSymLink(file);
assertEquals(file.getPath(), target);
if (SystemInfo.isWindows) {
String path = myTempDirectory.getPath();
int length = 250 - path.length();
for (int i = 0; i < length / 10; i++) {
path += "\\x_x_x_x_x";
}
File baseDir = new File(path);
assertTrue(baseDir.mkdirs());
assertTrue(getAttributes(baseDir).isDirectory());
for (int i = 1; i <= 100; i++) {
dir = new File(baseDir, StringUtil.repeat("x", i));
assertTrue(dir.mkdir());
assertTrue(getAttributes(dir).isDirectory());
file = new File(dir, "file.txt");
FileUtil.writeToFile(file, "test".getBytes("UTF-8"));
assertTrue(file.exists());
assertFileAttributes(file);
target = FileSystemUtil.resolveSymLink(file);
assertEquals(file.getPath(), target);
}
}
}
@Test
public void subst() throws Exception {
assumeTrue(SystemInfo.isWindows);
FileUtil.createTempFile(myTempDirectory, "test.", ".txt"); // just to populate a directory
final File substRoot = IoTestUtil.createSubst(myTempDirectory.getPath());
try {
final FileAttributes attributes = getAttributes(substRoot);
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
assertDirectoriesEqual(substRoot);
final File[] children = substRoot.listFiles();
assertNotNull(children);
assertEquals(1, children.length);
final File file = children[0];
final String target = FileSystemUtil.resolveSymLink(file);
assertEquals(file.getPath(), target);
}
finally {
IoTestUtil.deleteSubst(substRoot.getPath());
}
}
@Test
public void hardLink() throws Exception {
final File target = FileUtil.createTempFile(myTempDirectory, "test.", ".txt");
final File link = IoTestUtil.createHardLink(target.getPath(), myTempDirectory.getPath() + "/link");
FileAttributes attributes = getAttributes(link, SystemInfo.areSymLinksSupported); // ignore XP
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(target.length(), attributes.length);
assertTimestampsEqual(target.lastModified(), attributes.lastModified);
FileUtil.writeToFile(target, myTestData);
assertTrue(target.setLastModified(attributes.lastModified - 5000));
assertTrue(target.length() > 0);
assertTimestampsEqual(attributes.lastModified - 5000, target.lastModified());
attributes = getAttributes(link, SystemInfo.areSymLinksSupported); // ignore XP
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(target.length(), attributes.length);
assertTimestampsEqual(target.lastModified(), attributes.lastModified);
final String resolved = FileSystemUtil.resolveSymLink(link);
assertEquals(link.getPath(), resolved);
}
@Test
public void stamps() throws Exception {
FileAttributes attributes = FileSystemUtil.getAttributes(myTempDirectory);
assumeTrue(attributes != null && attributes.lastModified > (attributes.lastModified/1000)*1000);
long t1 = System.currentTimeMillis();
TimeoutUtil.sleep(10);
File file = IoTestUtil.createTestFile(myTempDirectory, "test.txt");
TimeoutUtil.sleep(10);
long t2 = System.currentTimeMillis();
attributes = getAttributes(file);
assertTrue(attributes.lastModified + " not in " + t1 + ".." + t2, t1 <= attributes.lastModified && attributes.lastModified <= t2);
t1 = System.currentTimeMillis();
TimeoutUtil.sleep(10);
FileUtil.writeToFile(file, myTestData);
TimeoutUtil.sleep(10);
t2 = System.currentTimeMillis();
attributes = getAttributes(file);
assertTrue(attributes.lastModified + " not in " + t1 + ".." + t2, t1 <= attributes.lastModified && attributes.lastModified <= t2);
ProcessBuilder cmd = SystemInfo.isWindows ? new ProcessBuilder("attrib", "-A", file.getPath()) : new ProcessBuilder("chmod", "644", file.getPath());
assertEquals(0, cmd.start().waitFor());
attributes = getAttributes(file);
assertTrue(attributes.lastModified + " not in " + t1 + ".." + t2, t1 <= attributes.lastModified && attributes.lastModified <= t2);
}
@Test
public void notOwned() throws Exception {
assumeTrue(SystemInfo.isUnix);
File userHome = new File(SystemProperties.getUserHome());
FileAttributes homeAttributes = getAttributes(userHome);
assertTrue(homeAttributes.isDirectory());
assertTrue(homeAttributes.isWritable());
FileAttributes parentAttributes = getAttributes(userHome.getParentFile());
assertTrue(parentAttributes.isDirectory());
assertFalse(parentAttributes.isWritable());
}
@NotNull
private static FileAttributes getAttributes(@NotNull final File file) {
return getAttributes(file, true);
}
@NotNull
private static FileAttributes getAttributes(@NotNull final File file, final boolean checkList) {
final FileAttributes attributes = FileSystemUtil.getAttributes(file);
assertNotNull(attributes);
if (SystemInfo.isWindows && checkList) {
final String parent = file.getParent();
if (parent != null) {
final FileInfo[] infos = IdeaWin32.getInstance().listChildren(parent);
assertNotNull(infos);
for (FileInfo info : infos) {
if (file.getName().equals(info.getName())) {
assertEquals(attributes, info.toFileAttributes());
return attributes;
}
}
fail(file + " not listed");
}
}
return attributes;
}
private static void assertFileAttributes(@NotNull final File file) {
final FileAttributes attributes = getAttributes(file);
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(0, attributes.flags);
assertEquals(file.length(), attributes.length);
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
assertTrue(attributes.isWritable());
}
private static void assertDirectoriesEqual(@NotNull final File dir) {
final String[] list1 = dir.list();
assertNotNull(list1);
final FileInfo[] list2 = IdeaWin32.getInstance().listChildren(dir.getPath());
assertNotNull(list2);
if (list1.length + 2 != list2.length) {
assertEquals(Arrays.toString(list1), Arrays.toString(list2));
}
}
}