Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: pkg/analysis_server/test/domain_completion_test.dart

Issue 744043002: discard code completion cache if context or other sources change (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merge Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/analysis_server/lib/src/domain_completion.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library test.domain.completion; 5 library test.domain.completion;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:analysis_server/src/analysis_server.dart';
9 import 'package:analysis_server/src/constants.dart'; 10 import 'package:analysis_server/src/constants.dart';
11 import 'package:analysis_server/src/domain_analysis.dart';
10 import 'package:analysis_server/src/domain_completion.dart'; 12 import 'package:analysis_server/src/domain_completion.dart';
11 import 'package:analysis_server/src/protocol.dart'; 13 import 'package:analysis_server/src/protocol.dart';
14 import 'package:analysis_server/src/services/completion/completion_manager.dart' ;
12 import 'package:analysis_server/src/services/index/index.dart' show Index; 15 import 'package:analysis_server/src/services/index/index.dart' show Index;
13 import 'package:analysis_server/src/services/index/local_memory_index.dart'; 16 import 'package:analysis_server/src/services/index/local_memory_index.dart';
17 import 'package:analysis_server/src/services/search/search_engine.dart';
18 import 'package:analyzer/src/generated/engine.dart';
19 import 'package:analyzer/src/generated/source.dart';
14 import 'package:unittest/unittest.dart'; 20 import 'package:unittest/unittest.dart';
15 21
16 import 'analysis_abstract.dart'; 22 import 'analysis_abstract.dart';
17 import 'mocks.dart'; 23 import 'mocks.dart';
18 import 'reflective_tests.dart'; 24 import 'reflective_tests.dart';
19 25
20 main() { 26 main() {
21 groupSep = ' | '; 27 groupSep = ' | ';
28 runReflectiveTests(CompletionCacheTest);
22 runReflectiveTests(CompletionTest); 29 runReflectiveTests(CompletionTest);
23 } 30 }
24 31
25 @ReflectiveTestCase() 32 @ReflectiveTestCase()
33 class CompletionCacheTest extends AbstractAnalysisTest {
34 AnalysisDomainHandler analysisDomain;
35
36 @override
37 void setUp() {
38 super.setUp();
39 createProject();
40 analysisDomain = handler;
41 handler = new Test_CompletionDomainHandler(server);
42 }
43
44 void tearDown() {
45 super.tearDown();
46 analysisDomain = null;
47 }
48
49 test_cache() {
50 Test_CompletionDomainHandler target = handler;
51 addTestFile('^library A; cl');
52 Request request =
53 new CompletionGetSuggestionsParams(testFile, 0).toRequest('0');
54
55 /*
56 * Assert cache is created by manager
57 * and context.onSourceChanged listen is called
58 */
59 Source source;
60 var expectedCache = null;
61 handleSuccessfulRequest(request);
62 return pumpEventQueue().then((_) {
63 expect(identical(target.cacheReceived, expectedCache), isTrue);
64 expect(target.completionManager.computeCallCount, 1);
65 source = target.completionManager.source;
66 expect(source, isNotNull);
67 expectedCache = target.completionManager.cache;
68 expect(expectedCache, isNotNull);
69 expect(target.mockContext.mockStream.listenCount, 1);
70 expect(target.mockContext.mockStream.cancelCount, 0);
71
72 /*
73 * Assert cache is stored in target,
74 * and context.onSourceChanged listen has not changed
75 */
76 handleSuccessfulRequest(request);
77 return pumpEventQueue();
78 }).then((_) {
79 expect(identical(target.cacheReceived, expectedCache), isTrue);
80 expect(target.completionManager.computeCallCount, 1);
81 expect(target.mockContext.mockStream.listenCount, 1);
82 expect(target.mockContext.mockStream.cancelCount, 0);
83
84 /*
85 * Assert same cache and listening is preserved across multiple calls
86 */
87 handleSuccessfulRequest(request);
88 return pumpEventQueue();
89 }).then((_) {
90 expect(identical(target.cacheReceived, expectedCache), isTrue);
91 expect(target.completionManager.computeCallCount, 1);
92 expect(target.mockContext.mockStream.listenCount, 1);
93 expect(target.mockContext.mockStream.cancelCount, 0);
94
95 /*
96 * Trigger source change event that should NOT clear existing cache
97 */
98 target.sourcesChanged(new SourcesChangedEvent.changedContent(source, ''));
99 }).then((_) {
100
101 handleSuccessfulRequest(request);
102 return pumpEventQueue();
103 }).then((_) {
104 expect(identical(target.cacheReceived, expectedCache), isTrue);
105 expect(target.completionManager.computeCallCount, 1);
106 expect(target.mockContext.mockStream.listenCount, 1);
107 expect(target.mockContext.mockStream.cancelCount, 0);
108
109 /*
110 * Trigger source change event that should clear existing cache
111 * and assert subscription.cancel is called when the cache is discarded.
112 */
113 ChangeSet changeSet = new ChangeSet();
114 changeSet.removedSource(source);
115 target.sourcesChanged(new SourcesChangedEvent(changeSet));
116 }).then((_) {
117 expect(target.mockContext.mockStream.listenCount, 1);
118 expect(target.mockContext.mockStream.cancelCount, 1);
119
120 /*
121 * Assert that cache was cleared, recreated,
122 * and context.onSourceChanged listen is called again.
123 */
124 expectedCache = null;
125 handleSuccessfulRequest(request);
126 return pumpEventQueue();
127 }).then((_) {
128 expect(identical(target.cacheReceived, expectedCache), isTrue);
129 expectedCache = target.completionManager.cache;
130 expect(expectedCache, isNotNull);
131 expect(target.completionManager.computeCallCount, 1);
132 expect(target.mockContext.mockStream.listenCount, 2);
133 expect(target.mockContext.mockStream.cancelCount, 1);
134
135 /*
136 * Assert same cache and listening is preserved across multiple calls
137 */
138 handleSuccessfulRequest(request);
139 return pumpEventQueue();
140 }).then((_) {
141 expect(identical(target.cacheReceived, expectedCache), isTrue);
142 expect(target.completionManager.computeCallCount, 1);
143 expect(target.mockContext.mockStream.listenCount, 2);
144 expect(target.mockContext.mockStream.cancelCount, 1);
145
146 /*
147 * Trigger context change event that should clear existing cache
148 */
149 Request request =
150 new AnalysisSetAnalysisRootsParams([], []).toRequest('0');
151 Response response = analysisDomain.handleRequest(request);
152 expect(response, isResponseSuccess('0'));
153 return pumpEventQueue();
154 }).then((_) {
155 expect(target.mockContext.mockStream.listenCount, 2);
156 expect(target.mockContext.mockStream.cancelCount, 2);
157
158 /*
159 * Assert that cache was cleared, recreated,
160 * and context.onSourceChanged listen is called again.
161 */
162 expectedCache = null;
163 handleSuccessfulRequest(request);
164 return pumpEventQueue();
165 }).then((_) {
166 expect(identical(target.cacheReceived, expectedCache), isTrue);
167 expectedCache = target.completionManager.cache;
168 expect(expectedCache, isNotNull);
169 expect(target.completionManager.computeCallCount, 1);
170 expect(target.mockContext.mockStream.listenCount, 3);
171 expect(target.mockContext.mockStream.cancelCount, 2);
172 });
173 }
174 }
175
176 @ReflectiveTestCase()
26 class CompletionTest extends AbstractAnalysisTest { 177 class CompletionTest extends AbstractAnalysisTest {
27 String completionId; 178 String completionId;
28 int completionOffset; 179 int completionOffset;
29 int replacementOffset; 180 int replacementOffset;
30 int replacementLength; 181 int replacementLength;
31 List<CompletionSuggestion> suggestions = []; 182 List<CompletionSuggestion> suggestions = [];
32 bool suggestionsDone = false; 183 bool suggestionsDone = false;
33 184
34 String addTestFile(String content) { 185 String addTestFile(String content) {
35 completionOffset = content.indexOf('^'); 186 completionOffset = content.indexOf('^');
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 '''); 355 ''');
205 return getSuggestions().then((_) { 356 return getSuggestions().then((_) {
206 expect(replacementOffset, equals(completionOffset - 3)); 357 expect(replacementOffset, equals(completionOffset - 3));
207 expect(replacementLength, equals(4)); 358 expect(replacementLength, equals(4));
208 assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object'); 359 assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
209 assertHasResult(CompletionSuggestionKind.INVOCATION, 'test'); 360 assertHasResult(CompletionSuggestionKind.INVOCATION, 'test');
210 assertNoResult('HtmlElement'); 361 assertNoResult('HtmlElement');
211 }); 362 });
212 } 363 }
213 } 364 }
365
366 class MockCache extends CompletionCache {
367 MockCache(AnalysisContext context, Source source) : super(context, source);
368 }
369
370 class MockCompletionManager implements CompletionManager {
371 final AnalysisContext context;
372 final Source source;
373 final int offset;
374 final SearchEngine searchEngine;
375 CompletionCache cache;
376 CompletionPerformance performance;
377 StreamController<CompletionResult> controller;
378 int computeCallCount = 0;
379
380 MockCompletionManager(this.context, this.source, this.offset,
381 this.searchEngine, this.cache, this.performance);
382
383 @override
384 CompletionCache get completionCache {
385 if (cache == null) {
386 cache = new MockCache(context, source);
387 }
388 return cache;
389 }
390
391 @override
392 void compute() {
393 ++computeCallCount;
394 CompletionResult result = new CompletionResult(0, 0, [], true);
395 controller.add(result);
396 }
397
398 @override
399 Stream<CompletionResult> results() {
400 controller = new StreamController<CompletionResult>(onListen: () {
401 scheduleMicrotask(compute);
402 });
403 return controller.stream;
404 }
405 }
406
407 /**
408 * Mock [AnaysisContext] for tracking usage of onSourcesChanged.
409 */
410 class MockContext implements AnalysisContext {
411 MockStream<SourcesChangedEvent> mockStream;
412
413 MockContext() {
414 mockStream = new MockStream<SourcesChangedEvent>();
415 }
416
417 @override
418 Stream<SourcesChangedEvent> get onSourcesChanged => mockStream;
419
420 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
421 }
422
423 /**
424 * Mock stream for tracking calls to listen and subscription.cancel.
425 */
426 class MockStream<E> implements Stream<E> {
427 MockSubscription<E> mockSubscription = new MockSubscription<E>();
428 int listenCount = 0;
429
430 int get cancelCount => mockSubscription.cancelCount;
431
432 @override
433 StreamSubscription<E> listen(void onData(E event), {Function onError, void
434 onDone(), bool cancelOnError}) {
435 ++listenCount;
436 return mockSubscription;
437 }
438
439 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
440 }
441
442 /**
443 * Mock subscription for tracking calls to subscription.cancel.
444 */
445 class MockSubscription<E> implements StreamSubscription<E> {
446 int cancelCount = 0;
447
448 Future cancel() {
449 ++cancelCount;
450 return new Future.value(true);
451 }
452
453 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
454 }
455
456 /**
457 * A [CompletionDomainHandler] subclass that returns a mock completion manager
458 * so that the domain handler cache management can be tested.
459 */
460 class Test_CompletionDomainHandler extends CompletionDomainHandler {
461 CompletionCache cacheReceived;
462 final MockContext mockContext = new MockContext();
463 MockCompletionManager completionManager;
464
465 Test_CompletionDomainHandler(AnalysisServer server) : super(server);
466
467 void contextsChanged(ContextsChangedEvent event) {
468 if (event.removed.length == 1) {
469 event = new ContextsChangedEvent(
470 added: event.added,
471 changed: event.changed,
472 removed: [mockContext]);
473 }
474 super.contextsChanged(event);
475 }
476
477 CompletionManager createCompletionManager(AnalysisContext context,
478 Source source, int offset, SearchEngine searchEngine, CompletionCache cach e,
479 CompletionPerformance performance) {
480 cacheReceived = cache;
481 completionManager = new MockCompletionManager(
482 mockContext,
483 source,
484 offset,
485 searchEngine,
486 cache,
487 performance);
488 return completionManager;
489 }
490 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/domain_completion.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698