diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexRestoreTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexRestoreTest.java new file mode 100644 index 000000000000..348eaed3aa81 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexRestoreTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2016 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.roots.impl; + +import com.intellij.openapi.roots.ContentIterator; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PsiTestUtil; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import static com.intellij.testFramework.VfsTestUtil.getEvents; +import static com.intellij.testFramework.VfsTestUtil.print; +import static java.util.Collections.singletonList; + +@PlatformTestCase.WrapInCommand +public class DirectoryIndexRestoreTest extends IdeaTestCase { + private VirtualFile myTempVFile; + private String myTestDirPath; + private ProjectFileIndex myFileIndex; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + LocalFileSystem fs = LocalFileSystem.getInstance(); + File temp = createTempDirectory(); + myTempVFile = fs.findFileByIoFile(temp); + assertNotNull(myTempVFile); + File root = new File(temp, "top/d1/d2/root"); + assertTrue(root.mkdirs()); + VirtualFile rootVFile = fs.findFileByIoFile(root); + assertNotNull(rootVFile); + + VirtualFile moduleDir = createChildDirectory(rootVFile, "module"); + VirtualFile srcDir = createChildDirectory(moduleDir, "src"); + VirtualFile testDir = createChildDirectory(srcDir, "pkg"); + ModuleRootModificationUtil.setModuleSdk(myModule, null); + PsiTestUtil.addContentRoot(myModule, moduleDir); + PsiTestUtil.addSourceRoot(myModule, srcDir); + + myTestDirPath = testDir.getPath(); + myFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); + + // to not interfere with previous test firing vfs events + VirtualFileManager.getInstance().syncRefresh(); + } + + public void testDeepDeleteAndRecreate() throws IOException { + AtomicInteger counter = new AtomicInteger(0); + ContentIterator iterator = (file) -> { + boolean found = file.getPath().equals(myTestDirPath); + if (found) counter.incrementAndGet(); + return !found; + }; + File topFile = new File(myTempVFile.getPath(), "top"), bakFile = new File(myTempVFile.getPath(), "top.bak"); + String topPath = myTempVFile.getPath() + "/top"; + + myFileIndex.iterateContent(iterator); + assertEquals(1, counter.get()); + + FileUtil.rename(topFile, bakFile); + List events1 = print(getEvents(() -> myTempVFile.refresh(false, true))); + assertEquals(singletonList("D : " + topPath), events1); + myFileIndex.iterateContent(iterator); + assertEquals(1, counter.get()); + + FileUtil.rename(bakFile, topFile); + List events2 = print(getEvents(() -> myTempVFile.refresh(false, true))); + assertEquals(singletonList("C : " + topPath), events2); + myFileIndex.iterateContent(iterator); + assertEquals(2, counter.get()); + } +} \ No newline at end of file diff --git a/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java index 31a5a69fa30d..0d7de9d4753e 100644 --- a/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -25,13 +25,20 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.*; import com.intellij.util.PathUtil; +import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.text.StringTokenizer; import org.jetbrains.annotations.NotNull; import org.junit.Assert; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; /** * @author nik @@ -39,8 +46,7 @@ import java.io.IOException; public class VfsTestUtil { public static final Key TEST_DATA_FILE_PATH = Key.create("TEST_DATA_FILE_PATH"); - private VfsTestUtil() { - } + private VfsTestUtil() { } public static VirtualFile createFile(final VirtualFile root, final String relativePath) { return createFile(root, relativePath, ""); @@ -150,4 +156,39 @@ public class VfsTestUtil { "real path " + realSuffixPath); } } -} + + @NotNull + public static List getEvents(@NotNull Runnable action) { + List allEvents = new ArrayList<>(); + + MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); + connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { + @Override + public void after(@NotNull List events) { + allEvents.addAll(events); + } + }); + try { + action.run(); + } + finally { + connection.disconnect(); + } + + return allEvents; + } + + @NotNull + public static List print(@NotNull List events) { + return events.stream().map(VfsTestUtil::print).collect(Collectors.toList()); + } + + private static String print(VFileEvent e) { + char type = '?'; + if (e instanceof VFileCreateEvent) type = 'C'; + else if (e instanceof VFileDeleteEvent) type = 'D'; + else if (e instanceof VFileContentChangeEvent) type = 'U'; + else if (e instanceof VFilePropertyChangeEvent) type = 'P'; + return type + " : " + e.getPath(); + } +} \ No newline at end of file