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

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

Issue 723263004: make completion managers responsible for their own caches (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merge Created 6 years 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
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/analysis_server.dart';
10 import 'package:analysis_server/src/channel/channel.dart';
10 import 'package:analysis_server/src/constants.dart'; 11 import 'package:analysis_server/src/constants.dart';
11 import 'package:analysis_server/src/domain_analysis.dart'; 12 import 'package:analysis_server/src/domain_analysis.dart';
12 import 'package:analysis_server/src/domain_completion.dart'; 13 import 'package:analysis_server/src/domain_completion.dart';
13 import 'package:analysis_server/src/protocol.dart'; 14 import 'package:analysis_server/src/protocol.dart';
14 import 'package:analysis_server/src/services/completion/completion_manager.dart' ; 15 import 'package:analysis_server/src/services/completion/completion_manager.dart' ;
15 import 'package:analysis_server/src/services/index/index.dart' show Index; 16 import 'package:analysis_server/src/services/index/index.dart' show Index;
16 import 'package:analysis_server/src/services/index/local_memory_index.dart'; 17 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:analysis_server/src/services/search/search_engine.dart';
19 import 'package:analyzer/file_system/file_system.dart';
20 import 'package:analyzer/source/package_map_provider.dart';
18 import 'package:analyzer/src/generated/engine.dart'; 21 import 'package:analyzer/src/generated/engine.dart';
22 import 'package:analyzer/src/generated/sdk.dart';
19 import 'package:analyzer/src/generated/source.dart'; 23 import 'package:analyzer/src/generated/source.dart';
20 import 'package:unittest/unittest.dart'; 24 import 'package:unittest/unittest.dart';
21 25
22 import 'analysis_abstract.dart'; 26 import 'analysis_abstract.dart';
27 import 'mock_sdk.dart';
23 import 'mocks.dart'; 28 import 'mocks.dart';
24 import 'reflective_tests.dart'; 29 import 'reflective_tests.dart';
25 30
26 main() { 31 main() {
27 groupSep = ' | '; 32 groupSep = ' | ';
28 runReflectiveTests(CompletionCacheTest); 33 runReflectiveTests(CompletionManagerTest);
29 runReflectiveTests(CompletionTest); 34 runReflectiveTests(CompletionTest);
30 } 35 }
31 36
32 @ReflectiveTestCase() 37 @ReflectiveTestCase()
33 class CompletionCacheTest extends AbstractAnalysisTest { 38 class CompletionManagerTest extends AbstractAnalysisTest {
34 AnalysisDomainHandler analysisDomain; 39 AnalysisDomainHandler analysisDomain;
40 Test_CompletionDomainHandler completionDomain;
41 Request request;
42 int requestCount = 0;
43 String testFile2 = '/project/bin/test2.dart';
44
45 AnalysisServer createAnalysisServer(Index index) {
46 return new Test_AnalysisServer(
47 super.serverChannel,
48 super.resourceProvider,
49 super.packageMapProvider,
50 index,
51 new AnalysisServerOptions(),
52 new MockSdk());
53 }
54
55 void sendRequest(String path) {
56 String id = (++requestCount).toString();
57 request = new CompletionGetSuggestionsParams(path, 0).toRequest(id);
58 Response response = handler.handleRequest(request);
59 expect(response, isResponseSuccess(id));
60 }
35 61
36 @override 62 @override
37 void setUp() { 63 void setUp() {
38 super.setUp(); 64 super.setUp();
39 createProject(); 65 createProject();
40 analysisDomain = handler; 66 analysisDomain = handler;
41 handler = new Test_CompletionDomainHandler(server); 67 completionDomain = new Test_CompletionDomainHandler(server);
68 handler = completionDomain;
69 addTestFile('^library A; cl');
70 addFile(testFile2, 'library B; cl');
42 } 71 }
43 72
44 void tearDown() { 73 void tearDown() {
45 super.tearDown(); 74 super.tearDown();
46 analysisDomain = null; 75 analysisDomain = null;
47 } 76 completionDomain = null;
48 77 }
49 test_cache() { 78
50 Test_CompletionDomainHandler target = handler; 79 /**
51 addTestFile('^library A; cl'); 80 * Assert different managers are used for different sources
52 Request request = 81 */
53 new CompletionGetSuggestionsParams(testFile, 0).toRequest('0'); 82 test_2_requests_different_sources() {
54 83 expect(completionDomain.manager, isNull);
55 /* 84 sendRequest(testFile);
56 * Assert cache is created by manager 85 expect(completionDomain.manager, isNotNull);
57 * and context.onSourceChanged listen is called 86 CompletionManager expectedManager = completionDomain.manager;
58 */ 87 expect(completionDomain.mockContext.mockStream.listenCount, 1);
59 Source source; 88 expect(completionDomain.mockContext.mockStream.cancelCount, 0);
60 var expectedCache = null; 89 return pumpEventQueue().then((_) {
61 handleSuccessfulRequest(request); 90 expect(completionDomain.manager, expectedManager);
62 return pumpEventQueue().then((_) { 91 expect(completionDomain.mockManager.computeCallCount, 1);
63 expect(identical(target.cacheReceived, expectedCache), isTrue); 92 sendRequest(testFile2);
64 expect(target.completionManager.computeCallCount, 1); 93 expect(completionDomain.manager, isNotNull);
65 source = target.completionManager.source; 94 expect(completionDomain.manager, isNot(expectedManager));
66 expect(source, isNotNull); 95 expectedManager = completionDomain.manager;
67 expectedCache = target.completionManager.cache; 96 expect(completionDomain.mockContext.mockStream.listenCount, 2);
68 expect(expectedCache, isNotNull); 97 expect(completionDomain.mockContext.mockStream.cancelCount, 1);
69 expect(target.mockContext.mockStream.listenCount, 1); 98 return pumpEventQueue();
70 expect(target.mockContext.mockStream.cancelCount, 0); 99 }).then((_) {
71 100 expect(completionDomain.manager, expectedManager);
72 /* 101 expect(completionDomain.mockContext.mockStream.listenCount, 2);
73 * Assert cache is stored in target, 102 expect(completionDomain.mockContext.mockStream.cancelCount, 1);
74 * and context.onSourceChanged listen has not changed 103 expect(completionDomain.mockManager.computeCallCount, 1);
75 */ 104 });
76 handleSuccessfulRequest(request); 105 }
77 return pumpEventQueue(); 106
78 }).then((_) { 107 /**
79 expect(identical(target.cacheReceived, expectedCache), isTrue); 108 * Assert same manager is used for multiple requests on same source
80 expect(target.completionManager.computeCallCount, 1); 109 */
81 expect(target.mockContext.mockStream.listenCount, 1); 110 test_2_requests_same_source() {
82 expect(target.mockContext.mockStream.cancelCount, 0); 111 expect(completionDomain.manager, isNull);
83 112 sendRequest(testFile);
84 /* 113 expect(completionDomain.manager, isNotNull);
85 * Assert same cache and listening is preserved across multiple calls 114 expect(completionDomain.manager.source, isNotNull);
86 */ 115 CompletionManager expectedManager = completionDomain.manager;
87 handleSuccessfulRequest(request); 116 expect(completionDomain.mockContext.mockStream.listenCount, 1);
88 return pumpEventQueue(); 117 expect(completionDomain.mockContext.mockStream.cancelCount, 0);
89 }).then((_) { 118 return pumpEventQueue().then((_) {
90 expect(identical(target.cacheReceived, expectedCache), isTrue); 119 expect(completionDomain.manager, expectedManager);
91 expect(target.completionManager.computeCallCount, 1); 120 expect(completionDomain.mockManager.computeCallCount, 1);
92 expect(target.mockContext.mockStream.listenCount, 1); 121 sendRequest(testFile);
93 expect(target.mockContext.mockStream.cancelCount, 0); 122 expect(completionDomain.manager, expectedManager);
94 123 expect(completionDomain.mockContext.mockStream.listenCount, 1);
95 /* 124 expect(completionDomain.mockContext.mockStream.cancelCount, 0);
96 * Trigger source change event that should NOT clear existing cache 125 return pumpEventQueue();
97 */ 126 }).then((_) {
98 target.sourcesChanged(new SourcesChangedEvent.changedContent(source, '')); 127 expect(completionDomain.manager, expectedManager);
99 }).then((_) { 128 expect(completionDomain.mockContext.mockStream.listenCount, 1);
100 129 expect(completionDomain.mockContext.mockStream.cancelCount, 0);
101 handleSuccessfulRequest(request); 130 expect(completionDomain.mockManager.computeCallCount, 2);
102 return pumpEventQueue(); 131 });
103 }).then((_) { 132 }
104 expect(identical(target.cacheReceived, expectedCache), isTrue); 133
105 expect(target.completionManager.computeCallCount, 1); 134 /**
106 expect(target.mockContext.mockStream.listenCount, 1); 135 * Assert manager is cleared when analysis roots are set
107 expect(target.mockContext.mockStream.cancelCount, 0); 136 */
108 137 test_setAnalysisRoots() {
109 /* 138 sendRequest(testFile);
110 * Trigger source change event that should clear existing cache 139 return pumpEventQueue().then((_) {
111 * and assert subscription.cancel is called when the cache is discarded. 140 expect(completionDomain.manager, isNotNull);
112 */ 141 request = new AnalysisSetAnalysisRootsParams([], []).toRequest('7');
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); 142 Response response = analysisDomain.handleRequest(request);
152 expect(response, isResponseSuccess('0')); 143 expect(response, isResponseSuccess('7'));
153 return pumpEventQueue(); 144 return pumpEventQueue();
154 }).then((_) { 145 }).then((_) {
155 expect(target.mockContext.mockStream.listenCount, 2); 146 expect(completionDomain.manager, isNull);
156 expect(target.mockContext.mockStream.cancelCount, 2); 147 });
157 148 }
158 /* 149
159 * Assert that cache was cleared, recreated, 150 /**
160 * and context.onSourceChanged listen is called again. 151 * Assert manager is NOT cleared when context NOT associated with manager chan ges.
161 */ 152 */
162 expectedCache = null; 153 test_contextsChanged_different() {
163 handleSuccessfulRequest(request); 154 sendRequest(testFile);
164 return pumpEventQueue(); 155 CompletionManager expectedManager;
165 }).then((_) { 156 return pumpEventQueue().then((_) {
166 expect(identical(target.cacheReceived, expectedCache), isTrue); 157 expect(completionDomain.manager, isNotNull);
167 expectedCache = target.completionManager.cache; 158 expectedManager = completionDomain.manager;
168 expect(expectedCache, isNotNull); 159 completionDomain.contextsChangedRaw(
169 expect(target.completionManager.computeCallCount, 1); 160 new ContextsChangedEvent(changed: [new MockContext()]));
170 expect(target.mockContext.mockStream.listenCount, 3); 161 return pumpEventQueue();
171 expect(target.mockContext.mockStream.cancelCount, 2); 162 }).then((_) {
163 expect(completionDomain.manager, expectedManager);
164 });
165 }
166
167 /**
168 * Assert manager is cleared when context associated with manager changes.
169 */
170 test_contextsChanged_same() {
171 sendRequest(testFile);
172 return pumpEventQueue().then((_) {
173 expect(completionDomain.manager, isNotNull);
174 completionDomain.contextsChangedRaw(
175 new ContextsChangedEvent(changed: [completionDomain.mockContext]));
176 return pumpEventQueue();
177 }).then((_) {
178 expect(completionDomain.manager, isNull);
179 });
180 }
181
182 /**
183 * Assert manager is cleared when source NOT associated with manager is change d.
184 */
185 test_sourcesChanged_different_source_changed() {
186 sendRequest(testFile);
187 return pumpEventQueue().then((_) {
188 expect(completionDomain.manager, isNotNull);
189 ChangeSet changeSet = new ChangeSet();
190 changeSet.changedSource(server.getSource(testFile2));
191 completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
192 expect(completionDomain.manager, isNull);
193 });
194 }
195
196 /**
197 * Assert manager is NOT cleared when source associated with manager is change d.
198 */
199 test_sourcesChanged_same_source_changed() {
200 sendRequest(testFile);
201 return pumpEventQueue().then((_) {
202 expect(completionDomain.manager, isNotNull);
203 CompletionManager expectedManager = completionDomain.manager;
204 ChangeSet changeSet = new ChangeSet();
205 changeSet.changedSource(completionDomain.manager.source);
206 completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
207 expect(completionDomain.manager, expectedManager);
208 });
209 }
210
211 /**
212 * Assert manager is cleared when source is deleted
213 */
214 test_sourcesChanged_source_deleted() {
215 sendRequest(testFile);
216 return pumpEventQueue().then((_) {
217 expect(completionDomain.manager, isNotNull);
218 ChangeSet changeSet = new ChangeSet();
219 changeSet.deletedSource(completionDomain.manager.source);
220 completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
221 expect(completionDomain.manager, isNull);
222 });
223 }
224
225 /**
226 * Assert manager is cleared when source is removed
227 */
228 test_sourcesChanged_source_removed() {
229 sendRequest(testFile);
230 return pumpEventQueue().then((_) {
231 expect(completionDomain.manager, isNotNull);
232 ChangeSet changeSet = new ChangeSet();
233 changeSet.removedSource(completionDomain.manager.source);
234 completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
235 expect(completionDomain.manager, isNull);
172 }); 236 });
173 } 237 }
174 } 238 }
175 239
176 @ReflectiveTestCase() 240 @ReflectiveTestCase()
177 class CompletionTest extends AbstractAnalysisTest { 241 class CompletionTest extends AbstractAnalysisTest {
178 String completionId; 242 String completionId;
179 int completionOffset; 243 int completionOffset;
180 int replacementOffset; 244 int replacementOffset;
181 int replacementLength; 245 int replacementLength;
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 } 427 }
364 } 428 }
365 429
366 class MockCache extends CompletionCache { 430 class MockCache extends CompletionCache {
367 MockCache(AnalysisContext context, Source source) : super(context, source); 431 MockCache(AnalysisContext context, Source source) : super(context, source);
368 } 432 }
369 433
370 class MockCompletionManager implements CompletionManager { 434 class MockCompletionManager implements CompletionManager {
371 final AnalysisContext context; 435 final AnalysisContext context;
372 final Source source; 436 final Source source;
373 final int offset;
374 final SearchEngine searchEngine; 437 final SearchEngine searchEngine;
375 CompletionCache cache; 438 CompletionCache cache;
376 CompletionPerformance performance;
377 StreamController<CompletionResult> controller; 439 StreamController<CompletionResult> controller;
378 int computeCallCount = 0; 440 int computeCallCount = 0;
379 441
380 MockCompletionManager(this.context, this.source, this.offset, 442 MockCompletionManager(this.context, this.source, this.searchEngine,
381 this.searchEngine, this.cache, this.performance); 443 this.cache);
382 444
383 @override 445 @override
384 CompletionCache get completionCache { 446 void compute(CompletionRequest request) {
385 if (cache == null) {
386 cache = new MockCache(context, source);
387 }
388 return cache;
389 }
390
391 @override
392 void compute() {
393 ++computeCallCount; 447 ++computeCallCount;
394 CompletionResult result = new CompletionResult(0, 0, [], true); 448 CompletionResult result = new CompletionResult(0, 0, [], true);
395 controller.add(result); 449 controller.add(result);
396 } 450 }
397 451
398 @override 452 @override
399 Stream<CompletionResult> results() { 453 Stream<CompletionResult> results(CompletionRequest request) {
400 controller = new StreamController<CompletionResult>(onListen: () { 454 controller = new StreamController<CompletionResult>(onListen: () {
401 scheduleMicrotask(compute); 455 scheduleMicrotask(() {
456 compute(request);
457 });
402 }); 458 });
403 return controller.stream; 459 return controller.stream;
404 } 460 }
405 } 461 }
406 462
407 /** 463 /**
408 * Mock [AnaysisContext] for tracking usage of onSourcesChanged. 464 * Mock [AnaysisContext] for tracking usage of onSourcesChanged.
409 */ 465 */
410 class MockContext implements AnalysisContext { 466 class MockContext implements AnalysisContext {
411 MockStream<SourcesChangedEvent> mockStream; 467 MockStream<SourcesChangedEvent> mockStream;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 int cancelCount = 0; 502 int cancelCount = 0;
447 503
448 Future cancel() { 504 Future cancel() {
449 ++cancelCount; 505 ++cancelCount;
450 return new Future.value(true); 506 return new Future.value(true);
451 } 507 }
452 508
453 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); 509 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
454 } 510 }
455 511
512 class Test_AnalysisServer extends AnalysisServer {
513 final MockContext mockContext = new MockContext();
514
515 Test_AnalysisServer(ServerCommunicationChannel channel,
516 ResourceProvider resourceProvider, PackageMapProvider packageMapProvider,
517 Index index, AnalysisServerOptions analysisServerOptions, DartSdk defaultS dk)
518 : super(
519 channel,
520 resourceProvider,
521 packageMapProvider,
522 index,
523 analysisServerOptions,
524 defaultSdk);
525
526 AnalysisContext getAnalysisContext(String path) {
527 return mockContext;
528 }
529 }
530
456 /** 531 /**
457 * A [CompletionDomainHandler] subclass that returns a mock completion manager 532 * A [CompletionDomainHandler] subclass that returns a mock completion manager
458 * so that the domain handler cache management can be tested. 533 * so that the domain handler cache management can be tested.
459 */ 534 */
460 class Test_CompletionDomainHandler extends CompletionDomainHandler { 535 class Test_CompletionDomainHandler extends CompletionDomainHandler {
461 CompletionCache cacheReceived;
462 final MockContext mockContext = new MockContext();
463 MockCompletionManager completionManager;
464 536
465 Test_CompletionDomainHandler(AnalysisServer server) : super(server); 537 Test_CompletionDomainHandler(Test_AnalysisServer server) : super(server);
538
539 MockContext get mockContext => (server as Test_AnalysisServer).mockContext;
540
541 MockCompletionManager get mockManager => manager;
466 542
467 void contextsChanged(ContextsChangedEvent event) { 543 void contextsChanged(ContextsChangedEvent event) {
468 if (event.removed.length == 1) { 544 contextsChangedRaw(
469 event = new ContextsChangedEvent( 545 new ContextsChangedEvent(
470 added: event.added, 546 added: event.added.length > 0 ? [mockContext] : [],
471 changed: event.changed, 547 changed: event.changed.length > 0 ? [mockContext] : [],
472 removed: [mockContext]); 548 removed: event.removed.length > 0 ? [mockContext] : []));
473 } 549 }
474 super.contextsChanged(event); 550
551 void contextsChangedRaw(ContextsChangedEvent newEvent) {
552 super.contextsChanged(newEvent);
475 } 553 }
476 554
477 CompletionManager createCompletionManager(AnalysisContext context, 555 CompletionManager createCompletionManager(AnalysisContext context,
478 Source source, int offset, SearchEngine searchEngine, CompletionCache cach e, 556 Source source, SearchEngine searchEngine, CompletionCache cache) {
479 CompletionPerformance performance) { 557 return new MockCompletionManager(mockContext, source, searchEngine, cache);
480 cacheReceived = cache;
481 completionManager = new MockCompletionManager(
482 mockContext,
483 source,
484 offset,
485 searchEngine,
486 cache,
487 performance);
488 return completionManager;
489 } 558 }
490 } 559 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698