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

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

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

Powered by Google App Engine
This is Rietveld 408576698