| 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 |