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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analysis_server/lib/src/domain_completion.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analysis_server/test/domain_completion_test.dart
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 59d82c55b157cd216288961ee5b8e5f5843200af..a5caa95307b5190f373218a3c13335728d105353 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -6,11 +6,17 @@ library test.domain.completion;
import 'dart:async';
+import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/protocol.dart';
+import 'package:analysis_server/src/services/completion/completion_manager.dart';
import 'package:analysis_server/src/services/index/index.dart' show Index;
import 'package:analysis_server/src/services/index/local_memory_index.dart';
+import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
import 'package:unittest/unittest.dart';
import 'analysis_abstract.dart';
@@ -19,10 +25,155 @@ import 'reflective_tests.dart';
main() {
groupSep = ' | ';
+ runReflectiveTests(CompletionCacheTest);
runReflectiveTests(CompletionTest);
}
@ReflectiveTestCase()
+class CompletionCacheTest extends AbstractAnalysisTest {
+ AnalysisDomainHandler analysisDomain;
+
+ @override
+ void setUp() {
+ super.setUp();
+ createProject();
+ analysisDomain = handler;
+ handler = new Test_CompletionDomainHandler(server);
+ }
+
+ void tearDown() {
+ super.tearDown();
+ analysisDomain = null;
+ }
+
+ test_cache() {
+ Test_CompletionDomainHandler target = handler;
+ addTestFile('^library A; cl');
+ Request request =
+ new CompletionGetSuggestionsParams(testFile, 0).toRequest('0');
+
+ /*
+ * Assert cache is created by manager
+ * and context.onSourceChanged listen is called
+ */
+ Source source;
+ var expectedCache = null;
+ handleSuccessfulRequest(request);
+ return pumpEventQueue().then((_) {
+ expect(identical(target.cacheReceived, expectedCache), isTrue);
+ expect(target.completionManager.computeCallCount, 1);
+ source = target.completionManager.source;
+ expect(source, isNotNull);
+ expectedCache = target.completionManager.cache;
+ expect(expectedCache, isNotNull);
+ expect(target.mockContext.mockStream.listenCount, 1);
+ expect(target.mockContext.mockStream.cancelCount, 0);
+
+ /*
+ * Assert cache is stored in target,
+ * and context.onSourceChanged listen has not changed
+ */
+ handleSuccessfulRequest(request);
+ return pumpEventQueue();
+ }).then((_) {
+ expect(identical(target.cacheReceived, expectedCache), isTrue);
+ expect(target.completionManager.computeCallCount, 1);
+ expect(target.mockContext.mockStream.listenCount, 1);
+ expect(target.mockContext.mockStream.cancelCount, 0);
+
+ /*
+ * Assert same cache and listening is preserved across multiple calls
+ */
+ handleSuccessfulRequest(request);
+ return pumpEventQueue();
+ }).then((_) {
+ expect(identical(target.cacheReceived, expectedCache), isTrue);
+ expect(target.completionManager.computeCallCount, 1);
+ expect(target.mockContext.mockStream.listenCount, 1);
+ expect(target.mockContext.mockStream.cancelCount, 0);
+
+ /*
+ * Trigger source change event that should NOT clear existing cache
+ */
+ target.sourcesChanged(new SourcesChangedEvent.changedContent(source, ''));
+ }).then((_) {
+
+ handleSuccessfulRequest(request);
+ return pumpEventQueue();
+ }).then((_) {
+ expect(identical(target.cacheReceived, expectedCache), isTrue);
+ expect(target.completionManager.computeCallCount, 1);
+ expect(target.mockContext.mockStream.listenCount, 1);
+ expect(target.mockContext.mockStream.cancelCount, 0);
+
+ /*
+ * Trigger source change event that should clear existing cache
+ * and assert subscription.cancel is called when the cache is discarded.
+ */
+ ChangeSet changeSet = new ChangeSet();
+ changeSet.removedSource(source);
+ target.sourcesChanged(new SourcesChangedEvent(changeSet));
+ }).then((_) {
+ expect(target.mockContext.mockStream.listenCount, 1);
+ expect(target.mockContext.mockStream.cancelCount, 1);
+
+ /*
+ * Assert that cache was cleared, recreated,
+ * and context.onSourceChanged listen is called again.
+ */
+ expectedCache = null;
+ handleSuccessfulRequest(request);
+ return pumpEventQueue();
+ }).then((_) {
+ expect(identical(target.cacheReceived, expectedCache), isTrue);
+ expectedCache = target.completionManager.cache;
+ expect(expectedCache, isNotNull);
+ expect(target.completionManager.computeCallCount, 1);
+ expect(target.mockContext.mockStream.listenCount, 2);
+ expect(target.mockContext.mockStream.cancelCount, 1);
+
+ /*
+ * Assert same cache and listening is preserved across multiple calls
+ */
+ handleSuccessfulRequest(request);
+ return pumpEventQueue();
+ }).then((_) {
+ expect(identical(target.cacheReceived, expectedCache), isTrue);
+ expect(target.completionManager.computeCallCount, 1);
+ expect(target.mockContext.mockStream.listenCount, 2);
+ expect(target.mockContext.mockStream.cancelCount, 1);
+
+ /*
+ * Trigger context change event that should clear existing cache
+ */
+ Request request =
+ new AnalysisSetAnalysisRootsParams([], []).toRequest('0');
+ Response response = analysisDomain.handleRequest(request);
+ expect(response, isResponseSuccess('0'));
+ return pumpEventQueue();
+ }).then((_) {
+ expect(target.mockContext.mockStream.listenCount, 2);
+ expect(target.mockContext.mockStream.cancelCount, 2);
+
+ /*
+ * Assert that cache was cleared, recreated,
+ * and context.onSourceChanged listen is called again.
+ */
+ expectedCache = null;
+ handleSuccessfulRequest(request);
+ return pumpEventQueue();
+ }).then((_) {
+ expect(identical(target.cacheReceived, expectedCache), isTrue);
+ expectedCache = target.completionManager.cache;
+ expect(expectedCache, isNotNull);
+ expect(target.completionManager.computeCallCount, 1);
+ expect(target.mockContext.mockStream.listenCount, 3);
+ expect(target.mockContext.mockStream.cancelCount, 2);
+ });
+ }
+}
+
+@ReflectiveTestCase()
class CompletionTest extends AbstractAnalysisTest {
String completionId;
int completionOffset;
@@ -211,3 +362,129 @@ class CompletionTest extends AbstractAnalysisTest {
});
}
}
+
+class MockCache extends CompletionCache {
+ MockCache(AnalysisContext context, Source source) : super(context, source);
+}
+
+class MockCompletionManager implements CompletionManager {
+ final AnalysisContext context;
+ final Source source;
+ final int offset;
+ final SearchEngine searchEngine;
+ CompletionCache cache;
+ CompletionPerformance performance;
+ StreamController<CompletionResult> controller;
+ int computeCallCount = 0;
+
+ MockCompletionManager(this.context, this.source, this.offset,
+ this.searchEngine, this.cache, this.performance);
+
+ @override
+ CompletionCache get completionCache {
+ if (cache == null) {
+ cache = new MockCache(context, source);
+ }
+ return cache;
+ }
+
+ @override
+ void compute() {
+ ++computeCallCount;
+ CompletionResult result = new CompletionResult(0, 0, [], true);
+ controller.add(result);
+ }
+
+ @override
+ Stream<CompletionResult> results() {
+ controller = new StreamController<CompletionResult>(onListen: () {
+ scheduleMicrotask(compute);
+ });
+ return controller.stream;
+ }
+}
+
+/**
+ * Mock [AnaysisContext] for tracking usage of onSourcesChanged.
+ */
+class MockContext implements AnalysisContext {
+ MockStream<SourcesChangedEvent> mockStream;
+
+ MockContext() {
+ mockStream = new MockStream<SourcesChangedEvent>();
+ }
+
+ @override
+ Stream<SourcesChangedEvent> get onSourcesChanged => mockStream;
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+/**
+ * Mock stream for tracking calls to listen and subscription.cancel.
+ */
+class MockStream<E> implements Stream<E> {
+ MockSubscription<E> mockSubscription = new MockSubscription<E>();
+ int listenCount = 0;
+
+ int get cancelCount => mockSubscription.cancelCount;
+
+ @override
+ StreamSubscription<E> listen(void onData(E event), {Function onError, void
+ onDone(), bool cancelOnError}) {
+ ++listenCount;
+ return mockSubscription;
+ }
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+/**
+ * Mock subscription for tracking calls to subscription.cancel.
+ */
+class MockSubscription<E> implements StreamSubscription<E> {
+ int cancelCount = 0;
+
+ Future cancel() {
+ ++cancelCount;
+ return new Future.value(true);
+ }
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+/**
+ * A [CompletionDomainHandler] subclass that returns a mock completion manager
+ * so that the domain handler cache management can be tested.
+ */
+class Test_CompletionDomainHandler extends CompletionDomainHandler {
+ CompletionCache cacheReceived;
+ final MockContext mockContext = new MockContext();
+ MockCompletionManager completionManager;
+
+ Test_CompletionDomainHandler(AnalysisServer server) : super(server);
+
+ void contextsChanged(ContextsChangedEvent event) {
+ if (event.removed.length == 1) {
+ event = new ContextsChangedEvent(
+ added: event.added,
+ changed: event.changed,
+ removed: [mockContext]);
+ }
+ super.contextsChanged(event);
+ }
+
+ CompletionManager createCompletionManager(AnalysisContext context,
+ Source source, int offset, SearchEngine searchEngine, CompletionCache cache,
+ CompletionPerformance performance) {
+ cacheReceived = cache;
+ completionManager = new MockCompletionManager(
+ mockContext,
+ source,
+ offset,
+ searchEngine,
+ cache,
+ performance);
+ return completionManager;
+ }
+}
« 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