fix "IDEA-221944 Deadlock on opening second project" and support preloading for proje...
[idea/community.git] / platform / platform-tests / testSrc / com / intellij / openapi / fileEditor / impl / IdeDocumentHistoryTest.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.openapi.fileEditor.impl;
3
4 import com.intellij.mock.Mock;
5 import com.intellij.openapi.fileEditor.FileEditor;
6 import com.intellij.openapi.fileEditor.FileEditorProvider;
7 import com.intellij.openapi.fileEditor.FileEditorState;
8 import com.intellij.openapi.fileEditor.FileEditorStateLevel;
9 import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
10 import com.intellij.openapi.fileEditor.ex.FileEditorWithProvider;
11 import com.intellij.openapi.util.Disposer;
12 import com.intellij.openapi.util.Pair;
13 import com.intellij.openapi.vfs.VirtualFile;
14 import com.intellij.testFramework.HeavyPlatformTestCase;
15 import org.jetbrains.annotations.NotNull;
16
17 public class IdeDocumentHistoryTest extends HeavyPlatformTestCase {
18   private IdeDocumentHistoryImpl myHistory;
19
20   private Mock.MyFileEditor  mySelectedEditor;
21   private Mock.MyVirtualFile mySelectedFile;
22   private FileEditorState myEditorState;
23   private FileEditorProvider myProvider;
24
25   private MyState myState1;
26   private MyState myState2;
27   private MyState myState3;
28
29   @Override
30   protected void setUp() throws Exception {
31     super.setUp();
32
33     mySelectedEditor = new Mock.MyFileEditor() {
34       @Override
35       @NotNull
36       public FileEditorState getState(@NotNull FileEditorStateLevel level) {
37         return myEditorState;
38       }
39
40       @Override
41       public void setState(@NotNull FileEditorState state) {
42         myEditorState = state;
43       }
44     };
45
46     EditorManager editorManager = new EditorManager();
47     myHistory = new IdeDocumentHistoryImpl(getProject()) {
48       @Override
49       protected FileEditorManagerEx getFileEditorManager() {
50         return editorManager;
51       }
52
53       @Override
54       protected FileEditorWithProvider getSelectedEditor() {
55         return mySelectedEditor == null ? null : new FileEditorWithProvider(mySelectedEditor, myProvider);
56       }
57
58       @Override
59       protected void executeCommand(Runnable runnable, String name, Object groupId) {
60         myHistory.onCommandStarted();
61         runnable.run();
62         myHistory.onSelectionChanged();
63         myHistory.onCommandFinished(getProject(), groupId);
64       }
65     };
66
67     mySelectedFile = new Mock.MyVirtualFile();
68     myEditorState = new MyState(false, "start");
69     myProvider = new Mock.MyFileEditorProvider() {
70       @Override
71       @NotNull
72       public String getEditorTypeId() {
73         return "EditorType";
74       }
75     };
76   }
77
78   @Override
79   protected void tearDown() throws Exception {
80     try {
81       Disposer.dispose(myHistory);
82       myHistory = null;
83       mySelectedEditor = null;
84       myEditorState = null;
85       myProvider = null;
86       mySelectedFile = null;
87       myState1 = null;
88       myState2 = null;
89       myState3 = null;
90     }
91     catch (Throwable e) {
92       addSuppressedException(e);
93     }
94     finally {
95       super.tearDown();
96     }
97   }
98
99   public void testNoHistoryRecording() {
100     myHistory.onCommandStarted();
101     myHistory.onCommandFinished(getProject(), null);
102
103     assertFalse(myHistory.isBackAvailable());
104     assertFalse(myHistory.isForwardAvailable());
105   }
106
107   public void testNavigationRecording() {
108     makeNavigationChange(myState2);
109
110     assertTrue(myHistory.isBackAvailable());
111     assertFalse(myHistory.isForwardAvailable());
112
113     assertEquals(1, myHistory.getBackPlaces().size());
114   }
115
116   public void testMergingForwardPlaces() {
117     myEditorState = new MyState(true, "state1");
118     makeNavigationChange(new MyState(true, "state2"));
119
120     assertTrue(myHistory.isBackAvailable());
121     assertFalse(myHistory.isForwardAvailable());
122
123     assertEquals(1, myHistory.getBackPlaces().size());
124   }
125
126   public void testSimpleNavigation() {
127     pushTwoStates();
128
129     assertFalse(myHistory.isForwardAvailable());
130     assertTrue(myHistory.isBackAvailable());
131
132     myHistory.back();
133     assertTrue(myHistory.isBackAvailable());
134     assertTrue(myHistory.isForwardAvailable());
135     assertSame(myState2, myEditorState);
136
137     myHistory.back();
138     assertFalse(myHistory.isBackAvailable());
139     assertTrue(myHistory.isForwardAvailable());
140     assertSame(myState1, myEditorState);
141
142     myHistory.forward();
143     assertTrue(myHistory.isBackAvailable());
144     assertTrue(myHistory.isForwardAvailable());
145     assertSame(myState2, myEditorState);
146
147     myHistory.forward();
148     assertTrue(myHistory.isBackAvailable());
149     assertFalse(myHistory.isForwardAvailable());
150     assertSame(myState3, myEditorState);
151   }
152
153   public void testQueueCutOff() {
154     pushTwoStates();
155     myHistory.back();
156
157     assertTrue(myHistory.isBackAvailable());
158     assertTrue(myHistory.isForwardAvailable());
159
160     MyState newState = new MyState(false, "newState");
161     makeNavigationChange(newState);
162
163     assertTrue(myHistory.isBackAvailable());
164     assertFalse(myHistory.isForwardAvailable());
165
166     myHistory.back();
167     assertSame(myState2, myEditorState);
168     myHistory.back();
169     assertSame(myState1, myEditorState);
170     assertFalse(myHistory.isBackAvailable());
171   }
172
173   public void testRemoveInvalid() {
174     pushTwoStates();
175     assertTrue(myHistory.isBackAvailable());
176
177     mySelectedFile.myValid = false;
178     myHistory.removeInvalidFilesFromStacks();
179
180     assertFalse(myHistory.isBackAvailable());
181     assertFalse(myHistory.isForwardAvailable());
182   }
183
184
185   private void pushTwoStates() {
186     myState1 = new MyState(false, "state1");
187     myState2 = new MyState(false, "state2");
188     myState3 = new MyState(false, "state3");
189
190     myEditorState = myState1;
191     makeNavigationChange(myState2);
192     makeNavigationChange(myState3);
193   }
194
195   private void makeNavigationChange(MyState newState) {
196     myHistory.onCommandStarted();
197     myHistory.onSelectionChanged();
198     myHistory.onCommandFinished(getProject(), null);
199     myEditorState = newState;
200   }
201
202   private class EditorManager extends Mock.MyFileEditorManager {
203     @Override
204     public VirtualFile getFile(@NotNull FileEditor editor) {
205       return mySelectedFile;
206     }
207
208     @Override
209     @NotNull
210     public Pair<FileEditor[], FileEditorProvider[]> openFileWithProviders(@NotNull VirtualFile file, boolean focusEditor, boolean searchForSplitter) {
211       return Pair.create(new FileEditor[]{mySelectedEditor}, new FileEditorProvider[]{myProvider});
212     }
213
214     @Override
215     public FileEditorProvider getProvider(FileEditor editor) {
216       return myProvider;
217     }
218   }
219
220   private static class MyState implements FileEditorState {
221
222     private final boolean myCanBeMerged;
223     private final String myName;
224
225     MyState(boolean canBeMerged, String name) {
226       myCanBeMerged = canBeMerged;
227       myName = name;
228     }
229
230     @Override
231     public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) {
232       return myCanBeMerged;
233     }
234
235     public String toString() {
236       return myName;
237     }
238   }
239 }