| /* |
| * 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.vfs.impl; |
| |
| import com.intellij.concurrency.Job; |
| import com.intellij.concurrency.JobLauncher; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.application.ex.PathManagerEx; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.openapi.util.Computable; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.vfs.*; |
| import com.intellij.openapi.vfs.ex.temp.TempFileSystem; |
| import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent; |
| import com.intellij.openapi.vfs.newvfs.events.VFileEvent; |
| import com.intellij.openapi.vfs.pointers.VirtualFilePointer; |
| import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; |
| import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; |
| import com.intellij.testFramework.PlatformLangTestCase; |
| import com.intellij.testFramework.PlatformTestUtil; |
| import com.intellij.testFramework.Timings; |
| import com.intellij.util.Consumer; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.util.ThrowableRunnable; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.Future; |
| |
| /** |
| * @author dsl |
| */ |
| public class VirtualFilePointerTest extends PlatformLangTestCase { |
| private VirtualFilePointerManagerImpl myVirtualFilePointerManager; |
| private int numberOfPointersBefore; |
| private final Disposable disposable = Disposer.newDisposable(); |
| private int numberOfListenersBefore; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| myVirtualFilePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); |
| numberOfPointersBefore = myVirtualFilePointerManager.numberOfPointers(); |
| numberOfListenersBefore = myVirtualFilePointerManager.numberOfListeners(); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| Disposer.dispose(disposable); |
| try { |
| assertEquals(numberOfPointersBefore, myVirtualFilePointerManager.numberOfPointers()); // check there is no leak |
| assertEquals(numberOfListenersBefore, myVirtualFilePointerManager.numberOfListeners()); // check there is no leak |
| } |
| finally { |
| super.tearDown(); |
| } |
| } |
| |
| @Override |
| protected boolean isRunInWriteAction() { |
| return false; |
| } |
| |
| private static class LoggingListener implements VirtualFilePointerListener { |
| private final ArrayList<String> myLog = new ArrayList<String>(); |
| |
| @Override |
| public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { |
| verifyPointersInCorrectState(pointers); |
| myLog.add(buildMessage("before", pointers)); |
| } |
| |
| private static String buildMessage(@NonNls final String startMsg, VirtualFilePointer[] pointers) { |
| StringBuilder buffer = new StringBuilder(startMsg); |
| buffer.append(":"); |
| for (int i = 0; i < pointers.length; i++) { |
| VirtualFilePointer pointer = pointers[i]; |
| final String s = Boolean.toString(pointer.isValid()); |
| if (i > 0) buffer.append(":"); |
| buffer.append(s); |
| } |
| return buffer.toString(); |
| } |
| |
| @Override |
| public void validityChanged(@NotNull VirtualFilePointer[] pointers) { |
| verifyPointersInCorrectState(pointers); |
| myLog.add(buildMessage("after", pointers)); |
| } |
| |
| public ArrayList<String> getLog() { |
| return myLog; |
| } |
| } |
| |
| public void testDelete() throws Exception { |
| File tempDirectory = createTempDirectory(); |
| final File fileToDelete = new File(tempDirectory, "toDelete.txt"); |
| fileToDelete.createNewFile(); |
| final LoggingListener fileToDeleteListener = new LoggingListener(); |
| final VirtualFilePointer fileToDeletePointer = createPointerByFile(fileToDelete, fileToDeleteListener); |
| assertTrue(fileToDeletePointer.isValid()); |
| delete(getVirtualFile(fileToDelete)); |
| assertFalse(fileToDeletePointer.isValid()); |
| assertEquals("[before:true, after:false]", fileToDeleteListener.getLog().toString()); |
| } |
| |
| public void testCreate() throws Exception { |
| final File tempDirectory = createTempDirectory(); |
| final File fileToCreate = new File(tempDirectory, "toCreate.txt"); |
| final LoggingListener fileToCreateListener = new LoggingListener(); |
| final VirtualFilePointer fileToCreatePointer = createPointerByFile(fileToCreate, fileToCreateListener); |
| assertFalse(fileToCreatePointer.isValid()); |
| fileToCreate.createNewFile(); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| VirtualFileManager.getInstance().syncRefresh(); |
| final VirtualFile virtualFile = getVirtualFile(tempDirectory); |
| virtualFile.refresh(false, true); |
| } |
| }); |
| assertTrue(fileToCreatePointer.isValid()); |
| assertEquals("[before:false, after:true]", fileToCreateListener.getLog().toString()); |
| try { |
| String expectedUrl = VirtualFileManager |
| .constructUrl(LocalFileSystem.PROTOCOL, fileToCreate.getCanonicalPath().replace(File.separatorChar, '/')); |
| assertEquals(expectedUrl.toUpperCase(), fileToCreatePointer.getUrl().toUpperCase()); |
| } |
| catch (IOException e) { |
| fail(); |
| } |
| } |
| |
| public void testPathNormalization() throws Exception { |
| checkFileName("///", ""); |
| } |
| public void testPathNormalization2() throws Exception { |
| checkFileName("\\\\", "/"); |
| } |
| public void testPathNormalization3() throws Exception { |
| checkFileName("//", "/////"); |
| } |
| |
| private void checkFileName(String prefix, String suffix) throws IOException { |
| final File tempDirectory = createTempDirectory(); |
| |
| final VirtualFile temp = getVirtualFile(tempDirectory); |
| String name = "toCreate.txt"; |
| final VirtualFilePointer fileToCreatePointer = createPointerByFile(new File(tempDirectory.getPath() + prefix + name +suffix), null); |
| assertFalse(fileToCreatePointer.isValid()); |
| assertNull(fileToCreatePointer.getFile()); |
| |
| VirtualFile child = createChildData(temp, name); |
| |
| assertTrue(fileToCreatePointer.isValid()); |
| assertEquals(child, fileToCreatePointer.getFile()); |
| |
| delete(child); |
| assertFalse(fileToCreatePointer.isValid()); |
| assertNull(fileToCreatePointer.getFile()); |
| } |
| |
| public void testMovePointedFile() throws Exception { |
| File tempDirectory = createTempDirectory(); |
| final File moveTarget = new File(tempDirectory, "moveTarget"); |
| moveTarget.mkdir(); |
| final File fileToMove = new File(tempDirectory, "toMove.txt"); |
| fileToMove.createNewFile(); |
| |
| final LoggingListener fileToMoveListener = new LoggingListener(); |
| final VirtualFilePointer fileToMovePointer = createPointerByFile(fileToMove, fileToMoveListener); |
| assertTrue(fileToMovePointer.isValid()); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| final VirtualFile virtualFile = getVirtualFile(fileToMove); |
| assertTrue(virtualFile.isValid()); |
| final VirtualFile target = getVirtualFile(moveTarget); |
| assertTrue(target.isValid()); |
| try { |
| virtualFile.move(null, target); |
| } |
| catch (IOException e) { |
| fail(); |
| } |
| } |
| }); |
| assertTrue(fileToMovePointer.isValid()); |
| assertEquals("[]", fileToMoveListener.getLog().toString()); |
| } |
| |
| public void testMoveFileUnderExistingPointer() throws Exception { |
| File tempDirectory = createTempDirectory(); |
| final File moveTarget = new File(tempDirectory, "moveTarget"); |
| moveTarget.mkdir(); |
| final File fileToMove = new File(tempDirectory, "toMove.txt"); |
| fileToMove.createNewFile(); |
| |
| final LoggingListener listener = new LoggingListener(); |
| final VirtualFilePointer fileToMoveTargetPointer = createPointerByFile(new File(moveTarget, fileToMove.getName()), listener); |
| assertFalse(fileToMoveTargetPointer.isValid()); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| final VirtualFile virtualFile = getVirtualFile(fileToMove); |
| assertTrue(virtualFile.isValid()); |
| final VirtualFile target = getVirtualFile(moveTarget); |
| assertTrue(target.isValid()); |
| try { |
| virtualFile.move(null, target); |
| } |
| catch (IOException e) { |
| fail(); |
| } |
| } |
| }); |
| assertTrue(fileToMoveTargetPointer.isValid()); |
| assertEquals("[before:false, after:true]", listener.getLog().toString()); |
| } |
| |
| public void testMovePointedFileUnderAnotherPointer() throws Exception { |
| File tempDirectory = createTempDirectory(); |
| final File moveTarget = new File(tempDirectory, "moveTarget"); |
| moveTarget.mkdir(); |
| final File fileToMove = new File(tempDirectory, "toMove.txt"); |
| fileToMove.createNewFile(); |
| |
| final LoggingListener listener = new LoggingListener(); |
| final LoggingListener targetListener = new LoggingListener(); |
| |
| final VirtualFilePointer fileToMovePointer = createPointerByFile(fileToMove, listener); |
| final VirtualFilePointer fileToMoveTargetPointer = createPointerByFile(new File(moveTarget, fileToMove.getName()), targetListener); |
| |
| assertFalse(fileToMoveTargetPointer.isValid()); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| final VirtualFile virtualFile = getVirtualFile(fileToMove); |
| assertTrue(virtualFile.isValid()); |
| final VirtualFile target = getVirtualFile(moveTarget); |
| assertTrue(target.isValid()); |
| try { |
| virtualFile.move(null, target); |
| } |
| catch (IOException e) { |
| fail(); |
| } |
| } |
| }); |
| assertTrue(fileToMovePointer.isValid()); |
| assertTrue(fileToMoveTargetPointer.isValid()); |
| assertEquals("[]", listener.getLog().toString()); |
| assertEquals("[before:false, after:true]", targetListener.getLog().toString()); |
| } |
| |
| public void testRenamingPointedFile() throws IOException { |
| final File tempDir = createTempDirectory(); |
| final File file = new File(tempDir, "f1"); |
| assertTrue(file.createNewFile()); |
| |
| final LoggingListener listener = new LoggingListener(); |
| VirtualFilePointer pointer = createPointerByFile(file, listener); |
| assertTrue(pointer.isValid()); |
| rename(getVirtualFile(file), "f2"); |
| assertTrue(pointer.isValid()); |
| assertEquals("[]", listener.getLog().toString()); |
| } |
| |
| public void testRenamingFileUnderTheExistingPointer() throws IOException { |
| final File tempDir = createTempDirectory(); |
| final File file = new File(tempDir, "f1"); |
| assertTrue(file.createNewFile()); |
| |
| final LoggingListener listener = new LoggingListener(); |
| VirtualFilePointer pointer = createPointerByFile(new File(file.getParent(), "f2"), listener); |
| assertFalse(pointer.isValid()); |
| rename(getVirtualFile(file), "f2"); |
| assertTrue(pointer.isValid()); |
| assertEquals("[before:false, after:true]", listener.getLog().toString()); |
| } |
| |
| public void testTwoPointersBecomeOneAfterFileRenamedUnderTheOtherName() throws IOException { |
| final File tempDir = createTempDirectory(); |
| final File f1 = new File(tempDir, "f1"); |
| boolean created = f1.createNewFile(); |
| assertTrue(created); |
| |
| final String url1 = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, f1.getCanonicalPath().replace(File.separatorChar, '/')); |
| final VirtualFile vFile1 = refreshAndFind(url1); |
| |
| final LoggingListener listener1 = new LoggingListener(); |
| VirtualFilePointer pointer1 = myVirtualFilePointerManager.create(url1, disposable, listener1); |
| assertTrue(pointer1.isValid()); |
| String url2 = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, tempDir.getCanonicalPath().replace(File.separatorChar, '/')+"/f2"); |
| final LoggingListener listener2 = new LoggingListener(); |
| VirtualFilePointer pointer2 = myVirtualFilePointerManager.create(url2, disposable, listener2); |
| assertFalse(pointer2.isValid()); |
| |
| rename(vFile1, "f2"); |
| |
| assertTrue(pointer1.isValid()); |
| assertTrue(pointer2.isValid()); |
| |
| assertEquals("[]", listener1.getLog().toString()); |
| assertEquals("[before:false, after:true]", listener2.getLog().toString()); |
| } |
| |
| public void testCreate1() throws Exception { |
| final File tempDirectory = createTempDirectory(); |
| final File fileToCreate = new File(tempDirectory, "toCreate1.txt"); |
| final LoggingListener fileToCreateListener = new LoggingListener(); |
| final VirtualFilePointer fileToCreatePointer = createPointerByFile(fileToCreate, fileToCreateListener); |
| assertFalse(fileToCreatePointer.isValid()); |
| fileToCreate.createNewFile(); |
| final Runnable postRunnable = new Runnable() { |
| @Override |
| public void run() { |
| assertTrue(fileToCreatePointer.isValid()); |
| assertEquals("[before:false, after:true]", fileToCreateListener.getLog().toString()); |
| try { |
| String expectedUrl = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, fileToCreate.getCanonicalPath().replace(File.separatorChar, '/')); |
| assertEquals(expectedUrl.toUpperCase(), fileToCreatePointer.getUrl().toUpperCase()); |
| } catch (IOException e) { |
| fail(); |
| } |
| } |
| }; |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| VirtualFileManager.getInstance().syncRefresh(); |
| final VirtualFile virtualFile = getVirtualFile(tempDirectory); |
| virtualFile.refresh(false, true); |
| } |
| }); |
| postRunnable.run(); |
| } |
| |
| public void testMultipleNotifications() throws Exception { |
| final File tempDir = createTempDirectory(); |
| final File file_f1 = new File(tempDir, "f1"); |
| final File file_f2 = new File(tempDir, "f2"); |
| final LoggingListener listener = new LoggingListener(); |
| final VirtualFilePointer pointer_f1 = createPointerByFile(file_f1, listener); |
| final VirtualFilePointer pointer_f2 = createPointerByFile(file_f2, listener); |
| assertFalse(pointer_f1.isValid()); |
| assertFalse(pointer_f2.isValid()); |
| file_f1.createNewFile(); |
| file_f2.createNewFile(); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| LocalFileSystem.getInstance().refresh(false); |
| } |
| }); |
| assertEquals("[before:false:false, after:true:true]", listener.getLog().toString()); |
| } |
| |
| public void testJars() throws Exception { |
| final File tempDir = createTempDirectory(); |
| final File jarParent = new File(tempDir, "jarParent"); |
| jarParent.mkdir(); |
| final File jar = new File(jarParent, "x.jar"); |
| final File originalJar = new File(PathManagerEx.getTestDataPath() + "/psi/generics22/collect-2.2.jar"); |
| FileUtil.copy(originalJar, jar); |
| |
| LocalFileSystem.getInstance().refreshAndFindFileByIoFile(jar); // Make sure we receive events when jar changes |
| |
| final VirtualFilePointer[] pointersToWatch = new VirtualFilePointer[2]; |
| final VirtualFilePointerListener listener = new VirtualFilePointerListener() { |
| @Override |
| public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { |
| verifyPointersInCorrectState(pointersToWatch); |
| } |
| |
| @Override |
| public void validityChanged(@NotNull VirtualFilePointer[] pointers) { |
| verifyPointersInCorrectState(pointersToWatch); |
| } |
| }; |
| final VirtualFilePointer jarParentPointer = createPointerByFile(jarParent, listener); |
| final String pathInJar = jar.getPath().replace(File.separatorChar, '/') + JarFileSystem.JAR_SEPARATOR; |
| final String jarUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, pathInJar); |
| final VirtualFilePointer jarPointer = myVirtualFilePointerManager.create(jarUrl, disposable, listener); |
| pointersToWatch[0] = jarParentPointer; |
| pointersToWatch[1] = jarPointer; |
| assertTrue(jarParentPointer.isValid()); |
| assertTrue(jarPointer.isValid()); |
| |
| jar.delete(); |
| jarParent.delete(); |
| refreshVFS(); |
| |
| verifyPointersInCorrectState(pointersToWatch); |
| assertFalse(jarParentPointer.isValid()); |
| assertFalse(jarPointer.isValid()); |
| UIUtil.dispatchAllInvocationEvents(); |
| |
| jarParent.mkdir(); |
| FileUtil.copy(originalJar, jar); |
| assert jar.exists(); |
| assert jarParent.exists(); |
| assert jarParent.getParentFile().exists(); |
| |
| refreshVFS(); |
| |
| verifyPointersInCorrectState(pointersToWatch); |
| assertTrue(jarParentPointer.isValid()); |
| assertTrue(jarPointer.isValid()); |
| UIUtil.dispatchAllInvocationEvents(); |
| |
| jar.delete(); |
| jarParent.delete(); |
| refreshVFS(); |
| UIUtil.dispatchAllInvocationEvents(); |
| |
| verifyPointersInCorrectState(pointersToWatch); |
| assertFalse(jarParentPointer.isValid()); |
| assertFalse(jarPointer.isValid()); |
| UIUtil.dispatchAllInvocationEvents(); |
| } |
| |
| public void testJars2() throws Exception { |
| final File tempDir = createTempDirectory(); |
| final File jarParent = new File(tempDir, "jarParent"); |
| jarParent.mkdir(); |
| final File jar = new File(jarParent, "x.jar"); |
| final File originalJar = new File(PathManagerEx.getTestDataPath() + "/psi/generics22/collect-2.2.jar"); |
| FileUtil.copy(originalJar, jar); |
| |
| LocalFileSystem.getInstance().refreshAndFindFileByIoFile(jar); // Make sure we receive events when jar changes |
| |
| final VirtualFilePointer[] pointersToWatch = new VirtualFilePointer[1]; |
| final VirtualFilePointerListener listener = new VirtualFilePointerListener() { |
| @Override |
| public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { |
| verifyPointersInCorrectState(pointersToWatch); |
| } |
| |
| @Override |
| public void validityChanged(@NotNull VirtualFilePointer[] pointers) { |
| verifyPointersInCorrectState(pointersToWatch); |
| } |
| }; |
| final String pathInJar = jar.getPath().replace(File.separatorChar, '/') + JarFileSystem.JAR_SEPARATOR; |
| final String jarUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, pathInJar); |
| final VirtualFilePointer jarPointer = myVirtualFilePointerManager.create(jarUrl, disposable, listener); |
| pointersToWatch[0] = jarPointer; |
| assertTrue(jarPointer.isValid()); |
| |
| jar.delete(); |
| |
| refreshVFS(); |
| |
| verifyPointersInCorrectState(pointersToWatch); |
| assertFalse(jarPointer.isValid()); |
| UIUtil.dispatchAllInvocationEvents(); |
| |
| jarParent.mkdir(); |
| FileUtil.copy(originalJar, jar); |
| assert jar.exists(); |
| |
| refreshVFS(); |
| |
| verifyPointersInCorrectState(pointersToWatch); |
| assertTrue(jarPointer.isValid()); |
| UIUtil.dispatchAllInvocationEvents(); |
| |
| jar.delete(); |
| refreshVFS(); |
| UIUtil.dispatchAllInvocationEvents(); |
| |
| verifyPointersInCorrectState(pointersToWatch); |
| assertFalse(jarPointer.isValid()); |
| UIUtil.dispatchAllInvocationEvents(); |
| } |
| |
| private static void refreshVFS() { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| VirtualFileManager.getInstance().syncRefresh(); |
| } |
| }); |
| UIUtil.dispatchAllInvocationEvents(); |
| } |
| |
| private static void verifyPointersInCorrectState(VirtualFilePointer[] pointers) { |
| for (VirtualFilePointer pointer : pointers) { |
| final VirtualFile file = pointer.getFile(); |
| assertTrue(file == null || file.isValid()); |
| } |
| } |
| |
| private VirtualFilePointer createPointerByFile(final File file, final VirtualFilePointerListener fileListener) throws IOException { |
| final String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, file.getCanonicalPath().replace(File.separatorChar, '/')); |
| final VirtualFile vFile = refreshAndFind(url); |
| return vFile == null |
| ? myVirtualFilePointerManager.create(url, disposable, fileListener) |
| : myVirtualFilePointerManager.create(vFile, disposable, fileListener); |
| } |
| |
| public void testFilePointerUpdate() throws Exception { |
| final File tempDir = createTempDirectory(); |
| final File file = new File(tempDir, "f1"); |
| |
| final VirtualFilePointer pointer = createPointerByFile(file, null); |
| |
| assertFalse(pointer.isValid()); |
| |
| boolean created = file.createNewFile(); |
| assertTrue(created); |
| |
| |
| doVfsRefresh(); |
| |
| assertTrue(pointer.isValid()); |
| |
| boolean deleted = file.delete(); |
| assertTrue(deleted); |
| |
| doVfsRefresh(); |
| assertFalse(pointer.isValid()); |
| } |
| |
| public void testContainerCreateDeletePerformance() throws Exception { |
| PlatformTestUtil.startPerformanceTest("VF container create/delete",200, new ThrowableRunnable() { |
| @Override |
| public void run() throws Exception { |
| Disposable parent = Disposer.newDisposable(); |
| for (int i = 0; i < 10000; i++) { |
| myVirtualFilePointerManager.createContainer(parent); |
| } |
| Disposer.dispose(parent); |
| } |
| }).cpuBound().assertTiming(); |
| } |
| |
| private static void doVfsRefresh() { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| LocalFileSystem.getInstance().refresh(false); |
| } |
| }); |
| } |
| |
| public void testDoubleDispose() throws IOException { |
| final File tempDir = createTempDirectory(); |
| final File file = new File(tempDir, "f1"); |
| boolean created = file.createNewFile(); |
| assertTrue(created); |
| |
| |
| final String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, file.getCanonicalPath().replace(File.separatorChar, '/')); |
| final VirtualFile vFile = refreshAndFind(url); |
| |
| Disposable disposable = Disposer.newDisposable(); |
| final VirtualFilePointer pointer = myVirtualFilePointerManager.create(vFile, disposable, new VirtualFilePointerListener() { |
| @Override |
| public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { |
| } |
| |
| @Override |
| public void validityChanged(@NotNull VirtualFilePointer[] pointers) { |
| } |
| }); |
| |
| |
| assertTrue(pointer.isValid()); |
| |
| Disposer.dispose(disposable); |
| assertFalse(pointer.isValid()); |
| } |
| |
| private static VirtualFile refreshAndFind(@NotNull final String url) { |
| return WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() { |
| @Override |
| public VirtualFile compute() { |
| return VirtualFileManager.getInstance().refreshAndFindFileByUrl(url); |
| } |
| }); |
| } |
| |
| public void testThreadsPerformance() throws IOException, InterruptedException { |
| final File ioTempDir = createTempDirectory(); |
| final File ioPtrBase = new File(ioTempDir, "parent"); |
| final File ioPtr = new File(ioPtrBase, "f1"); |
| final File ioSand = new File(ioTempDir, "sand"); |
| final File ioSandPtr = new File(ioSand, "f2"); |
| ioSandPtr.getParentFile().mkdirs(); |
| ioSandPtr.createNewFile(); |
| ioPtr.getParentFile().mkdirs(); |
| ioPtr.createNewFile(); |
| |
| doVfsRefresh(); |
| final VirtualFilePointer pointer = createPointerByFile(ioPtr, null); |
| assertTrue(pointer.isValid()); |
| final VirtualFile virtualFile = pointer.getFile(); |
| assertNotNull(virtualFile); |
| assertTrue(virtualFile.isValid()); |
| |
| VirtualFileAdapter listener = new VirtualFileAdapter() { |
| @Override |
| public void fileCreated(@NotNull VirtualFileEvent event) { |
| stressRead(pointer); |
| } |
| |
| @Override |
| public void fileDeleted(@NotNull VirtualFileEvent event) { |
| stressRead(pointer); |
| } |
| }; |
| Disposable disposable = Disposer.newDisposable(); |
| VirtualFileManager.getInstance().addVirtualFileListener(listener, disposable); |
| try { |
| int N = Timings.adjustAccordingToMySpeed(1000, false); |
| System.out.println("N = " + N); |
| for (int i=0;i< N;i++) { |
| assertNotNull(pointer.getFile()); |
| FileUtil.delete(ioPtrBase); |
| doVfsRefresh(); |
| |
| // ptr is now null, cached as map |
| |
| final VirtualFile v = LocalFileSystem.getInstance().findFileByIoFile(ioSandPtr); |
| new WriteCommandAction.Simple(getProject()) { |
| @Override |
| protected void run() throws Throwable { |
| v.delete(this); //inc FS modCount |
| LocalFileSystem.getInstance().findFileByIoFile(ioSand).createChildData(this, ioSandPtr.getName()); |
| } |
| }.execute().throwException(); |
| |
| // ptr is still null |
| |
| assertTrue(ioPtrBase.mkdirs()); |
| assertTrue(ioPtr.createNewFile()); |
| |
| stressRead(pointer); |
| doVfsRefresh(); |
| } |
| } |
| finally { |
| Disposer.dispose(disposable); // unregister listener early |
| } |
| } |
| |
| private static void stressRead(@NotNull final VirtualFilePointer pointer) { |
| for (int i = 0; i < 10; i++) { |
| JobLauncher.getInstance().submitToJobThread(Job.DEFAULT_PRIORITY, new Runnable() { |
| @Override |
| public void run() { |
| ApplicationManager.getApplication().runReadAction(new Runnable() { |
| @Override |
| public void run() { |
| VirtualFile file = pointer.getFile(); |
| if (file != null && !file.isValid()) { |
| throw new IncorrectOperationException("I've caught it. I am that good"); |
| } |
| } |
| }); |
| } |
| }, new Consumer<Future>() { |
| @Override |
| public void consume(Future future) { |
| try { |
| future.get(); |
| } |
| catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| }); |
| } |
| } |
| |
| public void testManyPointersUpdatePerformance() throws IOException { |
| LoggingListener listener = new LoggingListener(); |
| final List<VFileEvent> events = new ArrayList<VFileEvent>(); |
| final File ioTempDir = createTempDirectory(); |
| final VirtualFile temp = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioTempDir); |
| for (int i=0; i<100000; i++) { |
| myVirtualFilePointerManager.create(VfsUtilCore.pathToUrl("/a/b/c/d/" + i), disposable, listener); |
| events.add(new VFileCreateEvent(this, temp, "xxx" + i, false, true)); |
| } |
| PlatformTestUtil.startPerformanceTest("vfp update", 10000, new ThrowableRunnable() { |
| @Override |
| public void run() throws Throwable { |
| for (int i=0; i<100; i++) { |
| // simulate VFS refresh events since launching the actual refresh is too slow |
| myVirtualFilePointerManager.before(events); |
| myVirtualFilePointerManager.after(events); |
| } |
| } |
| }).assertTiming(); |
| } |
| |
| public void testMultipleCreationOfTheSamePointerPerformance() throws IOException { |
| final LoggingListener listener = new LoggingListener(); |
| final String url = VfsUtilCore.pathToUrl("/a/b/c/d/e"); |
| final VirtualFilePointer thePointer = myVirtualFilePointerManager.create(url, disposable, listener); |
| TempFileSystem.getInstance(); |
| PlatformTestUtil.startPerformanceTest("same url vfp create", 5000, new ThrowableRunnable() { |
| @Override |
| public void run() throws Throwable { |
| for (int i=0; i<10000000; i++) { |
| VirtualFilePointer pointer = myVirtualFilePointerManager.create(url, disposable, listener); |
| assertSame(pointer, thePointer); |
| } |
| } |
| }).assertTiming(); |
| } |
| } |