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 |
(...skipping 28 matching lines...) Expand all Loading... |
39 import org.eclipse.jface.text.Document; | 39 import org.eclipse.jface.text.Document; |
40 import org.eclipse.jface.text.Region; | 40 import org.eclipse.jface.text.Region; |
41 import org.eclipse.jface.text.reconciler.DirtyRegion; | 41 import org.eclipse.jface.text.reconciler.DirtyRegion; |
42 import org.eclipse.swt.events.DisposeListener; | 42 import org.eclipse.swt.events.DisposeListener; |
43 import org.eclipse.swt.events.FocusListener; | 43 import org.eclipse.swt.events.FocusListener; |
44 | 44 |
45 import java.io.File; | 45 import java.io.File; |
46 import java.util.Arrays; | 46 import java.util.Arrays; |
47 import java.util.List; | 47 import java.util.List; |
48 import java.util.concurrent.CountDownLatch; | 48 import java.util.concurrent.CountDownLatch; |
| 49 import java.util.concurrent.Semaphore; |
49 import java.util.concurrent.TimeUnit; | 50 import java.util.concurrent.TimeUnit; |
50 | 51 |
51 public class DartReconcilingStrategyTest extends TestCase { | 52 public class DartReconcilingStrategyTest extends TestCase { |
52 | 53 |
53 /** | 54 /** |
54 * Content cache that can wait for contents to be set. | 55 * Content cache that can wait for contents to be set. |
55 * | 56 * |
56 * @see #expectSetContentsFor(Source) | 57 * @see #expectSetContentsFor(Source) |
57 * @see #waitForSetContents(Source, long) | 58 * @see #waitForSetContents(Source, long) |
58 */ | 59 */ |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 219 } |
219 priorityOrderLatch = null; | 220 priorityOrderLatch = null; |
220 return priorityOrder; | 221 return priorityOrder; |
221 } | 222 } |
222 } | 223 } |
223 | 224 |
224 /** | 225 /** |
225 * Mock editor for testing {@link DartReconcilingStrategy} | 226 * Mock editor for testing {@link DartReconcilingStrategy} |
226 */ | 227 */ |
227 private final class MockEditor implements DartReconcilingEditor { | 228 private final class MockEditor implements DartReconcilingEditor { |
228 private CountDownLatch appliedLatch = null; | 229 private Semaphore applied = null; |
229 private CompilationUnit appliedUnit = null; | 230 private CompilationUnit appliedUnit = null; |
230 private DisposeListener disposeListener = null; | 231 private DisposeListener disposeListener = null; |
231 private FocusListener focusListener = null; | 232 private FocusListener focusListener = null; |
232 | 233 |
233 @Override | 234 @Override |
234 public void addViewerDisposeListener(DisposeListener listener) { | 235 public void addViewerDisposeListener(DisposeListener listener) { |
235 if (disposeListener != null) { | 236 if (disposeListener != null) { |
236 throw new RuntimeException("dispose listener already added"); | 237 throw new RuntimeException("dispose listener already added"); |
237 } | 238 } |
238 disposeListener = listener; | 239 disposeListener = listener; |
239 } | 240 } |
240 | 241 |
241 @Override | 242 @Override |
242 public void addViewerFocusListener(FocusListener listener) { | 243 public void addViewerFocusListener(FocusListener listener) { |
243 if (focusListener != null) { | 244 if (focusListener != null) { |
244 throw new RuntimeException("focus listener already added"); | 245 throw new RuntimeException("focus listener already added"); |
245 } | 246 } |
246 focusListener = listener; | 247 focusListener = listener; |
247 } | 248 } |
248 | 249 |
249 @Override | 250 @Override |
250 public void applyCompilationUnitElement(CompilationUnit unit) { | 251 public void applyCompilationUnitElement(CompilationUnit unit) { |
251 appliedUnit = unit; | 252 appliedUnit = unit; |
252 if (appliedLatch != null) { | 253 if (applied != null) { |
253 appliedLatch.countDown(); | 254 applied.release(); |
254 } | 255 } |
255 } | 256 } |
256 | 257 |
257 public void expectApply() { | 258 public void expectApply() { |
258 appliedLatch = new CountDownLatch(1); | 259 applied = new Semaphore(0); |
259 appliedUnit = null; | 260 appliedUnit = null; |
260 } | 261 } |
261 | 262 |
262 public DisposeListener getDisposeListener() { | 263 public DisposeListener getDisposeListener() { |
263 return disposeListener; | 264 return disposeListener; |
264 } | 265 } |
265 | 266 |
266 @Override | 267 @Override |
267 public AnalysisContext getInputAnalysisContext() { | 268 public AnalysisContext getInputAnalysisContext() { |
268 return mockContext; | 269 return mockContext; |
269 } | 270 } |
270 | 271 |
271 @Override | 272 @Override |
272 public Project getInputProject() { | 273 public Project getInputProject() { |
273 // TODO (danrubel): test null and non-null project | 274 // TODO (danrubel): test null and non-null project |
274 return null; | 275 return null; |
275 } | 276 } |
276 | 277 |
277 @Override | 278 @Override |
278 public Source getInputSource() { | 279 public Source getInputSource() { |
279 return mockSource; | 280 return mockSource; |
280 } | 281 } |
281 | 282 |
282 @Override | 283 @Override |
283 public String getTitle() { | 284 public String getTitle() { |
284 return mockSource.getShortName(); | 285 return mockSource.getShortName(); |
285 } | 286 } |
286 | 287 |
287 public CompilationUnit waitForApply(long milliseconds, boolean expectAnother
) { | 288 public CompilationUnit waitForApply(long milliseconds) { |
288 if (appliedLatch == null) { | 289 if (applied == null) { |
289 throw new IllegalStateException("Call expectApply"); | 290 throw new IllegalStateException("Call expectApply"); |
290 } | 291 } |
291 try { | 292 try { |
292 assertTrue(appliedLatch.await(milliseconds, TimeUnit.MILLISECONDS)); | 293 assertTrue(applied.tryAcquire(milliseconds, TimeUnit.MILLISECONDS)); |
293 } catch (InterruptedException e) { | 294 } catch (InterruptedException e) { |
294 assertEquals(0, appliedLatch.getCount()); | 295 assertTrue(applied.tryAcquire()); |
295 } | 296 } |
296 appliedLatch = expectAnother ? new CountDownLatch(1) : null; | |
297 return appliedUnit; | 297 return appliedUnit; |
298 } | 298 } |
299 } | 299 } |
300 | 300 |
301 private final static String EOL = System.getProperty("line.separator", "\n"); | 301 private final static String EOL = System.getProperty("line.separator", "\n"); |
302 private static final String INITIAL_CONTENTS = Joiner.on(EOL).join(// | 302 private static final String INITIAL_CONTENTS = Joiner.on(EOL).join(// |
303 "library a;", | 303 "library a;", |
304 "class A { foo() => 'two'; }"); | 304 "class A { foo() => 'two'; }"); |
305 | 305 |
306 MockEditor mockEditor = new MockEditor(); | 306 MockEditor mockEditor = new MockEditor(); |
(...skipping 21 matching lines...) Expand all Loading... |
328 /** | 328 /** |
329 * Assert unit resolved, applied, and order set during initialReconcile | 329 * Assert unit resolved, applied, and order set during initialReconcile |
330 */ | 330 */ |
331 public void test_initialReconcile() { | 331 public void test_initialReconcile() { |
332 mockEditor.expectApply(); | 332 mockEditor.expectApply(); |
333 mockContext.expectResolved(mockSource); | 333 mockContext.expectResolved(mockSource); |
334 mockContext.expectSetPriorityOrder(); | 334 mockContext.expectSetPriorityOrder(); |
335 | 335 |
336 strategy.initialReconcile(); | 336 strategy.initialReconcile(); |
337 | 337 |
338 assertNotNull(mockEditor.waitForApply(5000, true)); | 338 assertNotNull(mockEditor.waitForApply(5000)); |
339 CompilationUnit unit = mockContext.waitForResolution(mockSource, 5000); | 339 CompilationUnit unit = mockContext.waitForResolution(mockSource, 5000); |
340 assertNotNull(unit); | 340 assertNotNull(unit); |
341 assertSame(unit, mockEditor.waitForApply(5000, false)); | 341 unit = mockEditor.waitForApply(5000); |
342 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(5000); | 342 assertNotNull(unit); |
| 343 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(15000); |
343 assertEquals(1, priorityOrder.size()); | 344 assertEquals(1, priorityOrder.size()); |
344 assertSame(mockSource, priorityOrder.get(0)); | 345 assertSame(mockSource, priorityOrder.get(0)); |
345 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); | 346 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); |
346 } | 347 } |
347 | 348 |
348 /** | 349 /** |
349 * Assert unit resolved, applied, and order set during initialReconcile after
AST has been removed | 350 * Assert unit resolved, applied, and order set during initialReconcile after
AST has been removed |
350 * from the cache | 351 * from the cache |
351 */ | 352 */ |
352 public void test_initialReconcile_afterFlush() throws Exception { | 353 public void test_initialReconcile_afterFlush() throws Exception { |
353 assertNotNull(mockContext.resolveCompilationUnit(mockSource, mockSource)); | 354 assertNotNull(mockContext.resolveCompilationUnit(mockSource, mockSource)); |
354 mockContext.flushCompilationUnit(mockSource); | 355 mockContext.flushCompilationUnit(mockSource); |
355 assertNull(mockContext.getResolvedCompilationUnit(mockSource, mockSource)); | 356 assertNull(mockContext.getResolvedCompilationUnit(mockSource, mockSource)); |
356 | 357 |
357 mockEditor.expectApply(); | 358 mockEditor.expectApply(); |
358 mockContext.expectResolved(mockSource); | 359 mockContext.expectResolved(mockSource); |
359 mockContext.expectSetPriorityOrder(); | 360 mockContext.expectSetPriorityOrder(); |
360 | 361 |
361 strategy.initialReconcile(); | 362 strategy.initialReconcile(); |
362 | 363 |
363 assertNotNull(mockEditor.waitForApply(5000, true)); | 364 assertNotNull(mockEditor.waitForApply(5000)); |
364 CompilationUnit unit = mockContext.waitForResolution(mockSource, 5000); | 365 CompilationUnit unit = mockContext.waitForResolution(mockSource, 5000); |
365 assertNotNull(unit); | 366 assertNotNull(unit); |
366 assertSame(unit, mockEditor.waitForApply(5000, false)); | 367 unit = mockEditor.waitForApply(5000); |
367 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(5000); | 368 assertNotNull(unit); |
| 369 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(15000); |
368 assertEquals(1, priorityOrder.size()); | 370 assertEquals(1, priorityOrder.size()); |
369 assertSame(mockSource, priorityOrder.get(0)); | 371 assertSame(mockSource, priorityOrder.get(0)); |
370 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); | 372 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); |
371 } | 373 } |
372 | 374 |
373 /** | 375 /** |
374 * Assert unit resolved, applied, and order set during initialReconcile | 376 * Assert unit resolved, applied, and order set during initialReconcile |
375 */ | 377 */ |
376 public void test_initialReconcile_alreadyCached() throws Exception { | 378 public void test_initialReconcile_alreadyCached() throws Exception { |
377 CompilationUnit unit = mockContext.resolveCompilationUnit(mockSource, mockSo
urce); | 379 CompilationUnit unit = mockContext.resolveCompilationUnit(mockSource, mockSo
urce); |
378 assertNotNull(unit); | 380 assertNotNull(unit); |
379 mockEditor.expectApply(); | 381 mockEditor.expectApply(); |
380 mockContext.expectResolved(mockSource); | 382 mockContext.expectResolved(mockSource); |
381 mockContext.expectSetPriorityOrder(); | 383 mockContext.expectSetPriorityOrder(); |
382 | 384 |
383 strategy.initialReconcile(); | 385 strategy.initialReconcile(); |
384 | 386 |
385 assertSame(unit, mockEditor.waitForApply(5000, false)); | 387 assertSame(unit, mockEditor.waitForApply(5000)); |
386 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(5000); | 388 List<Source> priorityOrder = mockContext.waitForSetPriorityOrder(5000); |
387 assertEquals(1, priorityOrder.size()); | 389 assertEquals(1, priorityOrder.size()); |
388 assertSame(mockSource, priorityOrder.get(0)); | 390 assertSame(mockSource, priorityOrder.get(0)); |
389 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); | 391 mockContext.assertPrioritySetBeforeBackgroundAnalysis(); |
390 } | 392 } |
391 | 393 |
392 /** | 394 /** |
393 * Assert editor with no context does not throw exception | 395 * Assert editor with no context does not throw exception |
394 */ | 396 */ |
395 public void test_initialReconcile_nullContext() { | 397 public void test_initialReconcile_nullContext() { |
(...skipping 15 matching lines...) Expand all Loading... |
411 } | 413 } |
412 | 414 |
413 /** | 415 /** |
414 * Assert that a document change clears the cached unit and a resolve resets i
t | 416 * Assert that a document change clears the cached unit and a resolve resets i
t |
415 */ | 417 */ |
416 public void test_reconcileDirtyRegionIRegion() throws Exception { | 418 public void test_reconcileDirtyRegionIRegion() throws Exception { |
417 String newText = "//comment\n"; | 419 String newText = "//comment\n"; |
418 | 420 |
419 mockEditor.expectApply(); | 421 mockEditor.expectApply(); |
420 strategy.initialReconcile(); | 422 strategy.initialReconcile(); |
421 assertNotNull(mockEditor.waitForApply(5000, false)); | 423 assertNotNull(mockEditor.waitForApply(5000)); |
422 | 424 |
423 mockEditor.expectApply(); | 425 mockEditor.expectApply(); |
424 mockDocument.replace(0, 0, newText); | 426 mockDocument.replace(0, 0, newText); |
425 assertNull(mockEditor.waitForApply(5000, false)); | 427 assertNull(mockEditor.waitForApply(5000)); |
426 | 428 |
427 mockEditor.expectApply(); | 429 mockEditor.expectApply(); |
428 strategy.reconcile(new DirtyRegion(0, 0, DirtyRegion.INSERT, newText), new R
egion(0, 0)); | 430 strategy.reconcile(new DirtyRegion(0, 0, DirtyRegion.INSERT, newText), new R
egion(0, 0)); |
429 CompilationUnit unit = mockEditor.waitForApply(5000, false); | 431 CompilationUnit unit = mockEditor.waitForApply(5000); |
430 assertNotNull(unit); | 432 assertNotNull(unit); |
431 } | 433 } |
432 | 434 |
433 /** | 435 /** |
434 * Assert editor with no context does not throw exception | 436 * Assert editor with no context does not throw exception |
435 */ | 437 */ |
436 public void test_reconcileDirtyRegionIRegion_nullContext() throws Exception { | 438 public void test_reconcileDirtyRegionIRegion_nullContext() throws Exception { |
437 String newText = "//comment\n"; | 439 String newText = "//comment\n"; |
438 | 440 |
439 mockContext = null; | 441 mockContext = null; |
440 strategy.initialReconcile(); | 442 strategy.initialReconcile(); |
441 mockDocument.replace(0, 0, newText); | 443 mockDocument.replace(0, 0, newText); |
442 strategy.reconcile(new DirtyRegion(0, 0, DirtyRegion.INSERT, newText), new R
egion(0, 0)); | 444 strategy.reconcile(new DirtyRegion(0, 0, DirtyRegion.INSERT, newText), new R
egion(0, 0)); |
443 | 445 |
444 // test infrastructure asserts no exceptions | 446 // test infrastructure asserts no exceptions |
445 } | 447 } |
446 | 448 |
447 public void test_reconcileIRegion() throws Exception { | 449 public void test_reconcileIRegion() throws Exception { |
448 String newText = "//comment\n"; | 450 String newText = "//comment\n"; |
449 | 451 |
450 mockEditor.expectApply(); | 452 mockEditor.expectApply(); |
451 strategy.initialReconcile(); | 453 strategy.initialReconcile(); |
452 assertNotNull(mockEditor.waitForApply(5000, false)); | 454 assertNotNull(mockEditor.waitForApply(5000)); |
453 | 455 |
454 mockEditor.expectApply(); | 456 mockEditor.expectApply(); |
455 mockDocument.replace(0, 0, newText); | 457 mockDocument.replace(0, 0, newText); |
456 assertNull(mockEditor.waitForApply(5000, false)); | 458 assertNull(mockEditor.waitForApply(5000)); |
457 | 459 |
458 mockEditor.expectApply(); | 460 mockEditor.expectApply(); |
459 strategy.reconcile(new Region(0, newText.length())); | 461 strategy.reconcile(new Region(0, newText.length())); |
460 CompilationUnit unit = mockEditor.waitForApply(5000, false); | 462 CompilationUnit unit = mockEditor.waitForApply(5000); |
461 assertNotNull(unit); | 463 assertNotNull(unit); |
462 } | 464 } |
463 | 465 |
464 /** | 466 /** |
465 * Assert editor with no context does not throw exception | 467 * Assert editor with no context does not throw exception |
466 */ | 468 */ |
467 public void test_reconcileIRegion_nullContext() throws Exception { | 469 public void test_reconcileIRegion_nullContext() throws Exception { |
468 String newText = "//comment\n"; | 470 String newText = "//comment\n"; |
469 | 471 |
470 mockContext = null; | 472 mockContext = null; |
(...skipping 17 matching lines...) Expand all Loading... |
488 } | 490 } |
489 | 491 |
490 @Override | 492 @Override |
491 protected void tearDown() throws Exception { | 493 protected void tearDown() throws Exception { |
492 // Ensure that strategy removes its AnalysisWorker listener | 494 // Ensure that strategy removes its AnalysisWorker listener |
493 if (strategy != null) { | 495 if (strategy != null) { |
494 strategy.dispose(); | 496 strategy.dispose(); |
495 } | 497 } |
496 } | 498 } |
497 } | 499 } |
OLD | NEW |