[platform] fixes missed notifications on flat file watch root changes on macOS (IDEA-159022)

This commit is contained in:
Roman Shevchenko
2016-08-12 17:22:27 +03:00
parent ed3763c9cf
commit 01fbf78556
3 changed files with 125 additions and 9 deletions
@@ -141,6 +141,13 @@ class CanonicalPathMap {
continue ext;
}
}
else {
String rootParent = new File(root).getParent();
if (rootParent != null && FileUtil.namesEqual(path, rootParent)) {
changedPaths.add(root);
continue ext;
}
}
}
for (String root : myRecursiveWatchRoots) {
@@ -149,8 +156,8 @@ class CanonicalPathMap {
continue ext;
}
if (!isExact) {
String parentPath = new File(root).getParent();
if (parentPath != null && FileUtil.namesEqual(path, parentPath)) {
String rootParent = new File(root).getParent();
if (rootParent != null && FileUtil.namesEqual(path, rootParent)) {
changedPaths.add(root);
continue ext;
}
@@ -17,31 +17,130 @@ package com.intellij.openapi.vfs.impl.local;
import com.intellij.openapi.util.io.IoTestUtil;
import com.intellij.testFramework.rules.TempDirectory;
import com.intellij.util.PathUtil;
import org.junit.Rule;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import static com.intellij.openapi.util.Pair.pair;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
public class CanonicalPathMapTest {
@Rule public TempDirectory myTempDir = new TempDirectory();
@Test
public void testRemappedSymLinkReportsOriginalWatchedPath() throws Exception {
public void flatRootReportedExactlyViaParent() {
String root = "/parent/root";
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), true);
assertThat(paths).isEmpty();
}
@Test
public void flatRootReportedExactlyViaItself() {
String root = "/parent/root.txt";
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
Collection<String> paths = map.getWatchedPaths(root, true);
assertThat(paths).containsExactly(root);
}
@Test
public void flatRootReportedExactlyViaChild() {
String root = "/parent/root", child = root + "/child.txt";
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
Collection<String> paths = map.getWatchedPaths(child, true);
assertThat(paths).containsExactly(child);
}
@Test
public void flatRootReportedInexactlyViaParent() {
String root = "/parent/root.txt";
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), false);
assertThat(paths).containsExactly(root);
}
@Test
public void flatRootReportedInexactlyViaItself() {
String root = "/parent/root";
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
Collection<String> paths = map.getWatchedPaths(root, false);
assertThat(paths).containsExactly(root);
}
@Test
public void flatRootReportedInexactlyViaChild() {
String root = "/parent/root", child = root + "/child_dir";
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
Collection<String> paths = map.getWatchedPaths(child, false);
assertThat(paths).isEmpty();
}
@Test
public void recursiveRootReportedExactlyViaParent() {
String root = "/parent/root";
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), true);
assertThat(paths).isEmpty();
}
@Test
public void recursiveRootReportedExactlyViaItself() {
String root = "/parent/root";
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
Collection<String> paths = map.getWatchedPaths(root, true);
assertThat(paths).containsExactly(root);
}
@Test
public void recursiveRootReportedExactlyViaChild() {
String root = "/parent/root", child = root + "/child.txt";
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
Collection<String> paths = map.getWatchedPaths(child, true);
assertThat(paths).containsExactly(child);
}
@Test
public void recursiveRootReportedInexactlyViaParent() {
String root = "/parent/root";
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), false);
assertThat(paths).containsExactly(root);
}
@Test
public void recursiveRootReportedInexactlyViaItself() {
String root = "/parent/root";
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
Collection<String> paths = map.getWatchedPaths(root, false);
assertThat(paths).containsExactly(root);
}
@Test
public void recursiveRootReportedInexactlyViaChild() {
String root = "/parent/root", child = root + "/child";
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
Collection<String> paths = map.getWatchedPaths(child, false);
assertThat(paths).containsExactly(child);
}
@Test
public void remappedSymLinkReportsOriginalWatchedPath() throws IOException, InterruptedException {
// Tests the situation where the watch root is a symlink AND REMAPPED by the native file watcher.
File realDir = myTempDir.newFolder("real");
File symLink = IoTestUtil.createSymLink(realDir.getPath(), myTempDir.getRoot() + "/link");
File mappedDir = new File(myTempDir.getRoot(), "mapped");
// Initial symlink map: /?/root/link_dir -> /?/root/real
CanonicalPathMap pathMap = new CanonicalPathMap(Collections.singletonList(symLink.getPath()), Collections.emptyList());
CanonicalPathMap pathMap = new CanonicalPathMap(singletonList(symLink.getPath()), emptyList());
// REMAP from native file watcher: /?/root/mapped -> /?/root/real
pathMap.addMapping(Collections.singletonList(pair(mappedDir.getPath(), realDir.getPath())));
pathMap.addMapping(singletonList(pair(mappedDir.getPath(), realDir.getPath())));
Collection<String> watchedPaths = pathMap.getWatchedPaths(new File(mappedDir, "file.txt").getPath(), true);
assertThat(watchedPaths).containsExactly(new File(symLink, "file.txt").getPath());
@@ -81,6 +81,8 @@ class FileWatcherTest : BareTestFixtureTestCase() {
runInEdtAndWait { VirtualFileManager.getInstance().syncRefresh() }
alarm = Alarm(Alarm.ThreadToUse.POOLED_THREAD, testRootDisposable)
watcher = (fs as LocalFileSystemImpl).fileWatcher
assertFalse(watcher.isOperational)
watcher.startup { reset ->
@@ -90,8 +92,6 @@ class FileWatcherTest : BareTestFixtureTestCase() {
}
wait { !watcher.isOperational }
alarm = Alarm(Alarm.ThreadToUse.POOLED_THREAD, testRootDisposable)
LOG.debug("================== setting up " + getTestName(false) + " ==================")
}
@@ -122,7 +122,17 @@ class FileWatcherTest : BareTestFixtureTestCase() {
val file = tempDir.newFile("test.txt")
refresh(file)
watch(file)
watch(file, false)
assertEvents({ file.writeText("new content") }, mapOf(file to 'U'))
assertEvents({ file.delete() }, mapOf(file to 'D'))
assertEvents({ file.writeText("re-creation") }, mapOf(file to 'C'))
}
@Test fun testFileRootRecursive() {
val file = tempDir.newFile("test.txt")
refresh(file)
watch(file, true)
assertEvents({ file.writeText("new content") }, mapOf(file to 'U'))
assertEvents({ file.delete() }, mapOf(file to 'D'))
assertEvents({ file.writeText("re-creation") }, mapOf(file to 'C'))