OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013, the Dart project authors. | 2 * Copyright (c) 2013, the Dart project authors. |
3 * | 3 * |
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except | 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except |
5 * in compliance with the License. You may obtain a copy of the License at | 5 * in compliance with the License. You may obtain a copy of the License at |
6 * | 6 * |
7 * http://www.eclipse.org/legal/epl-v10.html | 7 * http://www.eclipse.org/legal/epl-v10.html |
8 * | 8 * |
9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License | 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License |
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express | 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express |
11 * or implied. See the License for the specific language governing permissions a
nd limitations under | 11 * or implied. See the License for the specific language governing permissions a
nd limitations under |
12 * the License. | 12 * the License. |
13 */ | 13 */ |
14 package com.google.dart.tools.ui.internal.text.dart; | 14 package com.google.dart.tools.ui.internal.text.dart; |
15 | 15 |
16 import com.google.common.base.Joiner; | 16 import com.google.common.base.Joiner; |
17 import com.google.dart.engine.ast.CompilationUnit; | 17 import com.google.dart.engine.ast.CompilationUnit; |
18 import com.google.dart.engine.context.AnalysisContext; | 18 import com.google.dart.engine.context.AnalysisContext; |
19 import com.google.dart.engine.context.AnalysisErrorInfo; | |
20 import com.google.dart.engine.context.AnalysisException; | |
21 import com.google.dart.engine.context.ChangeNotice; | 19 import com.google.dart.engine.context.ChangeNotice; |
22 import com.google.dart.engine.error.AnalysisError; | |
23 import com.google.dart.engine.internal.context.AnalysisContextImpl; | 20 import com.google.dart.engine.internal.context.AnalysisContextImpl; |
24 import com.google.dart.engine.sdk.DartSdk; | 21 import com.google.dart.engine.sdk.DartSdk; |
25 import com.google.dart.engine.sdk.DirectoryBasedDartSdk; | 22 import com.google.dart.engine.sdk.DirectoryBasedDartSdk; |
| 23 import com.google.dart.engine.source.ContentCache; |
26 import com.google.dart.engine.source.DartUriResolver; | 24 import com.google.dart.engine.source.DartUriResolver; |
27 import com.google.dart.engine.source.FileUriResolver; | 25 import com.google.dart.engine.source.FileUriResolver; |
28 import com.google.dart.engine.source.Source; | 26 import com.google.dart.engine.source.Source; |
29 import com.google.dart.engine.source.SourceFactory; | 27 import com.google.dart.engine.source.SourceFactory; |
30 import com.google.dart.engine.source.TestSource; | 28 import com.google.dart.engine.source.TestSource; |
31 import com.google.dart.engine.utilities.source.LineInfo; | 29 import com.google.dart.tools.core.analysis.model.AnalysisEvent; |
| 30 import com.google.dart.tools.core.analysis.model.AnalysisListener; |
32 import com.google.dart.tools.core.analysis.model.Project; | 31 import com.google.dart.tools.core.analysis.model.Project; |
| 32 import com.google.dart.tools.core.analysis.model.ResolvedEvent; |
| 33 import com.google.dart.tools.core.internal.builder.AnalysisWorker; |
| 34 |
| 35 import static com.google.dart.engine.utilities.io.FileUtilities2.createFile; |
33 | 36 |
34 import junit.framework.TestCase; | 37 import junit.framework.TestCase; |
35 | 38 |
36 import org.eclipse.jface.text.Document; | 39 import org.eclipse.jface.text.Document; |
37 import org.eclipse.jface.text.Region; | 40 import org.eclipse.jface.text.Region; |
38 import org.eclipse.jface.text.reconciler.DirtyRegion; | 41 import org.eclipse.jface.text.reconciler.DirtyRegion; |
39 import org.eclipse.swt.events.DisposeListener; | 42 import org.eclipse.swt.events.DisposeListener; |
40 import org.eclipse.swt.events.FocusListener; | 43 import org.eclipse.swt.events.FocusListener; |
41 | 44 |
42 import java.util.ArrayList; | 45 import java.io.File; |
43 import java.util.Arrays; | 46 import java.util.Arrays; |
44 import java.util.List; | 47 import java.util.List; |
| 48 import java.util.concurrent.CountDownLatch; |
| 49 import java.util.concurrent.TimeUnit; |
45 | 50 |
46 public class DartReconcilingStrategyTest extends TestCase { | 51 public class DartReconcilingStrategyTest extends TestCase { |
47 | 52 |
48 private final class MockContext extends com.google.dart.tools.core.internal.bu
ilder.MockContext { | 53 /** |
49 private final Object lock = new Object(); | 54 * Content cache that can wait for contents to be set. |
50 private String cachedContents = null; | 55 * |
51 private Exception exception = null; | 56 * @see #expectSetContentsFor(Source) |
52 private CompilationUnit unit = null; | 57 * @see #waitForSetContents(Source, long) |
53 private boolean resolved = false; | 58 */ |
54 private AnalysisErrorInfo unitInfo; | 59 private class MockCache extends ContentCache { |
55 private List<Source> priorityOrder = new ArrayList<Source>(); | 60 private Source expectedSource = null; |
| 61 private CountDownLatch expectedLatch = null; |
56 | 62 |
57 public Exception getException() { | 63 public void expectSetContentsFor(Source source) { |
58 return exception; | 64 expectedSource = source; |
| 65 expectedLatch = new CountDownLatch(1); |
59 } | 66 } |
60 | 67 |
61 @Override | 68 @Override |
62 public Source[] getLibrariesContaining(Source source) { | 69 public boolean setContents(Source source, String contents) { |
63 if (mockSource.equals(source)) { | 70 boolean result = super.setContents(source, contents); |
64 return new Source[] {mockSource}; | 71 if (source == expectedSource) { |
| 72 expectedLatch.countDown(); |
65 } | 73 } |
66 return super.getLibrariesContaining(source); | 74 return result; |
67 } | 75 } |
68 | 76 |
69 public CompilationUnit getUnit() { | 77 public String waitForSetContents(Source source, long milliseconds) { |
70 return unit; | 78 if (source != expectedSource) { |
| 79 throw new IllegalArgumentException("Should call expectSetContentsFor"); |
| 80 } |
| 81 try { |
| 82 assertTrue(expectedLatch.await(milliseconds, TimeUnit.MILLISECONDS)); |
| 83 } catch (InterruptedException e) { |
| 84 assertEquals(0, expectedLatch.getCount()); |
| 85 } |
| 86 expectedSource = null; |
| 87 expectedLatch = null; |
| 88 return getContents(source); |
| 89 } |
| 90 } |
| 91 |
| 92 /** |
| 93 * Analysis context that can wait for priority order and resolution. |
| 94 */ |
| 95 private class MockContext extends AnalysisContextImpl { |
| 96 private CountDownLatch priorityOrderLatch = null; |
| 97 private List<Source> priorityOrder = null; |
| 98 private long performAnalysisTaskTime = 0; |
| 99 private long setPriorityOrderTime = 0; |
| 100 private CountDownLatch resolvedLatch = null; |
| 101 private Source resolvedSource = null; |
| 102 private CompilationUnit resolvedUnit = null; |
| 103 private int flushCount = 0; |
| 104 |
| 105 private final AnalysisListener backgroundAnalysisListener = new AnalysisList
ener() { |
| 106 @Override |
| 107 public void complete(AnalysisEvent event) { |
| 108 synchronized (this) { |
| 109 if (resolvedLatch != null && resolvedLatch.getCount() > 0) { |
| 110 if (event.getContext() == MockContext.this) { |
| 111 resolvedUnit = getResolvedCompilationUnit(resolvedSource, resolved
Source); |
| 112 resolvedLatch.countDown(); |
| 113 } |
| 114 } |
| 115 } |
| 116 } |
| 117 |
| 118 @Override |
| 119 public void resolved(ResolvedEvent event) { |
| 120 synchronized (this) { |
| 121 if (resolvedLatch != null && resolvedLatch.getCount() > 0) { |
| 122 if (event.getContext() == MockContext.this && event.getSource() == r
esolvedSource) { |
| 123 resolvedUnit = event.getUnit(); |
| 124 resolvedLatch.countDown(); |
| 125 } |
| 126 } |
| 127 } |
| 128 } |
| 129 }; |
| 130 |
| 131 public void assertPrioritySetBeforeBackgroundAnalysis() { |
| 132 assertTrue(setPriorityOrderTime > 0); |
| 133 assertTrue(setPriorityOrderTime < performAnalysisTaskTime || performAnalys
isTaskTime == 0); |
71 } | 134 } |
72 | 135 |
73 @Override | 136 public void expectResolved(Source source) { |
74 public CompilationUnit parseCompilationUnit(Source source) throws AnalysisEx
ception { | 137 synchronized (backgroundAnalysisListener) { |
75 assertSame(mockSource, source); | 138 resolvedSource = source; |
76 synchronized (lock) { | 139 resolvedLatch = new CountDownLatch(1); |
77 if (unit != null) { | 140 resolvedUnit = null; |
78 final AnalysisContextImpl context = new AnalysisContextImpl(); | 141 AnalysisWorker.addListener(backgroundAnalysisListener); |
79 context.setContents(mockSource, cachedContents); | |
80 unit = context.parseCompilationUnit(mockSource); | |
81 unitInfo = context.getErrors(mockSource); | |
82 } | |
83 return unit; | |
84 } | 142 } |
85 } | 143 } |
86 | 144 |
| 145 public void expectSetPriorityOrder() { |
| 146 priorityOrderLatch = new CountDownLatch(1); |
| 147 } |
| 148 |
| 149 /** |
| 150 * Flush the resolved compilation unit for the specified source by creating
and resolving other |
| 151 * sources. |
| 152 * |
| 153 * @param source the source of the compilation unit to be flushed (not <code
>null</code>) |
| 154 */ |
| 155 public void flushCompilationUnit(Source source) throws Exception { |
| 156 for (int i = 0; i < 128; i++) { |
| 157 File newFile = createFile("/test_" + ++flushCount + ".dart"); |
| 158 Source newSource = new TestSource(mockCache, newFile, INITIAL_CONTENTS); |
| 159 assertNotNull(resolveCompilationUnit(newSource, newSource)); |
| 160 } |
| 161 } |
| 162 |
| 163 public List<Source> getPriorityOrder() { |
| 164 return priorityOrder; |
| 165 } |
| 166 |
87 @Override | 167 @Override |
88 public ChangeNotice[] performAnalysisTask() { | 168 public ChangeNotice[] performAnalysisTask() { |
89 if (!resolved) { | 169 if (performAnalysisTaskTime == 0) { |
90 resolved = true; | 170 performAnalysisTaskTime = System.currentTimeMillis(); |
91 final CompilationUnit resolvedUnit; | 171 if (performAnalysisTaskTime == setPriorityOrderTime) { |
92 final AnalysisErrorInfo resolvedInfo; | 172 performAnalysisTaskTime++; |
93 synchronized (lock) { | |
94 try { | |
95 resolvedUnit = parseCompilationUnit(mockSource); | |
96 resolvedInfo = unitInfo; | |
97 } catch (AnalysisException e) { | |
98 exception = e; | |
99 return super.performAnalysisTask(); | |
100 } | |
101 } | 173 } |
102 return new ChangeNotice[] {new ChangeNotice() { | |
103 | |
104 @Override | |
105 public CompilationUnit getCompilationUnit() { | |
106 return resolvedUnit; | |
107 } | |
108 | |
109 @Override | |
110 public AnalysisError[] getErrors() { | |
111 if (resolvedInfo != null) { | |
112 return resolvedInfo.getErrors(); | |
113 } | |
114 return null; | |
115 } | |
116 | |
117 @Override | |
118 public LineInfo getLineInfo() { | |
119 return resolvedInfo.getLineInfo(); | |
120 } | |
121 | |
122 @Override | |
123 public Source getSource() { | |
124 return mockSource; | |
125 } | |
126 }}; | |
127 } | 174 } |
128 return super.performAnalysisTask(); | 175 return super.performAnalysisTask(); |
129 } | 176 } |
130 | 177 |
131 @Override | 178 @Override |
132 public void setAnalysisPriorityOrder(List<Source> sources) { | 179 public void setAnalysisPriorityOrder(List<Source> sources) { |
133 synchronized (lock) { | 180 super.setAnalysisPriorityOrder(sources); |
| 181 if (setPriorityOrderTime == 0) { |
| 182 setPriorityOrderTime = System.currentTimeMillis(); |
| 183 if (setPriorityOrderTime == performAnalysisTaskTime) { |
| 184 setPriorityOrderTime++; |
| 185 } |
| 186 } |
| 187 if (priorityOrderLatch != null) { |
134 priorityOrder = sources; | 188 priorityOrder = sources; |
135 lock.notifyAll(); | 189 priorityOrderLatch.countDown(); |
136 } | 190 } |
137 } | 191 } |
138 | 192 |
139 @Override | 193 public CompilationUnit waitForResolution(Source source, long milliseconds) { |
140 public void setContents(Source source, String contents) { | 194 if (source != resolvedSource) { |
141 assertSame(mockSource, source); | 195 throw new IllegalArgumentException("Call expectResolved"); |
142 synchronized (lock) { | 196 } |
143 cachedContents = contents; | 197 try { |
144 resolved = false; | 198 assertTrue(resolvedLatch.await(milliseconds, TimeUnit.MILLISECONDS)); |
145 unit = null; | 199 } catch (InterruptedException e) { |
146 unitInfo = null; | 200 assertEquals(0, resolvedLatch.getCount()); |
147 lock.notifyAll(); | 201 } |
| 202 synchronized (backgroundAnalysisListener) { |
| 203 AnalysisWorker.removeListener(backgroundAnalysisListener); |
| 204 resolvedLatch = null; |
| 205 resolvedSource = null; |
| 206 return resolvedUnit; |
148 } | 207 } |
149 } | 208 } |
150 | 209 |
151 /** | 210 public List<Source> waitForSetPriorityOrder(long milliseconds) { |
152 * Wait up to the specified number of milliseconds for the cached contents. | 211 if (priorityOrderLatch == null) { |
153 * | 212 throw new IllegalStateException("Call expectSetPriorityOrder"); |
154 * @param milliseconds the maximum number of milliseconds to wait | |
155 * @param expectedContents the expected cached contents | |
156 * @return <code>true</code> if the contents match the expected contents | |
157 */ | |
158 public boolean waitFoCachedContents(long milliseconds, String expectedConten
ts) { | |
159 synchronized (lock) { | |
160 long end = System.currentTimeMillis() + milliseconds; | |
161 while (true) { | |
162 if (expectedContents == null ? cachedContents == null | |
163 : expectedContents.equals(cachedContents)) { | |
164 return true; | |
165 } | |
166 long delta = end - System.currentTimeMillis(); | |
167 if (delta <= 0) { | |
168 return false; | |
169 } | |
170 try { | |
171 lock.wait(delta); | |
172 } catch (InterruptedException e) { | |
173 //$FALL-THROUGH$ | |
174 } | |
175 } | |
176 } | 213 } |
177 } | 214 try { |
178 | 215 assertTrue(priorityOrderLatch.await(milliseconds, TimeUnit.MILLISECONDS)
); |
179 /** | 216 } catch (InterruptedException e) { |
180 * Wait up to the specified number of milliseconds for the priority order to
be set. | 217 assertEquals(0, priorityOrderLatch.getCount()); |
181 * | |
182 * @param expectedContents the expected cached contents | |
183 * @param milliseconds the maximum number of milliseconds to wait | |
184 * @return <code>true</code> if the contents match the expected contents | |
185 */ | |
186 public boolean waitForAnalysisPriorityOrder(long milliseconds, Source... exp
ectedOrder) { | |
187 synchronized (lock) { | |
188 long end = System.currentTimeMillis() + milliseconds; | |
189 while (true) { | |
190 if (Arrays.asList(expectedOrder).equals(priorityOrder)) { | |
191 return true; | |
192 } | |
193 long delta = end - System.currentTimeMillis(); | |
194 if (delta <= 0) { | |
195 return false; | |
196 } | |
197 try { | |
198 lock.wait(delta); | |
199 } catch (InterruptedException e) { | |
200 //$FALL-THROUGH$ | |
201 } | |
202 } | |
203 } | 218 } |
| 219 priorityOrderLatch = null; |
| 220 return priorityOrder; |
204 } | 221 } |
205 } | 222 } |
206 | 223 |
| 224 /** |
| 225 * Mock editor for testing {@link DartReconcilingStrategy} |
| 226 */ |
207 private final class MockEditor implements DartReconcilingEditor { | 227 private final class MockEditor implements DartReconcilingEditor { |
208 private final Object lock = new Object(); | 228 private CountDownLatch appliedLatch = null; |
209 | 229 private CompilationUnit appliedUnit = null; |
210 private DisposeListener disposeListener = null; | 230 private DisposeListener disposeListener = null; |
211 | |
212 private FocusListener focusListener = null; | 231 private FocusListener focusListener = null; |
213 | 232 |
214 private CompilationUnit appliedUnit = null; | |
215 private boolean applyCalled; | |
216 | |
217 @Override | 233 @Override |
218 public void addViewerDisposeListener(DisposeListener listener) { | 234 public void addViewerDisposeListener(DisposeListener listener) { |
219 if (disposeListener != null) { | 235 if (disposeListener != null) { |
220 throw new RuntimeException("dispose listener already added"); | 236 throw new RuntimeException("dispose listener already added"); |
221 } | 237 } |
222 disposeListener = listener; | 238 disposeListener = listener; |
223 } | 239 } |
224 | 240 |
225 @Override | 241 @Override |
226 public void addViewerFocusListener(FocusListener listener) { | 242 public void addViewerFocusListener(FocusListener listener) { |
227 if (focusListener != null) { | 243 if (focusListener != null) { |
228 throw new RuntimeException("focus listener already added"); | 244 throw new RuntimeException("focus listener already added"); |
229 } | 245 } |
230 focusListener = listener; | 246 focusListener = listener; |
231 } | 247 } |
232 | 248 |
233 @Override | 249 @Override |
234 public void applyCompilationUnitElement(CompilationUnit unit) { | 250 public void applyCompilationUnitElement(CompilationUnit unit) { |
235 synchronized (lock) { | 251 appliedUnit = unit; |
236 appliedUnit = unit; | 252 if (appliedLatch != null) { |
237 applyCalled = true; | 253 appliedLatch.countDown(); |
238 lock.notifyAll(); | |
239 } | 254 } |
240 } | 255 } |
241 | 256 |
242 public void clearApplyCalled() { | 257 public void expectApply() { |
243 applyCalled = true; | 258 appliedLatch = new CountDownLatch(1); |
244 } | 259 appliedUnit = null; |
245 | |
246 public CompilationUnit getAppliedUnit() { | |
247 synchronized (lock) { | |
248 return appliedUnit; | |
249 } | |
250 } | 260 } |
251 | 261 |
252 public DisposeListener getDisposeListener() { | 262 public DisposeListener getDisposeListener() { |
253 return disposeListener; | 263 return disposeListener; |
254 } | 264 } |
255 | 265 |
256 public FocusListener getFocusListener() { | |
257 return focusListener; | |
258 } | |
259 | |
260 @Override | 266 @Override |
261 public AnalysisContext getInputAnalysisContext() { | 267 public AnalysisContext getInputAnalysisContext() { |
262 return mockContext; | 268 return mockContext; |
263 } | 269 } |
264 | 270 |
265 @Override | 271 @Override |
266 public Project getInputProject() { | 272 public Project getInputProject() { |
267 // TODO (danrubel): test null and non-null project | 273 // TODO (danrubel): test null and non-null project |
268 return null; | 274 return null; |
269 } | 275 } |
270 | 276 |
271 @Override | 277 @Override |
272 public Source getInputSource() { | 278 public Source getInputSource() { |
273 return mockSource; | 279 return mockSource; |
274 } | 280 } |
275 | 281 |
276 @Override | 282 @Override |
277 public String getTitle() { | 283 public String getTitle() { |
278 return mockSource.getShortName(); | 284 return mockSource.getShortName(); |
279 } | 285 } |
280 | 286 |
281 /** | 287 public CompilationUnit waitForApply(long milliseconds, boolean expectAnother
) { |
282 * Wait up to the specified amount of time for the | 288 if (appliedLatch == null) { |
283 * {@link #applyCompilationUnitElement(CompilationUnit)} method to be called
. | 289 throw new IllegalStateException("Call expectApply"); |
284 * | |
285 * @param milliseconds the maximum number of milliseconds to wait | |
286 * @return {@code true} if the method was called, else {@code false} | |
287 */ | |
288 public boolean waitForApply(long milliseconds) { | |
289 long end = System.currentTimeMillis() + milliseconds; | |
290 synchronized (lock) { | |
291 while (!applyCalled) { | |
292 long delta = end - System.currentTimeMillis(); | |
293 if (delta <= 0) { | |
294 return false; | |
295 } | |
296 try { | |
297 lock.wait(delta); | |
298 } catch (InterruptedException e) { | |
299 //$FALL-THROUGH$ | |
300 } | |
301 } | |
302 } | 290 } |
303 return true; | 291 try { |
| 292 assertTrue(appliedLatch.await(milliseconds, TimeUnit.MILLISECONDS)); |
| 293 } catch (InterruptedException e) { |
| 294 assertEquals(0, appliedLatch.getCount()); |
| 295 } |
| 296 appliedLatch = expectAnother ? new CountDownLatch(1) : null; |
| 297 return appliedUnit; |
304 } | 298 } |
305 } | 299 } |
306 | 300 |
307 private final static String EOL = System.getProperty("line.separator", "\n"); | 301 private final static String EOL = System.getProperty("line.separator", "\n"); |
308 private static final String INITIAL_CONTENTS = Joiner.on(EOL).join(// | 302 private static final String INITIAL_CONTENTS = Joiner.on(EOL).join(// |
309 "library a;", | 303 "library a;", |
310 "class A { foo() => 'two'; }"); | 304 "class A { foo() => 'two'; }"); |
311 | 305 |
312 MockEditor mockEditor = new MockEditor(); | 306 MockEditor mockEditor = new MockEditor(); |
313 | 307 MockCache mockCache = new MockCache(); |
314 Source mockSource = new TestSource(INITIAL_CONTENTS); | 308 Source mockSource = new TestSource(mockCache, createFile("/test.dart"), INITIA
L_CONTENTS); |
315 MockContext mockContext = new MockContext(); | 309 MockContext mockContext = new MockContext(); |
316 Document mockDocument = new Document(); | 310 Document mockDocument = new Document(INITIAL_CONTENTS); |
317 DartReconcilingStrategy strategy = new DartReconcilingStrategy(mockEditor); | 311 DartReconcilingStrategy strategy = new DartReconcilingStrategy(mockEditor); |
318 | 312 |
| 313 /** |
| 314 * Assert reconciler clears cached contents when disposed |
| 315 */ |
319 public void test_dispose() throws Exception { | 316 public void test_dispose() throws Exception { |
320 mockContext.setContents(mockSource, INITIAL_CONTENTS); | 317 mockContext.setContents(mockSource, INITIAL_CONTENTS); |
321 mockContext.setAnalysisPriorityOrder(Arrays.asList(new Source[] {mockSource}
)); | 318 mockContext.setAnalysisPriorityOrder(Arrays.asList(new Source[] {mockSource}
)); |
| 319 mockCache.expectSetContentsFor(mockSource); |
| 320 mockContext.expectSetPriorityOrder(); |
| 321 |
322 mockEditor.getDisposeListener().widgetDisposed(null); | 322 mockEditor.getDisposeListener().widgetDisposed(null); |
323 // assert reconciler clears cached contents when disposed | 323 |
324 assertTrue(mockContext.waitFoCachedContents(5000, null)); | 324 assertEquals(0, mockContext.waitForSetPriorityOrder(5000).size()); |
325 assertTrue(mockContext.waitForAnalysisPriorityOrder(5000)); | 325 assertNull(mockCache.waitForSetContents(mockSource, 5000)); |
326 } | 326 } |
327 | 327 |
| 328 /** |
| 329 * Assert unit resolved, applied, and order set during initialReconcile |
| 330 */ |
328 public void test_initialReconcile() { | 331 public void test_initialReconcile() { |
| 332 mockEditor.expectApply(); |
| 333 mockContext.expectResolved(mockSource); |
| 334 mockContext.expectSetPriorityOrder(); |
| 335 |
329 strategy.initialReconcile(); | 336 strategy.initialReconcile(); |
330 assertTrue(mockEditor.waitForApply(5000)); | 337 |
331 assertSame(mockContext.getUnit(), mockEditor.getAppliedUnit()); | 338 assertNotNull(mockEditor.waitForApply(5000, true)); |
332 assertTrue(mockContext.waitForAnalysisPriorityOrder(5000, mockSource)); | 339 CompilationUnit unit = mockContext.waitForResolution(mockSource, 5000); |
| 340 assertNotNull(unit); |
| 341 assertSame(unit, mockEditor.waitForApply(5000, false)); |
| 342 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(5000); |
| 343 assertEquals(1, priorityOrder.size()); |
| 344 assertSame(mockSource, priorityOrder.get(0)); |
| 345 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); |
333 } | 346 } |
334 | 347 |
| 348 /** |
| 349 * Assert unit resolved, applied, and order set during initialReconcile after
AST has been removed |
| 350 * from the cache |
| 351 */ |
| 352 public void test_initialReconcile_afterFlush() throws Exception { |
| 353 assertNotNull(mockContext.resolveCompilationUnit(mockSource, mockSource)); |
| 354 mockContext.flushCompilationUnit(mockSource); |
| 355 assertNull(mockContext.getResolvedCompilationUnit(mockSource, mockSource)); |
| 356 |
| 357 mockEditor.expectApply(); |
| 358 mockContext.expectResolved(mockSource); |
| 359 mockContext.expectSetPriorityOrder(); |
| 360 |
| 361 strategy.initialReconcile(); |
| 362 |
| 363 assertNotNull(mockEditor.waitForApply(5000, true)); |
| 364 CompilationUnit unit = mockContext.waitForResolution(mockSource, 5000); |
| 365 assertNotNull(unit); |
| 366 assertSame(unit, mockEditor.waitForApply(5000, false)); |
| 367 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(5000); |
| 368 assertEquals(1, priorityOrder.size()); |
| 369 assertSame(mockSource, priorityOrder.get(0)); |
| 370 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); |
| 371 } |
| 372 |
| 373 /** |
| 374 * Assert unit resolved, applied, and order set during initialReconcile |
| 375 */ |
| 376 public void test_initialReconcile_alreadyCached() throws Exception { |
| 377 CompilationUnit unit = mockContext.resolveCompilationUnit(mockSource, mockSo
urce); |
| 378 assertNotNull(unit); |
| 379 mockEditor.expectApply(); |
| 380 mockContext.expectResolved(mockSource); |
| 381 mockContext.expectSetPriorityOrder(); |
| 382 |
| 383 strategy.initialReconcile(); |
| 384 |
| 385 assertSame(unit, mockEditor.waitForApply(5000, false)); |
| 386 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(5000); |
| 387 assertEquals(1, priorityOrder.size()); |
| 388 assertSame(mockSource, priorityOrder.get(0)); |
| 389 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); |
| 390 } |
| 391 |
| 392 /** |
| 393 * Assert editor with no context does not throw exception |
| 394 */ |
335 public void test_initialReconcile_nullContext() { | 395 public void test_initialReconcile_nullContext() { |
336 mockContext = null; | 396 mockContext = null; |
| 397 assertNull(mockEditor.getInputAnalysisContext()); |
| 398 |
337 strategy.initialReconcile(); | 399 strategy.initialReconcile(); |
338 assertNull(mockEditor.getAppliedUnit()); | 400 |
| 401 // test infrastructure asserts no exceptions |
339 } | 402 } |
340 | 403 |
341 // assert reconciler lazily sets cached contents and performs resolution | 404 /** |
| 405 * Assert reconciler lazily sets cached contents and performs resolution |
| 406 */ |
342 public void test_initialState() throws Exception { | 407 public void test_initialState() throws Exception { |
343 assertTrue(mockContext.waitFoCachedContents(5000, null)); | 408 assertNull(mockCache.getContents(mockSource)); |
344 assertNull(mockContext.getUnit()); | 409 assertNull(mockContext.getResolvedCompilationUnit(mockSource, mockSource)); |
345 assertTrue(mockContext.waitForAnalysisPriorityOrder(5000)); | 410 assertNull(mockContext.getPriorityOrder()); |
346 } | 411 } |
347 | 412 |
348 public void test_reconcileDirtyRegionIRegion() { | 413 /** |
| 414 * Assert that a document change clears the cached unit and a resolve resets i
t |
| 415 */ |
| 416 public void test_reconcileDirtyRegionIRegion() throws Exception { |
| 417 String newText = "//comment\n"; |
| 418 |
| 419 mockEditor.expectApply(); |
349 strategy.initialReconcile(); | 420 strategy.initialReconcile(); |
350 assertTrue(mockEditor.waitForApply(5000)); | 421 assertNotNull(mockEditor.waitForApply(5000, false)); |
351 mockEditor.clearApplyCalled(); | 422 |
352 strategy.reconcile(new DirtyRegion(0, 5, "ignored", "hello"), new Region(0,
5)); | 423 mockEditor.expectApply(); |
353 assertTrue(mockEditor.waitForApply(5000)); | 424 mockDocument.replace(0, 0, newText); |
354 assertSame(mockContext.getUnit(), mockEditor.getAppliedUnit()); | 425 assertNull(mockEditor.waitForApply(5000, false)); |
| 426 |
| 427 mockEditor.expectApply(); |
| 428 strategy.reconcile(new DirtyRegion(0, 0, DirtyRegion.INSERT, newText), new R
egion(0, 0)); |
| 429 CompilationUnit unit = mockEditor.waitForApply(5000, false); |
| 430 assertNotNull(unit); |
355 } | 431 } |
356 | 432 |
357 public void test_reconcileDirtyRegionIRegion_nullContext() { | 433 /** |
| 434 * Assert editor with no context does not throw exception |
| 435 */ |
| 436 public void test_reconcileDirtyRegionIRegion_nullContext() throws Exception { |
| 437 String newText = "//comment\n"; |
| 438 |
358 mockContext = null; | 439 mockContext = null; |
359 strategy.initialReconcile(); | 440 strategy.initialReconcile(); |
360 strategy.reconcile(new DirtyRegion(0, 5, "ignored", "hello"), new Region(0,
5)); | 441 mockDocument.replace(0, 0, newText); |
361 assertNull(mockEditor.getAppliedUnit()); | 442 strategy.reconcile(new DirtyRegion(0, 0, DirtyRegion.INSERT, newText), new R
egion(0, 0)); |
| 443 |
| 444 // test infrastructure asserts no exceptions |
362 } | 445 } |
363 | 446 |
364 public void test_reconcileIRegion() { | 447 public void test_reconcileIRegion() throws Exception { |
| 448 String newText = "//comment\n"; |
| 449 |
| 450 mockEditor.expectApply(); |
365 strategy.initialReconcile(); | 451 strategy.initialReconcile(); |
366 assertTrue(mockEditor.waitForApply(5000)); | 452 assertNotNull(mockEditor.waitForApply(5000, false)); |
367 mockEditor.clearApplyCalled(); | 453 |
368 strategy.reconcile(new Region(0, 5)); | 454 mockEditor.expectApply(); |
369 assertTrue(mockEditor.waitForApply(5000)); | 455 mockDocument.replace(0, 0, newText); |
370 assertSame(mockContext.getUnit(), mockEditor.getAppliedUnit()); | 456 assertNull(mockEditor.waitForApply(5000, false)); |
| 457 |
| 458 mockEditor.expectApply(); |
| 459 strategy.reconcile(new Region(0, newText.length())); |
| 460 CompilationUnit unit = mockEditor.waitForApply(5000, false); |
| 461 assertNotNull(unit); |
371 } | 462 } |
372 | 463 |
373 public void test_reconcileIRegion_nullContext() { | 464 /** |
| 465 * Assert editor with no context does not throw exception |
| 466 */ |
| 467 public void test_reconcileIRegion_nullContext() throws Exception { |
| 468 String newText = "//comment\n"; |
| 469 |
374 mockContext = null; | 470 mockContext = null; |
375 strategy.initialReconcile(); | 471 strategy.initialReconcile(); |
376 strategy.reconcile(new Region(0, 5)); | 472 mockDocument.replace(0, 0, newText); |
377 assertNull(mockEditor.getAppliedUnit()); | 473 strategy.reconcile(new Region(0, newText.length())); |
| 474 |
| 475 // test infrastructure asserts no exceptions |
378 } | 476 } |
379 | 477 |
380 @Override | 478 @Override |
381 protected void setUp() throws Exception { | 479 protected void setUp() throws Exception { |
382 super.setUp(); | |
383 DartSdk sdk = DirectoryBasedDartSdk.getDefaultSdk(); | 480 DartSdk sdk = DirectoryBasedDartSdk.getDefaultSdk(); |
384 SourceFactory sourceFactory = new SourceFactory(new DartUriResolver(sdk), ne
w FileUriResolver()); | 481 assertNotNull(sdk); |
| 482 SourceFactory sourceFactory = new SourceFactory( |
| 483 mockCache, |
| 484 new DartUriResolver(sdk), |
| 485 new FileUriResolver()); |
385 mockContext.setSourceFactory(sourceFactory); | 486 mockContext.setSourceFactory(sourceFactory); |
386 strategy.setDocument(mockDocument); | 487 strategy.setDocument(mockDocument); |
387 } | 488 } |
388 | 489 |
389 @Override | 490 @Override |
390 protected void tearDown() throws Exception { | 491 protected void tearDown() throws Exception { |
391 if (mockContext != null) { | |
392 assertNull(mockContext.getException()); | |
393 } | |
394 // Ensure that strategy removes its AnalysisWorker listener | 492 // Ensure that strategy removes its AnalysisWorker listener |
395 if (strategy != null) { | 493 if (strategy != null) { |
396 strategy.dispose(); | 494 strategy.dispose(); |
397 } | 495 } |
398 } | 496 } |
399 } | 497 } |
OLD | NEW |