more tests -> community
authorpeter <peter@jetbrains.com>
Fri, 27 Jan 2012 22:32:21 +0000 (23:32 +0100)
committerpeter <peter@jetbrains.com>
Fri, 27 Jan 2012 22:32:21 +0000 (23:32 +0100)
java/java-tests/testData/psi/java/cls/Clazz.class [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/psi/impl/file/impl/EventsTestListener.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/psi/impl/file/impl/InvalidateClassFileTest.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java [new file with mode: 0644]

diff --git a/java/java-tests/testData/psi/java/cls/Clazz.class b/java/java-tests/testData/psi/java/cls/Clazz.class
new file mode 100644 (file)
index 0000000..117efbe
Binary files /dev/null and b/java/java-tests/testData/psi/java/cls/Clazz.class differ
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/EventsTestListener.java b/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/EventsTestListener.java
new file mode 100644 (file)
index 0000000..c8dfde3
--- /dev/null
@@ -0,0 +1,75 @@
+package com.intellij.psi.impl.file.impl;
+
+import com.intellij.psi.PsiTreeChangeEvent;
+import com.intellij.psi.PsiTreeChangeListener;
+
+/**
+ *  @author dsl
+ */
+class EventsTestListener implements PsiTreeChangeListener {
+  StringBuffer myBuffer = new StringBuffer();
+
+  public String getEventsString() {
+    return myBuffer.toString();
+  }
+
+  @Override
+  public void beforeChildAddition(PsiTreeChangeEvent event) {
+    myBuffer.append("beforeChildAddition\n");
+  }
+
+  @Override
+  public void beforeChildRemoval(PsiTreeChangeEvent event) {
+    myBuffer.append("beforeChildRemoval\n");
+  }
+
+  @Override
+  public void beforeChildReplacement(PsiTreeChangeEvent event) {
+    myBuffer.append("beforeChildReplacement\n");
+  }
+
+  @Override
+  public void beforeChildMovement(PsiTreeChangeEvent event) {
+    myBuffer.append("beforeChildMovement\n");
+  }
+
+  @Override
+  public void beforeChildrenChange(PsiTreeChangeEvent event) {
+    myBuffer.append("beforeChildrenChange\n");
+  }
+
+  @Override
+  public void beforePropertyChange(PsiTreeChangeEvent event) {
+    myBuffer.append("beforePropertyChange\n");
+  }
+
+  @Override
+  public void childAdded(PsiTreeChangeEvent event) {
+    myBuffer.append("childAdded\n");
+  }
+
+  @Override
+  public void childRemoved(PsiTreeChangeEvent event) {
+    myBuffer.append("childRemoved\n");
+  }
+
+  @Override
+  public void childReplaced(PsiTreeChangeEvent event) {
+    myBuffer.append("childReplaced\n");
+  }
+
+  @Override
+  public void childrenChanged(PsiTreeChangeEvent event) {
+    myBuffer.append("childrenChanged\n");
+  }
+
+  @Override
+  public void childMoved(PsiTreeChangeEvent event) {
+    myBuffer.append("childMoved\n");
+  }
+
+  @Override
+  public void propertyChanged(PsiTreeChangeEvent event) {
+    myBuffer.append("propertyChanged\n");
+  }
+}
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/InvalidateClassFileTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/InvalidateClassFileTest.java
new file mode 100644 (file)
index 0000000..ac79a17
--- /dev/null
@@ -0,0 +1,90 @@
+package com.intellij.psi.impl.file.impl;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.roots.libraries.Library;
+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.psi.PsiClass;
+import com.intellij.psi.PsiTreeChangeAdapter;
+import com.intellij.psi.PsiTreeChangeEvent;
+import com.intellij.testFramework.PsiTestCase;
+
+import java.io.File;
+
+/**
+ * @author ven
+ */
+public class InvalidateClassFileTest extends PsiTestCase {
+  private File myRoot;
+
+  private static final String BASE_PATH = "/psi/java/cls/";
+
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    myRoot = createTempDirectory();
+    myFilesToDelete.add(myRoot);
+  }
+
+  public void test1() throws Exception {
+    String srcPath = JavaTestUtil.getJavaTestDataPath() + BASE_PATH + "Clazz.class";
+    final File srcFile = new File(srcPath);
+    final File dstFile = new File(myRoot, "Clazz.class");
+    assertFalse(dstFile.exists());
+    FileUtil.copy(srcFile, dstFile);
+
+    final VirtualFile rootVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myRoot);
+
+    assertNotNull(rootVFile);
+
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      public void run() {
+        Module module = myModule;
+        final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
+        final ModifiableRootModel rootModel = rootManager.getModifiableModel();
+        final Library library = rootModel.getModuleLibraryTable().createLibrary();
+        final Library.ModifiableModel libraryModel = library.getModifiableModel();
+        libraryModel.addRoot(rootVFile.getUrl(), OrderRootType.CLASSES);
+        libraryModel.commit();
+        rootModel.commit();
+      }
+    });
+
+
+    PsiClass clazz = getJavaFacade().findClass("Clazz");
+    assertNotNull(clazz);
+    final boolean[] notified = new boolean[] {false};
+    final PsiTreeChangeAdapter listener = new PsiTreeChangeAdapter() {
+      @Override
+      public void childRemoved(PsiTreeChangeEvent event) {
+        notified[0] = true;
+      }
+
+      @Override
+      public void childrenChanged(PsiTreeChangeEvent event) {
+        notified[0] = true;
+      }
+    };
+    getPsiManager().addPsiTreeChangeListener(listener);
+
+    try {
+      dstFile.setLastModified(System.currentTimeMillis());
+      VirtualFileManager.getInstance().refresh(false);
+      assertTrue("No event sent!", notified[0]);
+    }
+    finally {
+      getPsiManager().removePsiTreeChangeListener(listener);
+    }
+
+    assertFalse(clazz.isValid());
+    assertNotNull(getJavaFacade().findClass("Clazz"));
+  }
+}
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java
new file mode 100644 (file)
index 0000000..884e038
--- /dev/null
@@ -0,0 +1,666 @@
+package com.intellij.psi.impl.file.impl;
+
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.roots.libraries.Library;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiTreeChangeEventImpl;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.testFramework.PsiTestCase;
+import com.intellij.util.io.ReadOnlyAttributeUtil;
+import com.intellij.util.WaitFor;
+
+import java.io.File;
+import java.io.IOException;
+
+public class PsiEventsTest extends PsiTestCase {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.file.impl.PsiEventsTest");
+
+  private VirtualFile myPrjDir1;
+  private VirtualFile myPrjDir2;
+  private VirtualFile myPrjDir3;
+  private VirtualFile mySrcDir1;
+  private VirtualFile mySrcDir2;
+  private VirtualFile mySrcDir3;
+  private VirtualFile mySrcDir4;
+  private VirtualFile myClsDir1;
+  private VirtualFile myExcludedDir1;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+
+    final File root = FileUtil.createTempFile(getName(), "");
+    root.delete();
+    root.mkdir();
+    myFilesToDelete.add(root);
+
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          VirtualFile rootVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(root);
+
+          myPrjDir1 = rootVFile.createChildDirectory(null, "prj1");
+          mySrcDir1 = myPrjDir1.createChildDirectory(null, "src1");
+          mySrcDir2 = myPrjDir1.createChildDirectory(null, "src2");
+
+          myPrjDir2 = rootVFile.createChildDirectory(null, "prj2");
+          mySrcDir3 = myPrjDir2;
+
+
+          myClsDir1 = myPrjDir1.createChildDirectory(null, "cls1");
+
+          myExcludedDir1 = mySrcDir1.createChildDirectory(null, "excluded");
+
+          final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel();
+          final ContentEntry contentEntry1 = rootModel.addContentEntry(myPrjDir1);
+          contentEntry1.addSourceFolder(mySrcDir1, false);
+          contentEntry1.addSourceFolder(mySrcDir2, false);
+          contentEntry1.addExcludeFolder(myExcludedDir1);
+          final Library.ModifiableModel libraryModel = rootModel.getModuleLibraryTable().createLibrary().getModifiableModel();
+          libraryModel.addRoot(myClsDir1, OrderRootType.CLASSES);
+          libraryModel.commit();
+          final ContentEntry contentEntry2 = rootModel.addContentEntry(myPrjDir2);
+          contentEntry2.addSourceFolder(mySrcDir3, false);
+          rootModel.commit();
+        } catch (IOException e) {
+          LOG.error(e);
+        }
+      }
+    });
+
+    //((PsiManagerImpl)myPsiManager).getFileManager().disbleVFSEventsProcessing();
+  }
+
+  public void testCreateFile() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    PsiDirectory psiDir = fileManager.findDirectory(myPrjDir1);
+    myPrjDir1.createChildData(null, "a.txt");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildAddition\n" +
+            "childAdded\n";
+    assertEquals(expected, string);
+  }
+
+  public void testCreateDirectory() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    PsiDirectory psiDir = fileManager.findDirectory(myPrjDir1);
+    myPrjDir1.createChildDirectory(null, "aaa");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildAddition\n" +
+            "childAdded\n";
+    assertEquals(expected, string);
+  }
+
+  public void testDeleteFile() throws Exception {
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+
+    FileManager fileManager = myPsiManager.getFileManager();
+    PsiFile psiFile = fileManager.findFile(file);//it's important to hold the reference
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.delete(null);
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildRemoval\n" +
+            "childRemoved\n";
+    assertEquals(expected, string);
+  }
+
+  public void testDeleteDirectory() throws Exception {
+    VirtualFile file = myPrjDir1.createChildDirectory(null, "aaa");
+
+    FileManager fileManager = myPsiManager.getFileManager();
+    PsiDirectory psiDirectory = fileManager.findDirectory(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.delete(null);
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildRemoval\n" +
+            "childRemoved\n";
+    assertEquals(expected, string);
+  }
+
+  public void testRenameFile1() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+    PsiFile psiFile = fileManager.findFile(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.rename(null, "b.txt");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforePropertyChange\n" +
+            "propertyChanged\n";
+    assertEquals(expected, string);
+  }
+
+  public void testRenameFile2() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+    PsiFile psiFile = fileManager.findFile(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.rename(null, "b.xml");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildReplacement\n" +
+            "childReplaced\n";
+    assertEquals(expected, string);
+  }
+
+  public void testRenameFile3() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+    PsiFile psiFile = fileManager.findFile(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.rename(null, "CVS");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildRemoval\n" +
+            "childRemoved\n";
+    assertEquals(expected, string);
+    assertNull(fileManager.findFile(file));
+  }
+
+  public void testRenameFile4() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "CVS");
+    PsiDirectory psiDirectory = fileManager.findDirectory(file.getParent());
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.rename(null, "aaa.txt");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildAddition\n" +
+            "childAdded\n";
+    assertEquals(expected, string);
+  }
+
+  public void testRenameDirectory1() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildDirectory(null, "dir1");
+    PsiDirectory psiDirectory = fileManager.findDirectory(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.rename(null, "dir2");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforePropertyChange\n" +
+            "propertyChanged\n";
+    assertEquals(expected, string);
+  }
+
+  public void testRenameDirectory2() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildDirectory(null, "dir1");
+    PsiDirectory psiDirectory = fileManager.findDirectory(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.rename(null, "CVS");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildRemoval\n" +
+            "childRemoved\n";
+    assertEquals(expected, string);
+    assertNull(fileManager.findDirectory(file));
+  }
+
+  public void testRenameDirectory3() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildDirectory(null, "CVS");
+    PsiDirectory psiDirectory = fileManager.findDirectory(file.getParent());
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.rename(null, "dir");
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildAddition\n" +
+            "childAdded\n";
+    assertEquals(expected, string);
+  }
+
+  public void testMakeFileReadOnly() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+    PsiFile psiFile = fileManager.findFile(file);
+
+    final EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    ReadOnlyAttributeUtil.setReadOnlyAttribute(file, true);
+
+    String string = listener.getEventsString();
+    final String expected =
+            "beforePropertyChange\n" +
+            "propertyChanged\n";
+
+    new WaitFor(500){
+      @Override
+      protected boolean condition() {
+        return expected.equals(listener.getEventsString());
+      }
+    }.assertCompleted(expected);
+
+    ReadOnlyAttributeUtil.setReadOnlyAttribute(file, false);
+  }
+
+  public void testMoveFile1() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+    PsiFile psiFile = fileManager.findFile(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, myPrjDir1.getParent());
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildMovement\n" +
+            "childMoved\n";
+    assertEquals(expected, string);
+  }
+
+  public void testMoveFile2() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+    PsiFile psiFile = fileManager.findFile(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, myExcludedDir1);
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildRemoval\n" +
+            "childRemoved\n";
+    assertEquals(expected, string);
+    assertNull(fileManager.findFile(file));
+  }
+
+  public void testMoveFile3() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myExcludedDir1.createChildData(null, "a.txt");
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, myPrjDir1);
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildAddition\n" +
+            "childAdded\n";
+    assertEquals(expected, string);
+  }
+
+  public void testMoveFile4() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myExcludedDir1.createChildData(null, "a.txt");
+    VirtualFile subdir = myExcludedDir1.createChildDirectory(null, "subdir");
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, subdir);
+
+    String string = listener.getEventsString();
+    String expected = "";
+    assertEquals(expected, string);
+  }
+
+  public void testMoveDirectory1() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildDirectory(null, "dir");
+    PsiDirectory psiDirectory = fileManager.findDirectory(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, myPrjDir1.getParent());
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildMovement\n" +
+            "childMoved\n";
+    assertEquals(expected, string);
+  }
+
+  public void testMoveDirectory2() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildDirectory(null, "dir");
+    PsiDirectory psiDirectory = fileManager.findDirectory(file);
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, myExcludedDir1);
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildRemoval\n" +
+            "childRemoved\n";
+    assertEquals(expected, string);
+    assertNull(fileManager.findDirectory(file));
+  }
+
+  public void testMoveDirectory3() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myExcludedDir1.createChildDirectory(null, "dir");
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, myPrjDir1);
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforeChildAddition\n" +
+            "childAdded\n";
+    assertEquals(expected, string);
+  }
+
+  public void testMoveDirectory4() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myExcludedDir1.createChildDirectory(null, "dir");
+    VirtualFile subdir = myExcludedDir1.createChildDirectory(null, "subdir");
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    file.move(null, subdir);
+
+    String string = listener.getEventsString();
+    String expected = "";
+    assertEquals(expected, string);
+  }
+
+  public void testChangeFile() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    VirtualFile file = myPrjDir1.createChildData(null, "a.txt");
+    VfsUtil.saveText(file, "aaa");
+    PsiFile psiFile = fileManager.findFile(file);
+    psiFile.getText();
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    VfsUtil.saveText(file, "bbb");
+    PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+
+    /*
+    assertEquals("", listener.getEventsString());
+
+    PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+    */
+
+    assertEquals(
+            "beforeChildrenChange\n" +
+            "beforeChildReplacement\n" +
+            "childReplaced\n"+
+            "childrenChanged\n",
+            listener.getEventsString());
+  }
+
+  public void testAddExcludeRoot() throws IOException {
+    final VirtualFile dir = myPrjDir1.createChildDirectory(null, "aaa");
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      @Override
+      public void run() {
+        final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel();
+        final ContentEntry contentEntry1 = rootModel.getContentEntries()[0];
+        contentEntry1.addExcludeFolder(dir);
+        rootModel.commit();
+      }
+    });
+
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforePropertyChange\n" +
+            "propertyChanged\n";
+    assertEquals(expected, string);
+  }
+
+  public void testAddSourceRoot() throws IOException {
+    final VirtualFile dir = myPrjDir1.createChildDirectory(null, "aaa");
+
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      @Override
+      public void run() {
+        final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel();
+        final ContentEntry contentEntry1 = rootModel.getContentEntries()[0];
+        contentEntry1.addSourceFolder(dir, false);
+        rootModel.commit();
+      }
+    });
+
+
+    String string = listener.getEventsString();
+    String expected =
+            "beforePropertyChange\n" +
+            "propertyChanged\n";
+    assertEquals(expected, string);
+  }
+
+  public void testModifyFileTypes() throws Exception {
+    FileManager fileManager = myPsiManager.getFileManager();
+    EventsTestListener listener = new EventsTestListener();
+    myPsiManager.addPsiTreeChangeListener(listener,getTestRootDisposable());
+
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      @Override
+      public void run() {
+        ((FileTypeManagerEx)FileTypeManager.getInstance()).fireBeforeFileTypesChanged();
+        ((FileTypeManagerEx)FileTypeManager.getInstance()).fireFileTypesChanged();
+      }
+    });
+
+
+    String string = listener.getEventsString();
+    String expected =
+      "beforePropertyChange\n" +
+      "propertyChanged\n";
+    assertEquals(expected, string);
+  }
+
+  public void testCyclicDispatching() throws Throwable {
+    final VirtualFile virtualFile = createFile("a.xml", "<tag/>").getVirtualFile();
+    final PsiTreeChangeAdapter listener = new PsiTreeChangeAdapter() {
+      @Override
+      public void propertyChanged(PsiTreeChangeEvent event) {
+        getJavaFacade().findClass("XXX", GlobalSearchScope.allScope(myProject));
+      }
+    };
+    getPsiManager().addPsiTreeChangeListener(listener,getTestRootDisposable());
+    virtualFile.rename(this, "b.xml");
+  }
+
+  String newText;
+  String original;
+  String eventsFired = "";
+  PsiTreeChangeListener listener;
+  public void testBeforeAfterChildrenChange() throws Throwable {
+    listener = new PsiTreeChangeListener() {
+      @Override
+      public void beforeChildAddition(PsiTreeChangeEvent event) {
+        logEvent(event);
+      }
+
+      @Override
+      public void beforeChildRemoval(PsiTreeChangeEvent event) {
+        logEvent(event);
+      }
+
+      @Override
+      public void beforeChildReplacement(PsiTreeChangeEvent event) {
+        logEvent(event);
+      }
+
+      @Override
+      public void beforeChildMovement(PsiTreeChangeEvent event) {
+        logEvent(event);
+      }
+
+      @Override
+      public void beforeChildrenChange(PsiTreeChangeEvent event) {
+        logEvent(event);
+      }
+
+      @Override
+      public void beforePropertyChange(PsiTreeChangeEvent event) {
+        logEvent(event);
+      }
+
+      @Override
+      public void childAdded(PsiTreeChangeEvent event) {
+        logEvent(event);
+        assertBeforeEventFired(event);
+      }
+
+      @Override
+      public void childRemoved(PsiTreeChangeEvent event) {
+        logEvent(event);
+        assertBeforeEventFired(event);
+      }
+
+      @Override
+      public void childReplaced(PsiTreeChangeEvent event) {
+        logEvent(event);
+        assertBeforeEventFired(event);
+      }
+
+      @Override
+      public void childrenChanged(PsiTreeChangeEvent event) {
+        logEvent(event);
+        assertBeforeEventFired(event);
+      }
+
+      @Override
+      public void childMoved(PsiTreeChangeEvent event) {
+        logEvent(event);
+        assertBeforeEventFired(event);
+      }
+
+      @Override
+      public void propertyChanged(PsiTreeChangeEvent event) {
+        logEvent(event);
+        assertBeforeEventFired(event);
+      }
+    };
+
+    myFile = createFile("A.java", "class A { int i; }");
+    doTestEvents("class A { }");
+    //doTestEvents("class A { int i; int j; }"); //todo: f*(&&ing compactChanges() in TreeChangeEventImpl garbles afterXXX events so that they don't match beforeXXX
+    doTestEvents("class A { int k; }");
+    doTestEvents("class A { int k; int i; }");
+    doTestEvents("class A { void foo(){} }");
+    doTestEvents("xxxxxx");
+    doTestEvents("");
+  }
+
+  private void logEvent(PsiTreeChangeEvent event) {
+    PsiTreeChangeEventImpl.PsiEventType code = ((PsiTreeChangeEventImpl)event).getCode();
+    eventsFired += eventText(event, code);
+  }
+
+  private static String eventText(PsiTreeChangeEvent event, PsiTreeChangeEventImpl.PsiEventType code) {
+    PsiElement parent = event.getParent();
+    PsiElement oldChild = event.getOldChild();
+    if (oldChild == null) oldChild = event.getChild();
+    PsiElement newChild = event.getNewChild();
+    return code + ":" +
+           (parent == null ? null : parent.getNode().getElementType()) + "/" +
+           (oldChild == null ? null : oldChild.getNode().getElementType()) + "->" +
+           (newChild == null ? null : newChild.getNode().getElementType()) +
+           ";";
+  }
+
+  private void assertBeforeEventFired(PsiTreeChangeEvent afterEvent) {
+    PsiTreeChangeEventImpl.PsiEventType code = ((PsiTreeChangeEventImpl)afterEvent).getCode();
+    assertFalse(code.name(), code.name().startsWith("BEFORE_"));
+    PsiTreeChangeEventImpl.PsiEventType beforeCode = PsiTreeChangeEventImpl.PsiEventType.values()[code.ordinal() - 1];
+    assertTrue(beforeCode.name(), beforeCode.name().startsWith("BEFORE_"));
+    String beforeText = eventText(afterEvent, beforeCode);
+    int i = eventsFired.indexOf(beforeText);
+    assertTrue("Event '" + beforeText + "' must be fired. Events so far: " + eventsFired, i >= 0);
+  }
+  private void doTestEvents(String newText) {
+    try {
+      getPsiManager().addPsiTreeChangeListener(listener);
+      eventsFired = "";
+      this.newText = newText;
+      original = getFile().getText();
+      Document document = PsiDocumentManager.getInstance(getProject()).getDocument(getFile());
+      document.setText(newText);
+      PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+
+      document.setText(original);
+      PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+    }
+    finally {
+      getPsiManager().removePsiTreeChangeListener(listener);
+    }
+  }
+}