diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java new file mode 100644 index 000000000000..baed1c53c602 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java @@ -0,0 +1,580 @@ +package com.intellij.openapi.fileEditor; + +import com.intellij.codeStyle.CodeStyleFacade; +import com.intellij.codeStyle.DefaultCodeStyleFacade; +import com.intellij.mock.MockCommandProcessor; +import com.intellij.mock.MockEditorFactory; +import com.intellij.mock.MockVirtualFile; +import com.intellij.mock.MockVirtualFileManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.UndoConfirmationPolicy; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; +import com.intellij.openapi.fileTypes.*; +import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl; +import com.intellij.openapi.fileTypes.impl.InternalFileTypeFactory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectLocator; +import com.intellij.openapi.project.impl.DefaultProjectLocator; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileEvent; +import com.intellij.testFramework.MockSchemesManagerFactory; +import com.intellij.testFramework.PlatformLiteFixture; +import com.intellij.util.LocalTimeCounter; +import org.jetbrains.annotations.NotNull; + +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.util.Arrays; + +public class FileDocumentManagerImplTest extends PlatformLiteFixture { + private MyFileDocumentManagerImpl myDocumentManager; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initApplication(); + registerExtension(FileTypeFactory.FILE_TYPE_FACTORY_EP, new InternalFileTypeFactory()); + registerExtensionPoint(FileDocumentSynchronizationVetoer.EP_NAME, FileDocumentSynchronizationVetoer.class); + getApplication().registerService(CommandProcessor.class, new MyMockCommandProcessor()); + getApplication().registerService(CodeStyleFacade.class, new DefaultCodeStyleFacade()); + getApplication().registerService(ProjectLocator.class, new DefaultProjectLocator()); + + MockEditorFactory editorFactory = new MockEditorFactory(); + getApplication().registerService(EditorFactory.class, editorFactory); + final LanguageFileType[] fileType = {null}; + getApplication().addComponent(FileTypeManager.class, new FileTypeManagerImpl(null, new MockSchemesManagerFactory()){ + @NotNull + @Override + public FileType getFileTypeByFileName(@NotNull String fileName) { + return fileType[0]; + } + + @NotNull + @Override + public FileType getFileTypeByFile(@NotNull VirtualFile file) { + return fileType[0]; + } + + @NotNull + @Override + public FileType getFileTypeByExtension(@NotNull String extension) { + return fileType[0]; + } + }); + + fileType[0] = StdFileTypes.JAVA; + + getApplication().getComponent(FileTypeManager.class); + myDocumentManager = new MyFileDocumentManagerImpl(); + getApplication().registerService(FileDocumentManager.class, myDocumentManager); + } + + public void testGetCachedDocument_Cached() throws Exception { + final Document cachedDocument = myDocumentManager.getCachedDocument(new MockVirtualFile("test.txt")); + assertNull(cachedDocument); + } + + public void testGetCachedDocument_NotCached() throws Exception { + final VirtualFile file = newTextFile(); + final Document document = myDocumentManager.getDocument(file); + + assertSame(myDocumentManager.getCachedDocument(file), document); + } + + public void testGetDocument_CreateNew() throws Exception { + final VirtualFile file = newTextFile(); + final Document document = myDocumentManager.getDocument(file); + assertNotNull(document); + assertEquals("test", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(file.isWritable(), document.isWritable()); + } + + public void testGetDocument_CreateNew_ReadOnly() throws Exception { + final MockVirtualFile file = newTextFile(); + file.setWritable(false); + final Document document = myDocumentManager.getDocument(file); + assertNotNull(document); + assertEquals("test", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(file.isWritable(), document.isWritable()); + } + + public void testGetDocument_ReturnCachedValueTwice() throws Exception { + final VirtualFile file = newTextFile(); + final Document document = myDocumentManager.getDocument(file); + assertNotNull(document); + assertEquals("test", document.getText()); + + final Document document2 = myDocumentManager.getDocument(file); + assertSame(document2, document); + } + + public void testGetDocument_CreatesNewAfterGced() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + int idCode = System.identityHashCode(document); + //noinspection UnusedAssignment + document = null; + + System.gc(); + System.gc(); + + document = myDocumentManager.getDocument(file); + assertTrue(idCode != System.identityHashCode(document)); + } + + public void testGetUnsavedDocuments_NoDocuments() throws Exception { + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + public void testGetUnsavedDocuments_CreatedDocument() throws Exception { + final VirtualFile file = newTextFile(); + myDocumentManager.getDocument(file); + + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + public void testGetUnsavedDocuments_ModifiedDocument() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(1, unsavedDocuments.length); + assertSame(document, unsavedDocuments[0]); + assertTrue(Arrays.equals("test".getBytes(), file.contentsToByteArray())); + } + + public void testGetUnsavedDocuments_afterSaveAllDocuments() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveAllDocuments(); + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + public void testGetUnsavedDocuments_afterSaveDocuments() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveDocument(document); + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + private static MockVirtualFile newTextFile() { + return new MockVirtualFile("test.txt", "test"); + } + + public void testGetUnsavedDocuments_afterSaveDocumentWithProblems() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @Override + @NotNull + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + throw new IOException(""); + } + }; + + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveDocument(document); + + assertNotNull(myDocumentManager.myExceptionOnSave); + + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(1, unsavedDocuments.length); + assertSame(document, unsavedDocuments[0]); + assertTrue(Arrays.equals("test".getBytes(), file.contentsToByteArray())); + } + + public void testUnsavedDocument_DontGc() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + int idCode = System.identityHashCode(document); + //noinspection UnusedAssignment + document = null; + + System.gc(); + System.gc(); + + document = myDocumentManager.getDocument(file); + assertEquals(idCode, System.identityHashCode(document)); + } + + public void testUnsavedDocument_GcAfterSave() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + int idCode = System.identityHashCode(document); + //noinspection UnusedAssignment + document = null; + + myDocumentManager.saveAllDocuments(); + + System.gc(); + System.gc(); + + document = myDocumentManager.getDocument(file); + assertTrue(idCode != System.identityHashCode(document)); + } + + public void testSaveDocument_DocumentWasntChanged() throws Exception { + final VirtualFile file = newTextFile(); + final long stamp = file.getModificationStamp(); + Document document = myDocumentManager.getDocument(file); + myDocumentManager.saveDocument(document); + assertEquals(stamp, file.getModificationStamp()); + } + + public void testSaveDocument_DocumentWasChanged() throws Exception { + final VirtualFile file = newTextFile(); + final long stamp = file.getModificationStamp(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveDocument(document); + assertTrue(stamp != file.getModificationStamp()); + assertEquals(document.getModificationStamp(), file.getModificationStamp()); + assertTrue(Arrays.equals("xxxtest".getBytes(), file.contentsToByteArray())); + } + + public void testSaveAllDocuments_DocumentWasChanged() throws Exception { + final VirtualFile file = newTextFile(); + final long stamp = file.getModificationStamp(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveAllDocuments(); + assertTrue(stamp != file.getModificationStamp()); + assertTrue(Arrays.equals("xxxtest".getBytes(), file.contentsToByteArray())); + } + + public void testGetFile() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + assertSame(file, myDocumentManager.getFile(document)); + } + + public void testConvertSeparators() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + Document document = myDocumentManager.getDocument(file); + assertEquals("test\ntest", document.getText()); + } + + public void testRememberSeparators() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + myDocumentManager.saveAllDocuments(); + assertTrue(Arrays.equals("xxxtest\rtest".getBytes(), file.contentsToByteArray())); + } + + public void testContentChanged_noDocument() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + file.setContent(null, "xxx", true); + assertNull(myDocumentManager.getCachedDocument(file)); + } + + public void testContentChanged_documentPresent() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + file.setContent(null, "xxx", true); + assertEquals("xxx", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + } + + public void testContentChanged_ignoreEventsFromSelf() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + file.setContent(myDocumentManager, "xxx", true); + assertEquals("test\ntest", document.getText()); + } + + public void testContentChanged_ignoreEventsFromSelfOnSave() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest") { + public Writer getWriter(final Object requestor, final long newModificationStamp) { + final VirtualFile self = this; + return new CharArrayWriter() { + @Override + public void close() { + super.close(); + long oldStamp = getModificationStamp(); + setModificationStamp(newModificationStamp); + setText(toString()); + myDocumentManager.contentsChanged(new VirtualFileEvent(requestor, self, null, oldStamp, getModificationStamp())); + } + }; + } + }; + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + final long stamp = document.getModificationStamp(); + + myDocumentManager.saveAllDocuments(); + assertEquals(stamp, document.getModificationStamp()); + } + + public void testContentChanged_reloadChangedDocument() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + + myDocumentManager.myReloadFromDisk = Boolean.TRUE; + try { + file.setContent(null, "xxx", true); + + assertEquals("xxx", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(0, myDocumentManager.getUnsavedDocuments().length); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testContentChanged_dontreloadChangedDocument() throws Exception { + final MockVirtualFile file = newTextFile(); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + + myDocumentManager.myReloadFromDisk = Boolean.FALSE; + try { + long oldDocumentStamp = document.getModificationStamp(); + + file.setContent(null, "xxx", true); + + assertEquals("zzztest", document.getText()); + assertEquals(oldDocumentStamp, document.getModificationStamp()); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testSaveDocument_dontSaveIfModStampEqualsToFile() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @NotNull + @Override + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + fail(); + throw new IOException(); + } + }; + DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + document.setModificationStamp(file.getModificationStamp()); + + myDocumentManager.saveDocument(document); + } + + // this test requires changes in idea code to support MockFile as local file system file (FileDocumentManager.needsRefresh). + // TODO: think how to test this functionality without hacking production code + public void atestContentChanged_reloadChangedDocumentOnSave() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest") { + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + long oldStamp = getModificationStamp(); + setModificationStamp(LocalTimeCounter.currentTime()); + myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, oldStamp, getModificationStamp())); + } + }; + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + file.setContent(null, "xxx", false); + + myDocumentManager.myReloadFromDisk = Boolean.TRUE; + try { + file.setActualTimeStamp(file.getTimeStamp() + 1); + myDocumentManager.saveAllDocuments(); + long fileStamp = file.getModificationStamp(); + + assertEquals("xxx", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(file.getModificationStamp(), fileStamp); + assertEquals(0, myDocumentManager.getUnsavedDocuments().length); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testContentChanged_dontreloadChangedDocumentOnSave() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test") { + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + long oldStamp = getModificationStamp(); + setModificationStamp(LocalTimeCounter.currentTime()); + myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, oldStamp, getModificationStamp())); + } + }; + + myDocumentManager.myReloadFromDisk = Boolean.FALSE; + try { + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + long documentStamp = document.getModificationStamp(); + + file.setContent(null, "xxx", false); + + file.setActualTimeStamp(file.getTimeStamp() + 1); + myDocumentManager.saveAllDocuments(); + + assertEquals("zzztest", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertTrue(Arrays.equals("zzztest".getBytes(), file.contentsToByteArray())); + assertEquals(documentStamp, document.getModificationStamp()); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testReplaceDocumentTestWithTheSameTest() throws Exception { + final boolean[] canCallSave = {true}; + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @NotNull + @Override + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + if (!canCallSave[0]) fail(); + return super.getOutputStream(requestor, newModificationStamp, newTimeStamp); + } + }; + DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file); + + String newText = "test text"; + document.replaceString(0, document.getTextLength(), newText); + assertTrue(myDocumentManager.isDocumentUnsaved(document)); + myDocumentManager.saveDocument(document); + + canCallSave[0] = false; + + final long modificationStamp = document.getModificationStamp(); + + document.replaceString(0, document.getTextLength(), newText); + + if (myDocumentManager.isDocumentUnsaved(document)) { + assertTrue(document.getModificationStamp() > modificationStamp); + } + else { + assertEquals(modificationStamp, document.getModificationStamp()); + } + } + + + public void testExternalReplaceWithTheSameText() throws Exception{ + final long[] modificationStamp = new long[1]; + + modificationStamp[0] = 1; + + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @NotNull + @Override + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + fail(); + throw new IOException(); + } + + @Override + public long getModificationStamp() { + return modificationStamp[0]; + } + + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, 1, 2)); + + } + }; + DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file); + + + modificationStamp[0] = 2; + + file.refresh(false, false); + + assertEquals(2, document.getModificationStamp()); + } + + public static class MyFileDocumentManagerImpl extends FileDocumentManagerImpl { + + public static final FileDocumentManagerListener[] LISTENERS = new FileDocumentManagerListener[0]; + + public IOException myExceptionOnSave; + public Boolean myReloadFromDisk = null; + + public MyFileDocumentManagerImpl() { + super(new MockVirtualFileManager()); + } + + @Override + protected void reportErrorOnSave(IOException e) { + myExceptionOnSave = e; + } + + @Override + protected boolean askReloadFromDisk(VirtualFile file, Document document) { + if (myReloadFromDisk == null){ + fail(); + return false; + } + else{ + return myReloadFromDisk.booleanValue(); + } + } + + @NotNull + @Override + protected FileDocumentManagerListener[] getListeners() { + return LISTENERS; + } + } + + private static class MyMockCommandProcessor extends MockCommandProcessor { + @Override + public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId) { + runnable.run(); + } + + @Override + public void executeCommand(Project project, + @NotNull Runnable runnable, + String name, + Object groupId, + @NotNull UndoConfirmationPolicy confirmationPolicy, + Document document) { + runnable.run(); + } + + @Override + public void executeCommand(Project project, + @NotNull Runnable runnable, + String name, + Object groupId, + @NotNull UndoConfirmationPolicy confirmationPolicy) { + runnable.run(); + } + + @Override + public void executeCommand(@NotNull Runnable runnable, String name, Object groupId) { + runnable.run(); + } + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryTest.java new file mode 100644 index 000000000000..04264ccb9df3 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryTest.java @@ -0,0 +1,210 @@ +package com.intellij.openapi.fileEditor; + +import com.intellij.mock.Mock; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.testFramework.PlatformTestCase; +import org.jetbrains.annotations.NotNull; + +public class IdeDocumentHistoryTest extends PlatformTestCase { + private IdeDocumentHistoryImpl myHistory; + + private Mock.MyFileEditor mySelectedEditor; + private Mock.MyVirtualFile mySelectedFile; + private FileEditorState myEditorState; + private FileEditorProvider myProvider; + + private MyState myState1; + private MyState myState2; + private MyState myState3; + + @Override + protected void setUp() throws Exception { + super.setUp(); + myHistory = new IdeDocumentHistoryImpl(getProject(), EditorFactory.getInstance(), new EditorManager(), VirtualFileManager.getInstance(), CommandProcessor.getInstance(), new Mock.MyToolWindowManager()) { + @Override + protected Pair getSelectedEditor() { + return Pair.create ((FileEditor)mySelectedEditor, myProvider); + } + + @Override + protected void executeCommand(Runnable runnable, String name, Object groupId) { + myHistory.onCommandStarted(); + runnable.run(); + myHistory.onSelectionChanged(); + myHistory.onCommandFinished(groupId); + } + }; + + mySelectedEditor = new Mock.MyFileEditor() { + @Override + @NotNull + public FileEditorState getState(@NotNull FileEditorStateLevel level) { + return myEditorState; + } + + @Override + public void setState(@NotNull FileEditorState state) { + myEditorState = state; + } + }; + mySelectedFile = new Mock.MyVirtualFile(); + myEditorState = new MyState(false, "start"); + myProvider = new Mock.MyFileEditorProvider() { + @Override + @NotNull + public String getEditorTypeId() { + return "EditorType"; + } + }; + } + public void testNoHistoryRecording() throws Throwable { + myHistory.onCommandStarted(); + myHistory.onCommandFinished(null); + + assertFalse(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + } + + public void testNavigationRecording() throws Throwable { + makeNavigationChange(myState2); + + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + + assertEquals(1, myHistory.getBackPlaces().size()); + } + + public void testMergingForwardPlaces() throws Throwable { + myEditorState = new MyState(true, "state1"); + makeNavigationChange(new MyState(true, "state2")); + + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + + assertEquals(1, myHistory.getBackPlaces().size()); + } + + public void testSimpleNavigation() throws Throwable { + pushTwoStates(); + + assertFalse(myHistory.isForwardAvailable()); + assertTrue(myHistory.isBackAvailable()); + + myHistory.back(); + assertTrue(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + assertSame(myState2, myEditorState); + + myHistory.back(); + assertFalse(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + assertSame(myState1, myEditorState); + + myHistory.forward(); + assertTrue(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + assertSame(myState2, myEditorState); + + myHistory.forward(); + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + assertSame(myState3, myEditorState); + } + + public void testQueueCutOff() throws Throwable { + pushTwoStates(); + myHistory.back(); + + assertTrue(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + + MyState newState = new MyState(false, "newState"); + makeNavigationChange(newState); + + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + + myHistory.back(); + assertSame(myState2, myEditorState); + myHistory.back(); + assertSame(myState1, myEditorState); + assertFalse(myHistory.isBackAvailable()); + } + + public void testRemoveInvalid() throws Throwable { + pushTwoStates(); + assertTrue(myHistory.isBackAvailable()); + + mySelectedFile.myValid = false; + + myHistory.onFileDeleted(); + + assertFalse(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + } + + + private void pushTwoStates() { + myState1 = new MyState(false, "state1"); + myState2 = new MyState(false, "state2"); + myState3 = new MyState(false, "state3"); + + myEditorState = myState1; + makeNavigationChange(myState2); + makeNavigationChange(myState3); + } + + private void makeNavigationChange(MyState newState) { + myHistory.onCommandStarted(); + myHistory.onSelectionChanged(); + myHistory.onCommandFinished(null); + myEditorState = newState; + } + + private class EditorManager extends Mock.MyFileEditorManager { + + @Override + public VirtualFile getFile(@NotNull FileEditor editor) { + return mySelectedFile; + } + + @Override + @NotNull + public Pair openFileWithProviders(@NotNull VirtualFile file, + boolean focusEditor, + boolean searchForSplitter) { + return Pair.create (new FileEditor[] {mySelectedEditor}, new FileEditorProvider[] {myProvider}); + } + + @Override + public FileEditorProvider getProvider(FileEditor editor) { + return myProvider; + } + } + + private static class MyState implements FileEditorState { + + private final boolean myCanBeMerged; + private final String myName; + + public MyState(boolean canBeMerged, String name) { + myCanBeMerged = canBeMerged; + myName = name; + } + + @Override + public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) { + return myCanBeMerged; + } + + public String toString() { + return myName; + } + } + +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/LoadTextUtilTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/LoadTextUtilTest.java new file mode 100644 index 000000000000..74ead6c532b8 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/LoadTextUtilTest.java @@ -0,0 +1,37 @@ +package com.intellij.openapi.fileEditor; + +import com.intellij.openapi.fileEditor.impl.LoadTextUtil; +import com.intellij.openapi.util.Comparing; +import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.LightVirtualFile; + +public class LoadTextUtilTest extends LightPlatformTestCase { + private static void doTest(String source, String expected, String expectedSeparator) { + final LightVirtualFile vFile = new LightVirtualFile("test.txt"); + final CharSequence real = LoadTextUtil.getTextByBinaryPresentation(source.getBytes(), vFile); + assertTrue("content", Comparing.equal(expected, real)); + if (expectedSeparator != null) { + assertEquals("detected line separator", expectedSeparator, FileDocumentManager.getInstance().getLineSeparator(vFile, null)); + } + } + + public void testSimpleLoad() { + doTest("test", "test", null); + } + + public void testConvert_SlashR() { + doTest("test\rtest\rtest", "test\ntest\ntest", "\r"); + } + + public void testConvert_SlashN() { + doTest("test\ntest\ntest", "test\ntest\ntest", "\n"); + } + + public void testConvert_SlashR_SlashN() { + doTest("test\r\ntest\r\ntest", "test\ntest\ntest", "\r\n"); + } + + public void testConvertMostCommon() { + doTest("test\r\ntest\r\ntest\ntest", "test\ntest\ntest\ntest", "\r\n"); + } +} diff --git a/platform/testFramework/src/com/intellij/mock/Mock.java b/platform/testFramework/src/com/intellij/mock/Mock.java new file mode 100644 index 000000000000..74c68d273eb0 --- /dev/null +++ b/platform/testFramework/src/com/intellij/mock/Mock.java @@ -0,0 +1,681 @@ +package com.intellij.mock; + +import com.intellij.codeHighlighting.BackgroundEditorHighlighter; +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileEditor.impl.EditorComposite; +import com.intellij.openapi.fileEditor.impl.EditorWindow; +import com.intellij.openapi.fileEditor.impl.EditorsSplitters; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.ui.popup.Balloon; +import com.intellij.openapi.util.*; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowAnchor; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.impl.IdeFocusManagerHeadless; +import com.intellij.util.ArrayUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.HyperlinkListener; +import java.awt.*; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collections; +import java.util.List; + +//[kirillk] - this class looks to be an overkill but IdeDocumentHistory is highly coupled +// with all of that stuff below, so it's not possible to test it's back/forward capabilities +// w/o making mocks for all of them. perhaps later we will decouple those things +public class Mock { + + public static class MyFileEditor extends UserDataHolderBase implements DocumentsEditor { + public Document[] DOCUMENTS; + + @Override + public Document[] getDocuments() { + return DOCUMENTS; + } + + @Override + @NotNull + public JComponent getComponent() { + throw new UnsupportedOperationException(); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return null; + } + + @Override + @NotNull + public String getName() { + return ""; + } + + @Override + public void dispose() { + } + + @Override + public StructureViewBuilder getStructureViewBuilder() { + return null; + } + + @Override + @NotNull + public FileEditorState getState(@NotNull FileEditorStateLevel level) { + return new FileEditorState() { + @Override + public boolean canBeMergedWith(FileEditorState fileEditorState, FileEditorStateLevel fileEditorStateLevel) { + return false; + } + }; + } + + @Override + public void setState(@NotNull FileEditorState state) { + } + + @Override + public boolean isModified() { + return false; + } + + @Override + public boolean isValid() { + return false; + } + + @Override + public void selectNotify() { + } + + @Override + public void deselectNotify() { + } + + @Override + public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) { + } + + @Override + public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) { + } + + @Override + public BackgroundEditorHighlighter getBackgroundHighlighter() { + return null; + } + + @Override + public FileEditorLocation getCurrentLocation() { + return null; + } + } + + public static class MyFileEditorManager extends FileEditorManagerEx { + @Override + public JComponent getComponent() { + return null; + } + + @Override + public ActionCallback notifyPublisher(Runnable runnable) { + runnable.run(); + return new ActionCallback.Done(); + } + + @Override + public ActionCallback getReady(@NotNull Object requestor) { + return new ActionCallback.Done(); + } + + @NotNull + @Override + public Pair openFileWithProviders(@NotNull VirtualFile file, + boolean focusEditor, + @NotNull EditorWindow window) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isInsideChange() { + return false; + } + + @Override + public boolean hasSplitOrUndockedWindows() { + return false; + } + + @Override + public EditorsSplitters getSplittersFor(Component c) { + return null; + } + + @Override + public EditorsSplitters getSplitters() { + return null; + } + + @Override + public AsyncResult getActiveWindow() { + return null; + } + + @Override + public void addTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public void removeTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public void addBottomComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public void removeBottomComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public JComponent getPreferredFocusedComponent() { + return null; + } + + @Override + @NotNull + public Pair getEditorsWithProviders(@NotNull VirtualFile file) { + throw new UnsupportedOperationException(); + } + + public FileEditorProvider getProvider(FileEditor editor) { + return null; + } + + @Override + public EditorWindow getCurrentWindow() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void setCurrentWindow(EditorWindow window) { + } + + @Override + public VirtualFile getFile(@NotNull FileEditor editor) { + return null; + } + + @Override + public void updateFilePresentation(VirtualFile file) { + } + + @Override + public void unsplitWindow() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void unsplitAllWindow() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + @NotNull + public EditorWindow[] getWindows() { + return new EditorWindow[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + @NotNull + public VirtualFile[] getSiblings(VirtualFile file) { + return new VirtualFile[0]; + } + + @Override + public void createSplitter(int orientation, @Nullable EditorWindow window) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void changeSplitterOrientation() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void flipTabs() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean tabsMode() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isInSplitter() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean hasOpenedFile() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public VirtualFile getCurrentFile() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Pair getSelectedEditorWithProvider(@NotNull VirtualFile file) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isChanged(@NotNull EditorComposite editor) { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public EditorWindow getNextWindow(@NotNull EditorWindow window) { + return null; + } + + @Override + public EditorWindow getPrevWindow(@NotNull EditorWindow window) { + return null; + } + + @Override + public void closeAllFiles() { + } + + public Editor openTextEditorEnsureNoFocus(@NotNull OpenFileDescriptor descriptor) { + return null; + } + + @Override + @NotNull + public Pair openFileWithProviders(@NotNull VirtualFile file, + boolean focusEditor, + boolean searchForSplitter) { + return Pair.create (new FileEditor[0], new FileEditorProvider [0]); + } + + @Override + public void closeFile(@NotNull VirtualFile file) { + } + + @Override + public void closeFile(@NotNull VirtualFile file, @NotNull EditorWindow window) { + } + + @Override + public Editor openTextEditor(OpenFileDescriptor descriptor, boolean focusEditor) { + return null; + } + + @Override + public Editor getSelectedTextEditor() { + return null; + } + + @Override + public boolean isFileOpen(@NotNull VirtualFile file) { + return false; + } + + @Override + @NotNull + public VirtualFile[] getOpenFiles() { + return new VirtualFile[0]; + } + + @Override + @NotNull + public VirtualFile[] getSelectedFiles() { + return new VirtualFile[0]; + } + + @Override + @NotNull + public FileEditor[] getSelectedEditors() { + return new FileEditor[0]; + } + + @Override + public FileEditor getSelectedEditor(@NotNull VirtualFile file) { + return null; + } + + @Override + @NotNull + public FileEditor[] getEditors(@NotNull VirtualFile file) { + return new FileEditor[0]; + } + + @NotNull + @Override + public FileEditor[] getAllEditors(@NotNull VirtualFile file) { + return new FileEditor[0]; + } + + @Override + @NotNull + public FileEditor[] getAllEditors() { + return new FileEditor[0]; + } + + @Override + public void removeEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent) { + } + + @Override + public void showEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent) { + } + + @Override + public void addFileEditorManagerListener(@NotNull FileEditorManagerListener listener) { + } + + @Override + public void addFileEditorManagerListener(@NotNull FileEditorManagerListener listener, Disposable parentDisposable) { + } + + @Override + public void removeFileEditorManagerListener(@NotNull FileEditorManagerListener listener) { + } + + @Override + @NotNull + public List openEditor(@NotNull OpenFileDescriptor descriptor, boolean focusEditor) { + return Collections.emptyList(); + } + + @Override + @NotNull + public Project getProject() { + throw new UnsupportedOperationException(); + } + + @Override + public void registerExtraEditorDataProvider(@NotNull EditorDataProvider provider, Disposable parentDisposable) { + } + + @Override + public int getWindowSplitCount() { + return 0; + } + } + + public static class MyVirtualFile extends VirtualFile { + + public boolean myValid = true; + + @Override + @NotNull + public VirtualFileSystem getFileSystem() { + throw new UnsupportedOperationException(); + } + + @Override + public String getPath() { + return null; + } + + @Override + @NotNull + public String getName() { + throw new UnsupportedOperationException(); + } + + @Override + public void rename(Object requestor, @NotNull String newName) throws IOException { + } + + @Override + public boolean isWritable() { + return false; + } + + @Override + public boolean isDirectory() { + return false; + } + + @Override + public boolean isValid() { + return myValid; + } + + @Override + public VirtualFile getParent() { + return null; + } + + @Override + public VirtualFile[] getChildren() { + return new VirtualFile[0]; + } + + @Override + public VirtualFile createChildDirectory(Object requestor, String name) throws IOException { + return null; + } + + @Override + public VirtualFile createChildData(Object requestor, @NotNull String name) throws IOException { + return null; + } + + @Override + public void delete(Object requestor) throws IOException { + } + + @Override + public void move(Object requestor, @NotNull VirtualFile newParent) throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + return null; + } + + @Override + @NotNull + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + @NotNull + public byte[] contentsToByteArray() throws IOException { + return ArrayUtil.EMPTY_BYTE_ARRAY; + } + + @Override + public long getModificationStamp() { + return 0; + } + + @Override + public long getTimeStamp() { + return 0; + } + + @Override + public long getLength() { + return 0; + } + + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + } + } + + public static class MyToolWindowManager extends ToolWindowManager { + @Override + public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull String id, + @NotNull JComponent component, + @NotNull ToolWindowAnchor anchor, + Disposable parentDisposable, + boolean canWorkInDumbMode, boolean canCloseContents) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull String id, + @NotNull JComponent component, + @NotNull ToolWindowAnchor anchor, + Disposable parentDisposable, + boolean canWorkInDumbMode) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, + final Disposable parentDisposable, final boolean dumbAware) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, final boolean sideTool) { + return null; + } + + public JComponent getFocusTargetFor(final JComponent comp) { + return null; + } + + @Override + public void unregisterToolWindow(@NotNull String id) { + } + + @Override + public void activateEditorComponent() { + } + + public ActionCallback requestFocus(final Component c, final boolean forced) { + return new ActionCallback.Done(); + } + + public ActionCallback requestFocus(final ActiveRunnable command, final boolean forced) { + return new ActionCallback.Done(); + } + + @Override + public boolean isEditorComponentActive() { + return false; + } + + @Override + public String[] getToolWindowIds() { + return ArrayUtil.EMPTY_STRING_ARRAY; + } + + @Override + public String getActiveToolWindowId() { + return null; + } + + @Override + public ToolWindow getToolWindow(String id) { + return null; + } + + @Override + public void invokeLater(Runnable runnable) { + } + + @Override + public IdeFocusManager getFocusManager() { + return IdeFocusManagerHeadless.INSTANCE; + } + + @Override + public void notifyByBalloon(@NotNull final String toolWindowId, final MessageType type, @NotNull final String text, @Nullable final Icon icon, + @Nullable final HyperlinkListener listener) { + } + + @Override + public Balloon getToolWindowBalloon(String id) { + return null; + } + + @Override + public void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody) { + } + } + + + public static class MyFileEditorProvider implements FileEditorProvider { + @Override + public boolean accept(@NotNull Project project, @NotNull VirtualFile file) { + return false; + } + + @Override + @NotNull + public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) { + throw new UnsupportedOperationException(); + } + + @Override + public void disposeEditor(@NotNull FileEditor editor) { + } + + @Override + @NotNull + public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project, @NotNull VirtualFile file) { + throw new UnsupportedOperationException(); + } + + @Override + public void writeState(@NotNull FileEditorState state, @NotNull Project project, @NotNull Element targetElement) { + } + + @Override + @NotNull + public String getEditorTypeId() { + throw new UnsupportedOperationException(); + } + + @Override + @NotNull + public FileEditorPolicy getPolicy() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/platform/testFramework/src/com/intellij/mock/MockCommandProcessor.java b/platform/testFramework/src/com/intellij/mock/MockCommandProcessor.java new file mode 100644 index 000000000000..981b97fc25df --- /dev/null +++ b/platform/testFramework/src/com/intellij/mock/MockCommandProcessor.java @@ -0,0 +1,104 @@ +package com.intellij.mock; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.command.CommandListener; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.UndoConfirmationPolicy; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MockCommandProcessor extends CommandProcessor { + @Override + public void executeCommand(@NotNull Runnable runnable, String name, Object groupId) { + } + + @Override + public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId) { + } + + @Override + public void executeCommand(Project project, + @NotNull Runnable runnable, + String name, + Object groupId, + @NotNull UndoConfirmationPolicy confirmationPolicy) { + + } + + @Override + public void setCurrentCommandName(String name) { + } + + @Override + public void setCurrentCommandGroupId(Object groupId) { + } + + @Override + public Runnable getCurrentCommand() { + return null; + } + + @Override + public String getCurrentCommandName() { + return null; + } + + @Override + @Nullable + public Object getCurrentCommandGroupId() { + return null; + } + + @Override + public Project getCurrentCommandProject() { + return null; + } + + @Override + public void addCommandListener(@NotNull CommandListener listener) { + } + + @Override + public void addCommandListener(@NotNull CommandListener listener, @NotNull Disposable parentDisposable) { + } + + @Override + public void removeCommandListener(@NotNull CommandListener listener) { + } + + @Override + public boolean isUndoTransparentActionInProgress() { + return false; + } + + @Override + public void markCurrentCommandAsGlobal(Project project) { + + } + + @Override + public void runUndoTransparentAction(@NotNull Runnable action) { + } + + @Override + public void executeCommand(Project project, @NotNull Runnable command, String name, Object groupId, @NotNull UndoConfirmationPolicy confirmationPolicy, + Document document) { + } + + @Override + public void executeCommand(Project project, @NotNull Runnable runnable, @Nls String name, Object groupId, @Nullable Document document) { + + } + + @Override + public void addAffectedDocuments(Project project, @NotNull Document... docs) { + } + + @Override + public void addAffectedFiles(Project project, @NotNull VirtualFile... files) { + } +} diff --git a/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java b/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java index 5478d0b84890..4a8ac05d43ff 100644 --- a/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java +++ b/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java @@ -3,15 +3,14 @@ */ package com.intellij.mock; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.openapi.vfs.*; +import com.intellij.util.LocalTimeCounter; import com.intellij.util.SmartList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -26,8 +25,8 @@ public class MockVirtualFile extends VirtualFile { private final boolean myDirectory; private final List myChildren = new SmartList(); private String myText; - private FileType myFileType; private final MockVirtualFileSystem myFileSystem = new MockVirtualFileSystem(); + private long myModStamp = LocalTimeCounter.currentTime(); public MockVirtualFile(final String name) { this(false, name); @@ -38,6 +37,12 @@ public class MockVirtualFile extends VirtualFile { myName = name; } + public MockVirtualFile(String name, String text) { + myName = name; + myText = text; + myDirectory = false; + } + public void setText(final String text) { myText = text; } @@ -73,9 +78,13 @@ public class MockVirtualFile extends VirtualFile { return prefix + "/" + myName; } + private boolean myIsWritable = true; @Override public boolean isWritable() { - throw new UnsupportedOperationException("Method isWritable is not yet implemented in " + getClass().getName()); + return myIsWritable; + } + public void setWritable(boolean b) { + myIsWritable = b; } @Override @@ -96,13 +105,28 @@ public class MockVirtualFile extends VirtualFile { @Override public VirtualFile[] getChildren() { - return (VirtualFile[])VfsUtil.toVirtualFileArray(myChildren); + return VfsUtil.toVirtualFileArray(myChildren); } @Override @NotNull - public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { - throw new UnsupportedOperationException("Method getOutputStream is not yet implemented in " + getClass().getName()); + public OutputStream getOutputStream(Object requestor, final long newModificationStamp, long newTimeStamp) throws IOException { + return new ByteArrayOutputStream() { + @Override + public void close() { + myModStamp = newModificationStamp; + myText = toString(); + } + }; + } + + @Override + public long getModificationStamp() { + return myModStamp; + } + + public void setModificationStamp(long modStamp) { + myModStamp = modStamp; } @Override @@ -111,9 +135,11 @@ public class MockVirtualFile extends VirtualFile { return myText.getBytes(); } + + private final long myTimeStamp = System.currentTimeMillis(); @Override public long getTimeStamp() { - throw new UnsupportedOperationException("Method getTimeStamp is not yet implemented in " + getClass().getName()); + return myTimeStamp; } @Override @@ -123,7 +149,16 @@ public class MockVirtualFile extends VirtualFile { @Override public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { - throw new UnsupportedOperationException("Method refresh is not yet implemented in " + getClass().getName()); + + } + + private long myActualTimeStamp = myTimeStamp; + public void setActualTimeStamp(long actualTimeStamp) { + myActualTimeStamp = actualTimeStamp; + } + + public long getActualTimeStamp() { + return myActualTimeStamp; } @Override @@ -131,6 +166,19 @@ public class MockVirtualFile extends VirtualFile { throw new UnsupportedOperationException("Method getInputStream is not yet implemented in " + getClass().getName()); } + private VirtualFileListener myListener = null; + public void setListener(VirtualFileListener listener) { + myListener = listener; + } + + public void setContent(Object requestor, String content, boolean fireEvent) { + long oldStamp = myModStamp; + myText = content; + if (fireEvent) { + myModStamp = LocalTimeCounter.currentTime(); + myListener.contentsChanged(new VirtualFileEvent(requestor, this, null, oldStamp, myModStamp)); + } + } }