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

Side by Side Diff: pkg/analysis_server/test/index/split_store_test.dart

Issue 351453004: Move split_store.dart to the store/ folder and extract collections/codecs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library test.index.split.store;
6
7 import 'dart:async';
8 import 'dart:collection';
9
10 import 'package:analysis_server/src/index/split_store.dart';
11 import 'package:analyzer/src/generated/element.dart';
12 import 'package:analyzer/src/generated/engine.dart';
13 import 'package:analyzer/src/generated/index.dart';
14 import 'package:analyzer/src/generated/source.dart';
15 import 'package:typed_mock/typed_mock.dart';
16 import 'package:unittest/unittest.dart';
17
18 import '../reflective_tests.dart';
19
20
21 main() {
22 groupSep = ' | ';
23 group('ContextCodec', () {
24 runReflectiveTests(_ContextCodecTest);
25 });
26 group('ElementCodec', () {
27 runReflectiveTests(_ElementCodecTest);
28 });
29 group('FileNodeManager', () {
30 runReflectiveTests(_FileNodeManagerTest);
31 });
32 group('IndexNode', () {
33 runReflectiveTests(_IndexNodeTest);
34 });
35 group('IntToIntSetMap', () {
36 runReflectiveTests(_IntToIntSetMapTest);
37 });
38 group('LocationData', () {
39 runReflectiveTests(_LocationDataTest);
40 });
41 group('RelationKeyData', () {
42 runReflectiveTests(_RelationKeyDataTest);
43 });
44 group('RelationshipCodec', () {
45 runReflectiveTests(_RelationshipCodecTest);
46 });
47 group('SplitIndexStore', () {
48 runReflectiveTests(_SplitIndexStoreTest);
49 });
50 group('StringCodec', () {
51 runReflectiveTests(_StringCodecTest);
52 });
53 }
54
55
56 void _assertHasLocation(List<Location> locations, Element element, int offset,
57 int length) {
58 for (Location location in locations) {
59 if ((element == null || location.element == element) && location.offset ==
60 offset && location.length == length) {
61 return;
62 }
63 }
64 fail('Expected to find Location'
65 '(element=$element, offset=$offset, length=$length)');
66 }
67
68
69 @ReflectiveTestCase()
70 class _ContextCodecTest {
71 ContextCodec codec = new ContextCodec();
72
73 void test_encode_decode() {
74 AnalysisContext contextA = new _MockAnalysisContext('contextA');
75 AnalysisContext contextB = new _MockAnalysisContext('contextB');
76 int idA = codec.encode(contextA);
77 int idB = codec.encode(contextB);
78 expect(idA, codec.encode(contextA));
79 expect(idB, codec.encode(contextB));
80 expect(codec.decode(idA), contextA);
81 expect(codec.decode(idB), contextB);
82 }
83
84 void test_remove() {
85 // encode
86 {
87 AnalysisContext context = new _MockAnalysisContext('context');
88 // encode
89 int id = codec.encode(context);
90 expect(id, 0);
91 expect(codec.decode(id), context);
92 // remove
93 codec.remove(context);
94 expect(codec.decode(id), isNull);
95 }
96 // encode again
97 {
98 AnalysisContext context = new _MockAnalysisContext('context');
99 // encode
100 int id = codec.encode(context);
101 expect(id, 1);
102 expect(codec.decode(id), context);
103 }
104 }
105 }
106
107
108 @ReflectiveTestCase()
109 class _ElementCodecTest {
110 ElementCodec codec;
111 AnalysisContext context = new _MockAnalysisContext('context');
112 StringCodec stringCodec = new StringCodec();
113
114 void setUp() {
115 codec = new ElementCodec(stringCodec);
116 }
117
118 void test_localLocalVariable() {
119 {
120 Element element = new _MockElement();
121 ElementLocation location = new ElementLocationImpl.con3(['main', 'foo@1',
122 'bar@2']);
123 when(context.getElement(location)).thenReturn(element);
124 when(element.location).thenReturn(location);
125 int id = codec.encode(element);
126 expect(codec.decode(context, id), element);
127 }
128 {
129 Element element = new _MockElement();
130 ElementLocation location = new ElementLocationImpl.con3(['main', 'foo@10',
131 'bar@20']);
132 when(context.getElement(location)).thenReturn(element);
133 when(element.location).thenReturn(location);
134 int id = codec.encode(element);
135 expect(codec.decode(context, id), element);
136 }
137 // check strings, "foo" as a single string, no "foo@1" or "foo@10"
138 expect(stringCodec.nameToIndex, hasLength(3));
139 expect(stringCodec.nameToIndex, containsPair('main', 0));
140 expect(stringCodec.nameToIndex, containsPair('foo', 1));
141 expect(stringCodec.nameToIndex, containsPair('bar', 2));
142 }
143
144 void test_localVariable() {
145 {
146 Element element = new _MockElement();
147 ElementLocation location = new ElementLocationImpl.con3(['main',
148 'foo@42']);
149 when(context.getElement(location)).thenReturn(element);
150 when(element.location).thenReturn(location);
151 int id = codec.encode(element);
152 expect(codec.decode(context, id), element);
153 }
154 {
155 Element element = new _MockElement();
156 ElementLocation location = new ElementLocationImpl.con3(['main',
157 'foo@4200']);
158 when(context.getElement(location)).thenReturn(element);
159 when(element.location).thenReturn(location);
160 int id = codec.encode(element);
161 expect(codec.decode(context, id), element);
162 }
163 // check strings, "foo" as a single string, no "foo@42" or "foo@4200"
164 expect(stringCodec.nameToIndex, hasLength(2));
165 expect(stringCodec.nameToIndex, containsPair('main', 0));
166 expect(stringCodec.nameToIndex, containsPair('foo', 1));
167 }
168
169 void test_notLocal() {
170 Element element = new _MockElement();
171 ElementLocation location = new ElementLocationImpl.con3(['foo', 'bar']);
172 when(element.location).thenReturn(location);
173 when(context.getElement(location)).thenReturn(element);
174 int id = codec.encode(element);
175 expect(codec.encode(element), id);
176 expect(codec.decode(context, id), element);
177 // check strings
178 expect(stringCodec.nameToIndex, hasLength(2));
179 expect(stringCodec.nameToIndex, containsPair('foo', 0));
180 expect(stringCodec.nameToIndex, containsPair('bar', 1));
181 }
182 }
183
184
185 @ReflectiveTestCase()
186 class _FileNodeManagerTest {
187 AnalysisContext context = new _MockAnalysisContext('context');
188 ContextCodec contextCodec = new _MockContextCodec();
189 int contextId = 13;
190 ElementCodec elementCodec = new _MockElementCodec();
191 FileManager fileManager = new _MockFileManager();
192 _MockLogger logger = new _MockLogger();
193 int nextElementId = 0;
194 FileNodeManager nodeManager;
195 RelationshipCodec relationshipCodec;
196 StringCodec stringCodec = new StringCodec();
197
198 void setUp() {
199 relationshipCodec = new RelationshipCodec(stringCodec);
200 nodeManager = new FileNodeManager(fileManager, logger, stringCodec,
201 contextCodec, elementCodec, relationshipCodec);
202 when(contextCodec.encode(context)).thenReturn(contextId);
203 when(contextCodec.decode(contextId)).thenReturn(context);
204 }
205
206 void test_clear() {
207 nodeManager.clear();
208 verify(fileManager.clear()).once();
209 }
210
211 void test_getLocationCount_empty() {
212 expect(nodeManager.locationCount, 0);
213 }
214
215 void test_getNode_contextNull() {
216 String name = '42.index';
217 // record bytes
218 List<int> bytes;
219 when(fileManager.write(name, anyObject)).thenInvoke((name, bs) {
220 bytes = bs;
221 });
222 // put Node
223 Future putFuture;
224 {
225 IndexNode node = new IndexNode(context, elementCodec, relationshipCodec);
226 putFuture = nodeManager.putNode(name, node);
227 }
228 // do in the "put" Future
229 putFuture.then((_) {
230 // force "null" context
231 when(contextCodec.decode(contextId)).thenReturn(null);
232 // prepare input bytes
233 when(fileManager.read(name)).thenReturn(new Future.value(bytes));
234 // get Node
235 return nodeManager.getNode(name).then((IndexNode node) {
236 expect(node, isNull);
237 // no exceptions
238 verifyZeroInteractions(logger);
239 });
240 });
241 }
242
243 test_getNode_invalidVersion() {
244 String name = '42.index';
245 // prepare a stream with an invalid version
246 when(fileManager.read(name)).thenReturn(new Future.value([0x01, 0x02, 0x03,
247 0x04]));
248 // do in the Future
249 return nodeManager.getNode(name).then((IndexNode node) {
250 // no IndexNode
251 expect(node, isNull);
252 // failed
253 verify(logger.logError2(anyObject, anyObject)).once();
254 });
255 }
256
257 test_getNode_streamException() {
258 String name = '42.index';
259 when(fileManager.read(name)).thenReturn(new Future(() {
260 return throw new Exception();
261 }));
262 // do in the Future
263 return nodeManager.getNode(name).then((IndexNode node) {
264 expect(node, isNull);
265 // failed
266 verify(logger.logError2(anyString, anyObject)).once();
267 });
268 }
269
270 test_getNode_streamNull() {
271 String name = '42.index';
272 when(fileManager.read(name)).thenReturn(new Future.value(null));
273 // do in the Future
274 return nodeManager.getNode(name).then((IndexNode node) {
275 expect(node, isNull);
276 // OK
277 verifyZeroInteractions(logger);
278 });
279 }
280
281 void test_newNode() {
282 IndexNode node = nodeManager.newNode(context);
283 expect(node.context, context);
284 expect(node.locationCount, 0);
285 }
286
287 test_putNode_getNode() {
288 String name = '42.index';
289 // record bytes
290 List<int> bytes;
291 when(fileManager.write(name, anyObject)).thenInvoke((name, bs) {
292 bytes = bs;
293 });
294 // prepare elements
295 Element elementA = _mockElement();
296 Element elementB = _mockElement();
297 Element elementC = _mockElement();
298 Relationship relationship = Relationship.getRelationship('my-relationship');
299 // put Node
300 Future putFuture;
301 {
302 // prepare relations
303 int elementIdA = 0;
304 int elementIdB = 1;
305 int elementIdC = 2;
306 int relationshipId = relationshipCodec.encode(relationship);
307 RelationKeyData key = new RelationKeyData.forData(elementIdA,
308 relationshipId);
309 List<LocationData> locations = [new LocationData.forData(elementIdB, 1,
310 10), new LocationData.forData(elementIdC, 2, 20)];
311 Map<RelationKeyData, List<LocationData>> relations = {
312 key: locations
313 };
314 // prepare Node
315 IndexNode node = new _MockIndexNode();
316 when(node.context).thenReturn(context);
317 when(node.relations).thenReturn(relations);
318 when(node.locationCount).thenReturn(2);
319 // put Node
320 putFuture = nodeManager.putNode(name, node);
321 }
322 // do in the Future
323 putFuture.then((_) {
324 // has locations
325 expect(nodeManager.locationCount, 2);
326 // prepare input bytes
327 when(fileManager.read(name)).thenReturn(new Future.value(bytes));
328 // get Node
329 return nodeManager.getNode(name).then((IndexNode node) {
330 expect(2, node.locationCount);
331 {
332 List<Location> locations = node.getRelationships(elementA,
333 relationship);
334 expect(locations, hasLength(2));
335 _assertHasLocation(locations, elementB, 1, 10);
336 _assertHasLocation(locations, elementC, 2, 20);
337 }
338 });
339 });
340 }
341
342 test_putNode_streamException() {
343 String name = '42.index';
344 Exception exception = new Exception();
345 when(fileManager.write(name, anyObject)).thenReturn(new Future(() {
346 return throw exception;
347 }));
348 // prepare IndexNode
349 IndexNode node = new _MockIndexNode();
350 when(node.context).thenReturn(context);
351 when(node.locationCount).thenReturn(0);
352 when(node.relations).thenReturn({});
353 // try to put
354 return nodeManager.putNode(name, node).then((_) {
355 // failed
356 verify(logger.logError2(anyString, anyObject)).once();
357 });
358 }
359
360 void test_removeNode() {
361 String name = '42.index';
362 nodeManager.removeNode(name);
363 verify(fileManager.delete(name)).once();
364 }
365
366 Element _mockElement() {
367 int elementId = nextElementId++;
368 Element element = new _MockElement();
369 when(elementCodec.encode(element)).thenReturn(elementId);
370 when(elementCodec.decode(context, elementId)).thenReturn(element);
371 return element;
372 }
373 }
374
375
376 @ReflectiveTestCase()
377 class _IndexNodeTest {
378 AnalysisContext context = new _MockAnalysisContext('context');
379 ElementCodec elementCodec = new _MockElementCodec();
380 int nextElementId = 0;
381 IndexNode node;
382 RelationshipCodec relationshipCodec;
383 StringCodec stringCodec = new StringCodec();
384
385 void setUp() {
386 relationshipCodec = new RelationshipCodec(stringCodec);
387 node = new IndexNode(context, elementCodec, relationshipCodec);
388 }
389
390 void test_getContext() {
391 expect(node.context, context);
392 }
393
394 void test_recordRelationship() {
395 Element elementA = _mockElement();
396 Element elementB = _mockElement();
397 Element elementC = _mockElement();
398 Relationship relationship = Relationship.getRelationship('my-relationship');
399 Location locationA = new Location(elementB, 1, 2);
400 Location locationB = new Location(elementC, 10, 20);
401 // empty initially
402 expect(node.locationCount, 0);
403 // record
404 node.recordRelationship(elementA, relationship, locationA);
405 expect(node.locationCount, 1);
406 node.recordRelationship(elementA, relationship, locationB);
407 expect(node.locationCount, 2);
408 // get relations
409 expect(node.getRelationships(elementB, relationship), isEmpty);
410 {
411 List<Location> locations = node.getRelationships(elementA, relationship);
412 expect(locations, hasLength(2));
413 _assertHasLocation(locations, null, 1, 2);
414 _assertHasLocation(locations, null, 10, 20);
415 }
416 // verify relations map
417 {
418 Map<RelationKeyData, List<LocationData>> relations = node.relations;
419 expect(relations, hasLength(1));
420 List<LocationData> locations = relations.values.first;
421 expect(locations, hasLength(2));
422 }
423 }
424
425 void test_setRelations() {
426 Element elementA = _mockElement();
427 Element elementB = _mockElement();
428 Element elementC = _mockElement();
429 Relationship relationship = Relationship.getRelationship('my-relationship');
430 // record
431 {
432 int elementIdA = 0;
433 int elementIdB = 1;
434 int elementIdC = 2;
435 int relationshipId = relationshipCodec.encode(relationship);
436 RelationKeyData key = new RelationKeyData.forData(elementIdA,
437 relationshipId);
438 List<LocationData> locations = [new LocationData.forData(elementIdB, 1,
439 10), new LocationData.forData(elementIdC, 2, 20)];
440 node.relations = {
441 key: locations
442 };
443 }
444 // request
445 List<Location> locations = node.getRelationships(elementA, relationship);
446 expect(locations, hasLength(2));
447 _assertHasLocation(locations, elementB, 1, 10);
448 _assertHasLocation(locations, elementC, 2, 20);
449 }
450
451 Element _mockElement() {
452 int elementId = nextElementId++;
453 Element element = new _MockElement();
454 when(elementCodec.encode(element)).thenReturn(elementId);
455 when(elementCodec.decode(context, elementId)).thenReturn(element);
456 return element;
457 }
458 }
459
460
461 @ReflectiveTestCase()
462 class _IntToIntSetMapTest {
463 IntToIntSetMap map = new IntToIntSetMap(32, 0.75);
464
465 void test_clear() {
466 map.add(1, 10);
467 map.add(2, 20);
468 expect(map.length, 2);
469 map.clear();
470 expect(map.length, 0);
471 }
472
473 void test_get() {
474 map.add(1, 10);
475 map.add(1, 11);
476 map.add(1, 12);
477 map.add(2, 20);
478 map.add(2, 21);
479 expect(map.get(1), unorderedEquals([10, 11, 12]));
480 expect(map.get(2), unorderedEquals([20, 21]));
481 }
482
483 void test_get_no() {
484 expect(map.get(3), []);
485 }
486
487 void test_length() {
488 expect(map.length, 0);
489 map.add(1, 10);
490 expect(map.length, 1);
491 map.add(1, 11);
492 expect(map.length, 2);
493 map.add(1, 12);
494 expect(map.length, 3);
495 map.add(2, 20);
496 expect(map.length, 4);
497 map.add(2, 21);
498 expect(map.length, 5);
499 }
500 }
501
502
503 @ReflectiveTestCase()
504 class _LocationDataTest {
505 AnalysisContext context = new _MockAnalysisContext('context');
506 ElementCodec elementCodec = new _MockElementCodec();
507 StringCodec stringCodec = new StringCodec();
508
509 void test_newForData() {
510 Element element = new _MockElement();
511 when(elementCodec.decode(context, 0)).thenReturn(element);
512 LocationData locationData = new LocationData.forData(0, 1, 2);
513 Location location = locationData.getLocation(context, elementCodec);
514 expect(location.element, element);
515 expect(location.offset, 1);
516 expect(location.length, 2);
517 }
518
519 void test_newForObject() {
520 // prepare Element
521 Element element = new _MockElement();
522 when(elementCodec.encode(element)).thenReturn(42);
523 when(elementCodec.decode(context, 42)).thenReturn(element);
524 // create
525 Location location = new Location(element, 1, 2);
526 LocationData locationData = new LocationData.forObject(elementCodec,
527 location);
528 // touch 'hashCode'
529 locationData.hashCode;
530 // ==
531 expect(locationData == new LocationData.forData(42, 1, 2), isTrue);
532 // getLocation()
533 {
534 Location newLocation = locationData.getLocation(context, elementCodec);
535 expect(location.element, element);
536 expect(location.offset, 1);
537 expect(location.length, 2);
538 }
539 // no Element - no Location
540 {
541 when(elementCodec.decode(context, 42)).thenReturn(null);
542 Location newLocation = locationData.getLocation(context, elementCodec);
543 expect(newLocation, isNull);
544 }
545 }
546 }
547
548
549 /**
550 * [Location] has no [==] and [hashCode], so to compare locations by value we
551 * need to wrap them into such object.
552 */
553 class _LocationEqualsWrapper {
554 final Location location;
555
556 _LocationEqualsWrapper(this.location);
557
558 @override
559 int get hashCode {
560 return 31 * (31 * location.element.hashCode + location.offset) +
561 location.length;
562 }
563
564 @override
565 bool operator ==(Object other) {
566 if (other is _LocationEqualsWrapper) {
567 return other.location.offset == location.offset && other.location.length
568 == location.length && other.location.element == location.element;
569 }
570 return false;
571 }
572 }
573
574
575 class _MemoryNodeManager implements NodeManager {
576 ContextCodec _contextCodec = new ContextCodec();
577 ElementCodec _elementCodec;
578 int _locationCount = 0;
579 final Map<String, int> _nodeLocationCounts = new HashMap<String, int>();
580
581 final Map<String, IndexNode> _nodes = new HashMap<String, IndexNode>();
582 RelationshipCodec _relationshipCodec;
583 StringCodec _stringCodec = new StringCodec();
584
585 _MemoryNodeManager() {
586 _elementCodec = new ElementCodec(_stringCodec);
587 _relationshipCodec = new RelationshipCodec(_stringCodec);
588 }
589
590 @override
591 ContextCodec get contextCodec {
592 return _contextCodec;
593 }
594
595 @override
596 ElementCodec get elementCodec {
597 return _elementCodec;
598 }
599
600 @override
601 int get locationCount {
602 return _locationCount;
603 }
604
605 @override
606 StringCodec get stringCodec {
607 return _stringCodec;
608 }
609
610 @override
611 void clear() {
612 _nodes.clear();
613 }
614
615 int getLocationCount(String name) {
616 int locationCount = _nodeLocationCounts[name];
617 return locationCount != null ? locationCount : 0;
618 }
619
620 @override
621 Future<IndexNode> getNode(String name) {
622 return new Future.value(_nodes[name]);
623 }
624
625 bool isEmpty() {
626 for (IndexNode node in _nodes.values) {
627 Map<RelationKeyData, List<LocationData>> relations = node.relations;
628 if (!relations.isEmpty) {
629 return false;
630 }
631 }
632 return true;
633 }
634
635 @override
636 IndexNode newNode(AnalysisContext context) {
637 return new IndexNode(context, elementCodec, _relationshipCodec);
638 }
639
640 @override
641 void putNode(String name, IndexNode node) {
642 // update location count
643 {
644 _locationCount -= getLocationCount(name);
645 int nodeLocationCount = node.locationCount;
646 _nodeLocationCounts[name] = nodeLocationCount;
647 _locationCount += nodeLocationCount;
648 }
649 // remember the node
650 _nodes[name] = node;
651 }
652
653 @override
654 void removeNode(String name) {
655 _nodes.remove(name);
656 }
657 }
658
659
660 class _MockAnalysisContext extends TypedMock implements AnalysisContext {
661 String _name;
662 _MockAnalysisContext(this._name);
663 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
664 String toString() => _name;
665 }
666
667
668 class _MockCompilationUnitElement extends TypedMock implements
669 CompilationUnitElement {
670 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
671 }
672
673
674 class _MockContextCodec extends TypedMock implements ContextCodec {
675 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
676 }
677
678
679 class _MockElement extends TypedMock implements Element {
680 String _name;
681 _MockElement([this._name = '<element>']);
682 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
683 String toString() => _name;
684 }
685
686
687 class _MockElementCodec extends TypedMock implements ElementCodec {
688 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
689 }
690
691
692 class _MockFileManager extends TypedMock implements FileManager {
693 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
694 }
695
696
697 class _MockHtmlElement extends TypedMock implements HtmlElement {
698 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
699 }
700
701
702 class _MockIndexNode extends TypedMock implements IndexNode {
703 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
704 }
705
706
707 class _MockInstrumentedAnalysisContextImpl extends TypedMock implements
708 InstrumentedAnalysisContextImpl {
709 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
710 }
711
712
713 class _MockLibraryElement extends TypedMock implements LibraryElement {
714 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
715 }
716
717
718 class _MockLocation extends TypedMock implements Location {
719 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
720 }
721
722
723 class _MockLogger extends TypedMock implements Logger {
724 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
725 }
726
727
728 class _MockRelationshipCodec extends TypedMock implements RelationshipCodec {
729 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
730 }
731
732
733 class _MockSource extends TypedMock implements Source {
734 String _name;
735 _MockSource(this._name);
736 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
737 String toString() => _name;
738 }
739
740
741 @ReflectiveTestCase()
742 class _RelationKeyDataTest {
743 AnalysisContext context = new _MockAnalysisContext('context');
744 ElementCodec elementCodec = new _MockElementCodec();
745 RelationshipCodec relationshipCodec = new _MockRelationshipCodec();
746 StringCodec stringCodec = new StringCodec();
747
748 void test_newFromData() {
749 RelationKeyData keyData = new RelationKeyData.forData(1, 2);
750 // equals
751 expect(keyData == this, isFalse);
752 expect(keyData == new RelationKeyData.forData(10, 20), isFalse);
753 expect(keyData == keyData, isTrue);
754 expect(keyData == new RelationKeyData.forData(1, 2), isTrue);
755 }
756
757 void test_newFromObjects() {
758 // prepare Element
759 Element element;
760 int elementId = 2;
761 {
762 element = new _MockElement();
763 ElementLocation location = new ElementLocationImpl.con3(['foo', 'bar']);
764 when(element.location).thenReturn(location);
765 when(context.getElement(location)).thenReturn(element);
766 when(elementCodec.encode(element)).thenReturn(elementId);
767 }
768 // prepare relationship
769 Relationship relationship = Relationship.getRelationship('my-relationship');
770 int relationshipId = 1;
771 when(relationshipCodec.encode(relationship)).thenReturn(relationshipId);
772 // create RelationKeyData
773 RelationKeyData keyData = new RelationKeyData.forObject(elementCodec,
774 relationshipCodec, element, relationship);
775 // touch
776 keyData.hashCode;
777 // equals
778 expect(keyData == this, isFalse);
779 expect(keyData == new RelationKeyData.forData(10, 20), isFalse);
780 expect(keyData == keyData, isTrue);
781 expect(keyData == new RelationKeyData.forData(elementId, relationshipId),
782 isTrue);
783 }
784 }
785
786
787 @ReflectiveTestCase()
788 class _RelationshipCodecTest {
789 RelationshipCodec codec;
790 StringCodec stringCodec = new StringCodec();
791
792 void setUp() {
793 codec = new RelationshipCodec(stringCodec);
794 }
795
796 void test_all() {
797 Relationship relationship = Relationship.getRelationship('my-relationship');
798 int id = codec.encode(relationship);
799 expect(codec.decode(id), relationship);
800 }
801 }
802
803
804 class _SingleSourceContainer implements SourceContainer {
805 final Source _source;
806 _SingleSourceContainer(this._source);
807 @override
808 bool contains(Source source) => source == _source;
809 }
810
811
812 @ReflectiveTestCase()
813 class _SplitIndexStoreTest {
814 AnalysisContext contextA = new _MockAnalysisContext('contextA');
815
816 AnalysisContext contextB = new _MockAnalysisContext('contextB');
817
818 AnalysisContext contextC = new _MockAnalysisContext('contextC');
819
820 Element elementA = new _MockElement('elementA');
821 Element elementB = new _MockElement('elementB');
822
823 Element elementC = new _MockElement('elementC');
824 Element elementD = new _MockElement('elementD');
825 ElementLocation elementLocationA = new ElementLocationImpl.con3(
826 ['/home/user/sourceA.dart', 'ClassA']);
827 ElementLocation elementLocationB = new ElementLocationImpl.con3(
828 ['/home/user/sourceB.dart', 'ClassB']);
829 ElementLocation elementLocationC = new ElementLocationImpl.con3(
830 ['/home/user/sourceC.dart', 'ClassC']);
831 ElementLocation elementLocationD = new ElementLocationImpl.con3(
832 ['/home/user/sourceD.dart', 'ClassD']);
833 HtmlElement htmlElementA = new _MockHtmlElement();
834 HtmlElement htmlElementB = new _MockHtmlElement();
835 LibraryElement libraryElement = new _MockLibraryElement();
836 Source librarySource = new _MockSource('librarySource');
837 CompilationUnitElement libraryUnitElement = new _MockCompilationUnitElement();
838 _MemoryNodeManager nodeManager = new _MemoryNodeManager();
839 Relationship relationship = Relationship.getRelationship('test-relationship');
840 Source sourceA = new _MockSource('sourceA');
841 Source sourceB = new _MockSource('sourceB');
842 Source sourceC = new _MockSource('sourceC');
843 Source sourceD = new _MockSource('sourceD');
844 SplitIndexStore store;
845 CompilationUnitElement unitElementA = new _MockCompilationUnitElement();
846 CompilationUnitElement unitElementB = new _MockCompilationUnitElement();
847 CompilationUnitElement unitElementC = new _MockCompilationUnitElement();
848 CompilationUnitElement unitElementD = new _MockCompilationUnitElement();
849 void setUp() {
850 store = new SplitIndexStore(nodeManager);
851 when(contextA.isDisposed).thenReturn(false);
852 when(contextB.isDisposed).thenReturn(false);
853 when(contextC.isDisposed).thenReturn(false);
854 when(contextA.getElement(elementLocationA)).thenReturn(elementA);
855 when(contextA.getElement(elementLocationB)).thenReturn(elementB);
856 when(contextA.getElement(elementLocationC)).thenReturn(elementC);
857 when(contextA.getElement(elementLocationD)).thenReturn(elementD);
858 when(sourceA.fullName).thenReturn('/home/user/sourceA.dart');
859 when(sourceB.fullName).thenReturn('/home/user/sourceB.dart');
860 when(sourceC.fullName).thenReturn('/home/user/sourceC.dart');
861 when(sourceD.fullName).thenReturn('/home/user/sourceD.dart');
862 when(elementA.context).thenReturn(contextA);
863 when(elementB.context).thenReturn(contextA);
864 when(elementC.context).thenReturn(contextA);
865 when(elementD.context).thenReturn(contextA);
866 when(elementA.location).thenReturn(elementLocationA);
867 when(elementB.location).thenReturn(elementLocationB);
868 when(elementC.location).thenReturn(elementLocationC);
869 when(elementD.location).thenReturn(elementLocationD);
870 when(elementA.enclosingElement).thenReturn(unitElementA);
871 when(elementB.enclosingElement).thenReturn(unitElementB);
872 when(elementC.enclosingElement).thenReturn(unitElementC);
873 when(elementD.enclosingElement).thenReturn(unitElementD);
874 when(elementA.source).thenReturn(sourceA);
875 when(elementB.source).thenReturn(sourceB);
876 when(elementC.source).thenReturn(sourceC);
877 when(elementD.source).thenReturn(sourceD);
878 when(elementA.library).thenReturn(libraryElement);
879 when(elementB.library).thenReturn(libraryElement);
880 when(elementC.library).thenReturn(libraryElement);
881 when(elementD.library).thenReturn(libraryElement);
882 when(unitElementA.source).thenReturn(sourceA);
883 when(unitElementB.source).thenReturn(sourceB);
884 when(unitElementC.source).thenReturn(sourceC);
885 when(unitElementD.source).thenReturn(sourceD);
886 when(unitElementA.library).thenReturn(libraryElement);
887 when(unitElementB.library).thenReturn(libraryElement);
888 when(unitElementC.library).thenReturn(libraryElement);
889 when(unitElementD.library).thenReturn(libraryElement);
890 when(htmlElementA.source).thenReturn(sourceA);
891 when(htmlElementB.source).thenReturn(sourceB);
892 // library
893 when(libraryUnitElement.library).thenReturn(libraryElement);
894 when(libraryUnitElement.source).thenReturn(librarySource);
895 when(libraryElement.source).thenReturn(librarySource);
896 when(libraryElement.definingCompilationUnit).thenReturn(libraryUnitElement);
897 }
898 void test_aboutToIndexDart_disposedContext() {
899 when(contextA.isDisposed).thenReturn(true);
900 expect(store.aboutToIndexDart(contextA, unitElementA), isFalse);
901 }
902 void test_aboutToIndexDart_disposedContext_wrapped() {
903 when(contextA.isDisposed).thenReturn(true);
904 InstrumentedAnalysisContextImpl instrumentedContext =
905 new _MockInstrumentedAnalysisContextImpl();
906 when(instrumentedContext.basis).thenReturn(contextA);
907 expect(store.aboutToIndexDart(instrumentedContext, unitElementA), isFalse);
908 }
909
910 void test_aboutToIndexDart_library_first() {
911 when(libraryElement.parts).thenReturn(<CompilationUnitElement>[unitElementA,
912 unitElementB]);
913 {
914 store.aboutToIndexDart(contextA, libraryUnitElement);
915 store.doneIndex();
916 }
917 {
918 List<Location> locations = store.getRelationships(elementA, relationship);
919 assertLocations(locations, []);
920 }
921 }
922
923 test_aboutToIndexDart_library_secondWithoutOneUnit() {
924 Location locationA = mockLocation(elementA);
925 Location locationB = mockLocation(elementB);
926 {
927 store.aboutToIndexDart(contextA, unitElementA);
928 store.recordRelationship(elementA, relationship, locationA);
929 store.doneIndex();
930 }
931 {
932 store.aboutToIndexDart(contextA, unitElementB);
933 store.recordRelationship(elementA, relationship, locationB);
934 store.doneIndex();
935 }
936 // "A" and "B" locations
937 return store.getRelationshipsAsync(elementA, relationship).then(
938 (List<Location> locations) {
939 assertLocations(locations, [locationA, locationB]);
940 }).then((_) {
941 // apply "libraryUnitElement", only with "B"
942 when(libraryElement.parts).thenReturn([unitElementB]);
943 {
944 store.aboutToIndexDart(contextA, libraryUnitElement);
945 store.doneIndex();
946 }
947 return store.getRelationshipsAsync(elementA, relationship).then(
948 (List<Location> locations) {
949 assertLocations(locations, [locationB]);
950 });
951 });
952 }
953
954 void test_aboutToIndexDart_nullLibraryElement() {
955 when(unitElementA.library).thenReturn(null);
956 expect(store.aboutToIndexDart(contextA, unitElementA), isFalse);
957 }
958
959 void test_aboutToIndexDart_nullLibraryUnitElement() {
960 when(libraryElement.definingCompilationUnit).thenReturn(null);
961 expect(store.aboutToIndexDart(contextA, unitElementA), isFalse);
962 }
963
964 void test_aboutToIndexDart_nullUnitElement() {
965 expect(store.aboutToIndexDart(contextA, null), isFalse);
966 }
967
968 test_aboutToIndexHtml_() {
969 Location locationA = mockLocation(elementA);
970 Location locationB = mockLocation(elementB);
971 {
972 store.aboutToIndexHtml(contextA, htmlElementA);
973 store.recordRelationship(elementA, relationship, locationA);
974 store.doneIndex();
975 }
976 {
977 store.aboutToIndexHtml(contextA, htmlElementB);
978 store.recordRelationship(elementA, relationship, locationB);
979 store.doneIndex();
980 }
981 // "A" and "B" locations
982 return store.getRelationshipsAsync(elementA, relationship).then(
983 (List<Location> locations) {
984 assertLocations(locations, [locationA, locationB]);
985 });
986 }
987
988 void test_aboutToIndexHtml_disposedContext() {
989 when(contextA.isDisposed).thenReturn(true);
990 expect(store.aboutToIndexHtml(contextA, htmlElementA), isFalse);
991 }
992
993 void test_clear() {
994 Location locationA = mockLocation(elementA);
995 store.aboutToIndexDart(contextA, unitElementA);
996 store.recordRelationship(elementA, relationship, locationA);
997 store.doneIndex();
998 expect(nodeManager.isEmpty(), isFalse);
999 // clear
1000 store.clear();
1001 expect(nodeManager.isEmpty(), isTrue);
1002 }
1003
1004 test_getRelationships_empty() {
1005 return store.getRelationshipsAsync(elementA, relationship).then(
1006 (List<Location> locations) {
1007 expect(locations, isEmpty);
1008 });
1009 }
1010
1011 void test_getStatistics() {
1012 // empty initially
1013 {
1014 String statistics = store.statistics;
1015 expect(statistics, contains('0 locations'));
1016 expect(statistics, contains('0 sources'));
1017 }
1018 // add 2 locations
1019 Location locationA = mockLocation(elementA);
1020 Location locationB = mockLocation(elementB);
1021 {
1022 store.aboutToIndexDart(contextA, unitElementA);
1023 store.recordRelationship(elementA, relationship, locationA);
1024 store.doneIndex();
1025 }
1026 {
1027 store.aboutToIndexDart(contextA, unitElementB);
1028 store.recordRelationship(elementA, relationship, locationB);
1029 store.doneIndex();
1030 }
1031 {
1032 String statistics = store.statistics;
1033 expect(statistics, contains('2 locations'));
1034 expect(statistics, contains('3 sources'));
1035 }
1036 }
1037
1038 void test_recordRelationship_nullElement() {
1039 Location locationA = mockLocation(elementA);
1040 store.recordRelationship(null, relationship, locationA);
1041 store.doneIndex();
1042 expect(nodeManager.isEmpty(), isTrue);
1043 }
1044
1045 void test_recordRelationship_nullLocation() {
1046 store.recordRelationship(elementA, relationship, null);
1047 store.doneIndex();
1048 expect(nodeManager.isEmpty(), isTrue);
1049 }
1050
1051 test_recordRelationship_oneElement_twoNodes() {
1052 Location locationA = mockLocation(elementA);
1053 Location locationB = mockLocation(elementB);
1054 {
1055 store.aboutToIndexDart(contextA, unitElementA);
1056 store.recordRelationship(elementA, relationship, locationA);
1057 store.doneIndex();
1058 }
1059 {
1060 store.aboutToIndexDart(contextA, unitElementB);
1061 store.recordRelationship(elementA, relationship, locationB);
1062 store.doneIndex();
1063 }
1064 return store.getRelationshipsAsync(elementA, relationship).then(
1065 (List<Location> locations) {
1066 assertLocations(locations, [locationA, locationB]);
1067 });
1068 }
1069
1070 test_recordRelationship_oneLocation() {
1071 Location locationA = mockLocation(elementA);
1072 store.aboutToIndexDart(contextA, unitElementA);
1073 store.recordRelationship(elementA, relationship, locationA);
1074 store.doneIndex();
1075 return store.getRelationshipsAsync(elementA, relationship).then(
1076 (List<Location> locations) {
1077 assertLocations(locations, [locationA]);
1078 });
1079 }
1080
1081 test_recordRelationship_twoLocations() {
1082 Location locationA = mockLocation(elementA);
1083 Location locationB = mockLocation(elementA);
1084 store.aboutToIndexDart(contextA, unitElementA);
1085 store.recordRelationship(elementA, relationship, locationA);
1086 store.recordRelationship(elementA, relationship, locationB);
1087 store.doneIndex();
1088 return store.getRelationshipsAsync(elementA, relationship).then(
1089 (List<Location> locations) {
1090 assertLocations(locations, [locationA, locationB]);
1091 });
1092 }
1093
1094 test_removeContext() {
1095 Location locationA = mockLocation(elementA);
1096 Location locationB = mockLocation(elementB);
1097 {
1098 store.aboutToIndexDart(contextA, unitElementA);
1099 store.recordRelationship(elementA, relationship, locationA);
1100 store.doneIndex();
1101 }
1102 {
1103 store.aboutToIndexDart(contextA, unitElementB);
1104 store.recordRelationship(elementA, relationship, locationB);
1105 store.doneIndex();
1106 }
1107 // "A" and "B" locations
1108 return store.getRelationshipsAsync(elementA, relationship).then(
1109 (List<Location> locations) {
1110 assertLocations(locations, [locationA, locationB]);
1111 }).then((_) {
1112 // remove "A" context
1113 store.removeContext(contextA);
1114 return store.getRelationshipsAsync(elementA, relationship).then(
1115 (List<Location> locations) {
1116 assertLocations(locations, []);
1117 });
1118 });
1119 }
1120
1121 void test_removeContext_nullContext() {
1122 store.removeContext(null);
1123 }
1124
1125 test_removeSource_library() {
1126 Location locationA = mockLocation(elementA);
1127 Location locationB = mockLocation(elementB);
1128 Location locationC = mockLocation(elementC);
1129 {
1130 store.aboutToIndexDart(contextA, unitElementA);
1131 store.recordRelationship(elementA, relationship, locationA);
1132 store.doneIndex();
1133 }
1134 {
1135 store.aboutToIndexDart(contextA, unitElementB);
1136 store.recordRelationship(elementA, relationship, locationB);
1137 store.doneIndex();
1138 }
1139 {
1140 store.aboutToIndexDart(contextA, unitElementC);
1141 store.recordRelationship(elementA, relationship, locationC);
1142 store.doneIndex();
1143 }
1144 // "A", "B" and "C" locations
1145 return store.getRelationshipsAsync(elementA, relationship).then(
1146 (List<Location> locations) {
1147 assertLocations(locations, [locationA, locationB, locationC]);
1148 }).then((_) {
1149 // remove "librarySource"
1150 store.removeSource(contextA, librarySource);
1151 return store.getRelationshipsAsync(elementA, relationship).then(
1152 (List<Location> locations) {
1153 assertLocations(locations, []);
1154 });
1155 });
1156 }
1157
1158 void test_removeSource_nullContext() {
1159 store.removeSource(null, sourceA);
1160 }
1161
1162 test_removeSource_unit() {
1163 Location locationA = mockLocation(elementA);
1164 Location locationB = mockLocation(elementB);
1165 Location locationC = mockLocation(elementC);
1166 {
1167 store.aboutToIndexDart(contextA, unitElementA);
1168 store.recordRelationship(elementA, relationship, locationA);
1169 store.doneIndex();
1170 }
1171 {
1172 store.aboutToIndexDart(contextA, unitElementB);
1173 store.recordRelationship(elementA, relationship, locationB);
1174 store.doneIndex();
1175 }
1176 {
1177 store.aboutToIndexDart(contextA, unitElementC);
1178 store.recordRelationship(elementA, relationship, locationC);
1179 store.doneIndex();
1180 }
1181 // "A", "B" and "C" locations
1182 return store.getRelationshipsAsync(elementA, relationship).then(
1183 (List<Location> locations) {
1184 assertLocations(locations, [locationA, locationB, locationC]);
1185 }).then((_) {
1186 // remove "A" source
1187 store.removeSource(contextA, sourceA);
1188 return store.getRelationshipsAsync(elementA, relationship).then(
1189 (List<Location> locations) {
1190 assertLocations(locations, [locationB, locationC]);
1191 });
1192 });
1193 }
1194
1195 test_removeSources_library() {
1196 Location locationA = mockLocation(elementA);
1197 Location locationB = mockLocation(elementB);
1198 {
1199 store.aboutToIndexDart(contextA, unitElementA);
1200 store.recordRelationship(elementA, relationship, locationA);
1201 store.doneIndex();
1202 }
1203 {
1204 store.aboutToIndexDart(contextA, unitElementB);
1205 store.recordRelationship(elementA, relationship, locationB);
1206 store.doneIndex();
1207 }
1208 // "A" and "B" locations
1209 return store.getRelationshipsAsync(elementA, relationship).then(
1210 (List<Location> locations) {
1211 assertLocations(locations, [locationA, locationB]);
1212 }).then((_) {
1213 // remove "librarySource"
1214 store.removeSources(contextA, new _SingleSourceContainer(librarySource));
1215 return store.getRelationshipsAsync(elementA, relationship).then(
1216 (List<Location> locations) {
1217 assertLocations(locations, []);
1218 });
1219 });
1220 }
1221
1222 void test_removeSources_nullContext() {
1223 store.removeSources(null, null);
1224 }
1225
1226 test_removeSources_unit() {
1227 Location locationA = mockLocation(elementA);
1228 Location locationB = mockLocation(elementB);
1229 Location locationC = mockLocation(elementC);
1230 {
1231 store.aboutToIndexDart(contextA, unitElementA);
1232 store.recordRelationship(elementA, relationship, locationA);
1233 store.doneIndex();
1234 }
1235 {
1236 store.aboutToIndexDart(contextA, unitElementB);
1237 store.recordRelationship(elementA, relationship, locationB);
1238 store.doneIndex();
1239 }
1240 {
1241 store.aboutToIndexDart(contextA, unitElementC);
1242 store.recordRelationship(elementA, relationship, locationC);
1243 store.doneIndex();
1244 }
1245 // "A", "B" and "C" locations
1246 return store.getRelationshipsAsync(elementA, relationship).then(
1247 (List<Location> locations) {
1248 assertLocations(locations, [locationA, locationB, locationC]);
1249 }).then((_) {
1250 // remove "A" source
1251 store.removeSources(contextA, new _SingleSourceContainer(sourceA));
1252 store.removeSource(contextA, sourceA);
1253 return store.getRelationshipsAsync(elementA, relationship).then(
1254 (List<Location> locations) {
1255 assertLocations(locations, [locationB, locationC]);
1256 });
1257 });
1258 }
1259
1260 test_universe_aboutToIndex() {
1261 when(contextA.getElement(elementLocationA)).thenReturn(elementA);
1262 when(contextB.getElement(elementLocationB)).thenReturn(elementB);
1263 Location locationA = mockLocation(elementA);
1264 Location locationB = mockLocation(elementB);
1265 {
1266 store.aboutToIndexDart(contextA, unitElementA);
1267 store.recordRelationship(UniverseElement.INSTANCE, relationship,
1268 locationA);
1269 store.doneIndex();
1270 }
1271 {
1272 store.aboutToIndexDart(contextB, unitElementB);
1273 store.recordRelationship(UniverseElement.INSTANCE, relationship,
1274 locationB);
1275 store.doneIndex();
1276 }
1277 // get relationships
1278 return store.getRelationshipsAsync(UniverseElement.INSTANCE,
1279 relationship).then((List<Location> locations) {
1280 assertLocations(locations, [locationA, locationB]);
1281 }).then((_) {
1282 // re-index "unitElementA"
1283 store.aboutToIndexDart(contextA, unitElementA);
1284 store.doneIndex();
1285 return store.getRelationshipsAsync(UniverseElement.INSTANCE,
1286 relationship).then((List<Location> locations) {
1287 assertLocations(locations, [locationB]);
1288 });
1289 });
1290 }
1291
1292 test_universe_removeContext() {
1293 when(contextA.getElement(elementLocationA)).thenReturn(elementA);
1294 when(contextB.getElement(elementLocationB)).thenReturn(elementB);
1295 Location locationA = mockLocation(elementA);
1296 Location locationB = mockLocation(elementB);
1297 {
1298 store.aboutToIndexDart(contextA, unitElementA);
1299 store.recordRelationship(UniverseElement.INSTANCE, relationship,
1300 locationA);
1301 store.doneIndex();
1302 }
1303 {
1304 store.aboutToIndexDart(contextB, unitElementB);
1305 store.recordRelationship(UniverseElement.INSTANCE, relationship,
1306 locationB);
1307 store.doneIndex();
1308 }
1309 return store.getRelationshipsAsync(UniverseElement.INSTANCE,
1310 relationship).then((List<Location> locations) {
1311 assertLocations(locations, [locationA, locationB]);
1312 }).then((_) {
1313 // remove "contextA"
1314 store.removeContext(contextA);
1315 return store.getRelationshipsAsync(UniverseElement.INSTANCE,
1316 relationship).then((List<Location> locations) {
1317 assertLocations(locations, [locationB]);
1318 });
1319 });
1320 }
1321
1322 /**
1323 * Asserts that the [actual] locations have all the [expected] locations and
1324 * only them.
1325 */
1326 static void assertLocations(List<Location> actual, List<Location> expected) {
1327 List<_LocationEqualsWrapper> actualWrappers = wrapLocations(actual);
1328 List<_LocationEqualsWrapper> expectedWrappers = wrapLocations(expected);
1329 expect(actualWrappers, unorderedEquals(expectedWrappers));
1330 }
1331
1332 /**
1333 * @return the new [Location] mock.
1334 */
1335 static Location mockLocation(Element element) {
1336 Location location = new _MockLocation();
1337 when(location.element).thenReturn(element);
1338 when(location.offset).thenReturn(0);
1339 when(location.length).thenReturn(0);
1340 return location;
1341 }
1342
1343 /**
1344 * Wraps the given locations into [LocationEqualsWrapper].
1345 */
1346 static List<_LocationEqualsWrapper> wrapLocations(List<Location> locations) {
1347 List<_LocationEqualsWrapper> wrappers = <_LocationEqualsWrapper>[];
1348 for (Location location in locations) {
1349 wrappers.add(new _LocationEqualsWrapper(location));
1350 }
1351 return wrappers;
1352 }
1353 }
1354
1355
1356 @ReflectiveTestCase()
1357 class _StringCodecTest {
1358 StringCodec codec = new StringCodec();
1359
1360 void test_all() {
1361 int idA = codec.encode('aaa');
1362 int idB = codec.encode('bbb');
1363 expect(codec.decode(idA), 'aaa');
1364 expect(codec.decode(idB), 'bbb');
1365 }
1366 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/index/store/split_store.dart ('k') | pkg/analysis_server/test/index/store/codec_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698