OLD | NEW |
| (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.services.src.index.store.split_store; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_services/index/index.dart'; | |
10 import 'package:analysis_services/src/index/store/codec.dart'; | |
11 import 'package:analysis_services/src/index/store/memory_node_manager.dart'; | |
12 import 'package:analysis_services/src/index/store/split_store.dart'; | |
13 import 'package:analysis_testing/mocks.dart'; | |
14 import 'package:analysis_testing/reflective_tests.dart'; | |
15 import 'package:analyzer/src/generated/element.dart'; | |
16 import 'package:analyzer/src/generated/engine.dart'; | |
17 import 'package:analyzer/src/generated/source.dart'; | |
18 import 'package:typed_mock/typed_mock.dart'; | |
19 import 'package:unittest/unittest.dart'; | |
20 | |
21 import 'mocks.dart'; | |
22 import 'single_source_container.dart'; | |
23 | |
24 | |
25 main() { | |
26 groupSep = ' | '; | |
27 runReflectiveTests(_FileNodeManagerTest); | |
28 runReflectiveTests(_IndexNodeTest); | |
29 runReflectiveTests(_LocationDataTest); | |
30 runReflectiveTests(_RelationKeyDataTest); | |
31 runReflectiveTests(_SplitIndexStoreTest); | |
32 } | |
33 | |
34 | |
35 void _assertHasLocationQ(List<Location> locations, Element element, int offset, | |
36 int length) { | |
37 _assertHasLocation(locations, element, offset, length, isQualified: true); | |
38 } | |
39 | |
40 | |
41 void _assertHasLocation(List<Location> locations, Element element, int offset, | |
42 int length, {bool isQualified: false, | |
43 bool isResolved: true}) { | |
44 for (Location location in locations) { | |
45 if ((element == null || location.element == element) && | |
46 location.offset == offset && | |
47 location.length == length && | |
48 location.isQualified == isQualified && | |
49 location.isResolved == isResolved) { | |
50 return; | |
51 } | |
52 } | |
53 fail( | |
54 'Expected to find Location' | |
55 '(element=$element, offset=$offset, length=$length)'); | |
56 } | |
57 | |
58 | |
59 @ReflectiveTestCase() | |
60 class _FileNodeManagerTest { | |
61 MockLogger logger = new MockLogger(); | |
62 StringCodec stringCodec = new StringCodec(); | |
63 RelationshipCodec relationshipCodec; | |
64 | |
65 AnalysisContext context = new MockAnalysisContext('context'); | |
66 ContextCodec contextCodec = new MockContextCodec(); | |
67 int contextId = 13; | |
68 | |
69 ElementCodec elementCodec = new MockElementCodec(); | |
70 int nextElementId = 0; | |
71 | |
72 FileNodeManager nodeManager; | |
73 FileManager fileManager = new _MockFileManager(); | |
74 | |
75 void setUp() { | |
76 relationshipCodec = new RelationshipCodec(stringCodec); | |
77 nodeManager = new FileNodeManager( | |
78 fileManager, | |
79 logger, | |
80 stringCodec, | |
81 contextCodec, | |
82 elementCodec, | |
83 relationshipCodec); | |
84 when(contextCodec.encode(context)).thenReturn(contextId); | |
85 when(contextCodec.decode(contextId)).thenReturn(context); | |
86 } | |
87 | |
88 void test_clear() { | |
89 nodeManager.clear(); | |
90 verify(fileManager.clear()).once(); | |
91 } | |
92 | |
93 void test_getLocationCount_empty() { | |
94 expect(nodeManager.locationCount, 0); | |
95 } | |
96 | |
97 void test_getNode_contextNull() { | |
98 String name = '42.index'; | |
99 // record bytes | |
100 List<int> bytes; | |
101 when(fileManager.write(name, anyObject)).thenInvoke((name, bs) { | |
102 bytes = bs; | |
103 }); | |
104 // put Node | |
105 Future putFuture; | |
106 { | |
107 IndexNode node = new IndexNode(context, elementCodec, relationshipCodec); | |
108 putFuture = nodeManager.putNode(name, node); | |
109 } | |
110 // do in the "put" Future | |
111 putFuture.then((_) { | |
112 // force "null" context | |
113 when(contextCodec.decode(contextId)).thenReturn(null); | |
114 // prepare input bytes | |
115 when(fileManager.read(name)).thenReturn(new Future.value(bytes)); | |
116 // get Node | |
117 return nodeManager.getNode(name).then((IndexNode node) { | |
118 expect(node, isNull); | |
119 // no exceptions | |
120 verifyZeroInteractions(logger); | |
121 }); | |
122 }); | |
123 } | |
124 | |
125 test_getNode_invalidVersion() { | |
126 String name = '42.index'; | |
127 // prepare a stream with an invalid version | |
128 when( | |
129 fileManager.read(name)).thenReturn(new Future.value([0x01, 0x02, 0x03, 0
x04])); | |
130 // do in the Future | |
131 return nodeManager.getNode(name).then((IndexNode node) { | |
132 // no IndexNode | |
133 expect(node, isNull); | |
134 // failed | |
135 verify(logger.logError2(anyObject, anyObject)).once(); | |
136 }); | |
137 } | |
138 | |
139 test_getNode_streamException() { | |
140 String name = '42.index'; | |
141 when(fileManager.read(name)).thenReturn(new Future(() { | |
142 return throw new Exception(); | |
143 })); | |
144 // do in the Future | |
145 return nodeManager.getNode(name).then((IndexNode node) { | |
146 expect(node, isNull); | |
147 // failed | |
148 verify(logger.logError2(anyString, anyObject)).once(); | |
149 }); | |
150 } | |
151 | |
152 test_getNode_streamNull() { | |
153 String name = '42.index'; | |
154 when(fileManager.read(name)).thenReturn(new Future.value(null)); | |
155 // do in the Future | |
156 return nodeManager.getNode(name).then((IndexNode node) { | |
157 expect(node, isNull); | |
158 // OK | |
159 verifyZeroInteractions(logger); | |
160 }); | |
161 } | |
162 | |
163 void test_newNode() { | |
164 IndexNode node = nodeManager.newNode(context); | |
165 expect(node.context, context); | |
166 expect(node.locationCount, 0); | |
167 } | |
168 | |
169 test_putNode_getNode() { | |
170 String name = '42.index'; | |
171 // record bytes | |
172 List<int> bytes; | |
173 when(fileManager.write(name, anyObject)).thenInvoke((name, bs) { | |
174 bytes = bs; | |
175 }); | |
176 // prepare elements | |
177 Element elementA = _mockElement(); | |
178 Element elementB = _mockElement(); | |
179 Element elementC = _mockElement(); | |
180 Relationship relationship = Relationship.getRelationship('my-relationship'); | |
181 // put Node | |
182 Future putFuture; | |
183 { | |
184 // prepare relations | |
185 int elementIdA = 0; | |
186 int elementIdB = 1; | |
187 int elementIdC = 2; | |
188 int relationshipId = relationshipCodec.encode(relationship); | |
189 RelationKeyData key = | |
190 new RelationKeyData.forData(elementIdA, relationshipId); | |
191 List<LocationData> locations = [ | |
192 new LocationData.forData(elementIdB, 1, 10, 2), | |
193 new LocationData.forData(elementIdC, 2, 20, 3)]; | |
194 Map<RelationKeyData, List<LocationData>> relations = { | |
195 key: locations | |
196 }; | |
197 // prepare Node | |
198 IndexNode node = new _MockIndexNode(); | |
199 when(node.context).thenReturn(context); | |
200 when(node.relations).thenReturn(relations); | |
201 when(node.locationCount).thenReturn(2); | |
202 // put Node | |
203 putFuture = nodeManager.putNode(name, node); | |
204 } | |
205 // do in the Future | |
206 putFuture.then((_) { | |
207 // has locations | |
208 expect(nodeManager.locationCount, 2); | |
209 // prepare input bytes | |
210 when(fileManager.read(name)).thenReturn(new Future.value(bytes)); | |
211 // get Node | |
212 return nodeManager.getNode(name).then((IndexNode node) { | |
213 expect(2, node.locationCount); | |
214 { | |
215 List<Location> locations = | |
216 node.getRelationships(elementA, relationship); | |
217 expect(locations, hasLength(2)); | |
218 _assertHasLocation(locations, elementB, 1, 10); | |
219 _assertHasLocationQ(locations, elementC, 2, 20); | |
220 } | |
221 }); | |
222 }); | |
223 } | |
224 | |
225 test_putNode_streamException() { | |
226 String name = '42.index'; | |
227 Exception exception = new Exception(); | |
228 when(fileManager.write(name, anyObject)).thenReturn(new Future(() { | |
229 return throw exception; | |
230 })); | |
231 // prepare IndexNode | |
232 IndexNode node = new _MockIndexNode(); | |
233 when(node.context).thenReturn(context); | |
234 when(node.locationCount).thenReturn(0); | |
235 when(node.relations).thenReturn({}); | |
236 // try to put | |
237 return nodeManager.putNode(name, node).then((_) { | |
238 // failed | |
239 verify(logger.logError2(anyString, anyObject)).once(); | |
240 }); | |
241 } | |
242 | |
243 void test_removeNode() { | |
244 String name = '42.index'; | |
245 nodeManager.removeNode(name); | |
246 verify(fileManager.delete(name)).once(); | |
247 } | |
248 | |
249 Element _mockElement() { | |
250 int elementId = nextElementId++; | |
251 Element element = new MockElement(); | |
252 when(elementCodec.encode(element)).thenReturn(elementId); | |
253 when(elementCodec.decode(context, elementId)).thenReturn(element); | |
254 return element; | |
255 } | |
256 } | |
257 | |
258 | |
259 @ReflectiveTestCase() | |
260 class _IndexNodeTest { | |
261 AnalysisContext context = new MockAnalysisContext('context'); | |
262 ElementCodec elementCodec = new MockElementCodec(); | |
263 int nextElementId = 0; | |
264 IndexNode node; | |
265 RelationshipCodec relationshipCodec; | |
266 StringCodec stringCodec = new StringCodec(); | |
267 | |
268 void setUp() { | |
269 relationshipCodec = new RelationshipCodec(stringCodec); | |
270 node = new IndexNode(context, elementCodec, relationshipCodec); | |
271 } | |
272 | |
273 void test_getContext() { | |
274 expect(node.context, context); | |
275 } | |
276 | |
277 void test_recordRelationship() { | |
278 Element elementA = _mockElement(); | |
279 Element elementB = _mockElement(); | |
280 Element elementC = _mockElement(); | |
281 Relationship relationship = Relationship.getRelationship('my-relationship'); | |
282 Location locationA = new Location(elementB, 1, 2); | |
283 Location locationB = new Location(elementC, 10, 20); | |
284 // empty initially | |
285 expect(node.locationCount, 0); | |
286 // record | |
287 node.recordRelationship(elementA, relationship, locationA); | |
288 expect(node.locationCount, 1); | |
289 node.recordRelationship(elementA, relationship, locationB); | |
290 expect(node.locationCount, 2); | |
291 // get relations | |
292 expect(node.getRelationships(elementB, relationship), isEmpty); | |
293 { | |
294 List<Location> locations = node.getRelationships(elementA, relationship); | |
295 expect(locations, hasLength(2)); | |
296 _assertHasLocation(locations, null, 1, 2); | |
297 _assertHasLocation(locations, null, 10, 20); | |
298 } | |
299 // verify relations map | |
300 { | |
301 Map<RelationKeyData, List<LocationData>> relations = node.relations; | |
302 expect(relations, hasLength(1)); | |
303 List<LocationData> locations = relations.values.first; | |
304 expect(locations, hasLength(2)); | |
305 } | |
306 } | |
307 | |
308 void test_setRelations() { | |
309 Element elementA = _mockElement(); | |
310 Element elementB = _mockElement(); | |
311 Element elementC = _mockElement(); | |
312 Relationship relationship = Relationship.getRelationship('my-relationship'); | |
313 // record | |
314 { | |
315 int elementIdA = 0; | |
316 int elementIdB = 1; | |
317 int elementIdC = 2; | |
318 int relationshipId = relationshipCodec.encode(relationship); | |
319 RelationKeyData key = | |
320 new RelationKeyData.forData(elementIdA, relationshipId); | |
321 List<LocationData> locations = [ | |
322 new LocationData.forData(elementIdB, 1, 10, 2), | |
323 new LocationData.forData(elementIdC, 2, 20, 3)]; | |
324 node.relations = { | |
325 key: locations | |
326 }; | |
327 } | |
328 // request | |
329 List<Location> locations = node.getRelationships(elementA, relationship); | |
330 expect(locations, hasLength(2)); | |
331 _assertHasLocation(locations, elementB, 1, 10); | |
332 _assertHasLocationQ(locations, elementC, 2, 20); | |
333 } | |
334 | |
335 Element _mockElement() { | |
336 int elementId = nextElementId++; | |
337 Element element = new MockElement(); | |
338 when(elementCodec.encode(element)).thenReturn(elementId); | |
339 when(elementCodec.decode(context, elementId)).thenReturn(element); | |
340 return element; | |
341 } | |
342 } | |
343 | |
344 | |
345 @ReflectiveTestCase() | |
346 class _LocationDataTest { | |
347 AnalysisContext context = new MockAnalysisContext('context'); | |
348 ElementCodec elementCodec = new MockElementCodec(); | |
349 StringCodec stringCodec = new StringCodec(); | |
350 | |
351 void test_newForData() { | |
352 Element element = new MockElement(); | |
353 when(elementCodec.decode(context, 0)).thenReturn(element); | |
354 LocationData locationData = new LocationData.forData(0, 1, 2, 0); | |
355 Location location = locationData.getLocation(context, elementCodec); | |
356 expect(location.element, element); | |
357 expect(location.offset, 1); | |
358 expect(location.length, 2); | |
359 expect(location.isQualified, isFalse); | |
360 expect(location.isResolved, isFalse); | |
361 } | |
362 | |
363 void test_newForObject() { | |
364 // prepare Element | |
365 Element element = new MockElement(); | |
366 when(elementCodec.encode(element)).thenReturn(42); | |
367 when(elementCodec.decode(context, 42)).thenReturn(element); | |
368 // create | |
369 Location location = new Location(element, 1, 2); | |
370 LocationData locationData = | |
371 new LocationData.forObject(elementCodec, location); | |
372 // touch 'hashCode' | |
373 locationData.hashCode; | |
374 // == | |
375 expect(locationData == new LocationData.forData(42, 1, 2, 2), isTrue); | |
376 // getLocation() | |
377 { | |
378 Location newLocation = locationData.getLocation(context, elementCodec); | |
379 expect(location.element, element); | |
380 expect(location.offset, 1); | |
381 expect(location.length, 2); | |
382 } | |
383 // no Element - no Location | |
384 { | |
385 when(elementCodec.decode(context, 42)).thenReturn(null); | |
386 Location newLocation = locationData.getLocation(context, elementCodec); | |
387 expect(newLocation, isNull); | |
388 } | |
389 } | |
390 } | |
391 | |
392 | |
393 /** | |
394 * [Location] has no [==] and [hashCode], so to compare locations by value we | |
395 * need to wrap them into such object. | |
396 */ | |
397 class _LocationEqualsWrapper { | |
398 final Location location; | |
399 | |
400 _LocationEqualsWrapper(this.location); | |
401 | |
402 @override | |
403 int get hashCode { | |
404 return 31 * (31 * location.element.hashCode + location.offset) + | |
405 location.length; | |
406 } | |
407 | |
408 @override | |
409 bool operator ==(Object other) { | |
410 if (other is _LocationEqualsWrapper) { | |
411 return other.location.offset == location.offset && | |
412 other.location.length == location.length && | |
413 other.location.element == location.element; | |
414 } | |
415 return false; | |
416 } | |
417 } | |
418 | |
419 | |
420 class _MockFileManager extends TypedMock implements FileManager { | |
421 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | |
422 } | |
423 | |
424 | |
425 class _MockIndexNode extends TypedMock implements IndexNode { | |
426 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | |
427 } | |
428 | |
429 | |
430 @ReflectiveTestCase() | |
431 class _RelationKeyDataTest { | |
432 AnalysisContext context = new MockAnalysisContext('context'); | |
433 ElementCodec elementCodec = new MockElementCodec(); | |
434 RelationshipCodec relationshipCodec = new MockRelationshipCodec(); | |
435 StringCodec stringCodec = new StringCodec(); | |
436 | |
437 void test_newFromData() { | |
438 RelationKeyData keyData = new RelationKeyData.forData(1, 2); | |
439 // equals | |
440 expect(keyData == this, isFalse); | |
441 expect(keyData == new RelationKeyData.forData(10, 20), isFalse); | |
442 expect(keyData == keyData, isTrue); | |
443 expect(keyData == new RelationKeyData.forData(1, 2), isTrue); | |
444 } | |
445 | |
446 void test_newFromObjects() { | |
447 // prepare Element | |
448 Element element; | |
449 int elementId = 2; | |
450 { | |
451 element = new MockElement(); | |
452 ElementLocation location = new ElementLocationImpl.con3(['foo', 'bar']); | |
453 when(element.location).thenReturn(location); | |
454 when(context.getElement(location)).thenReturn(element); | |
455 when(elementCodec.encode(element)).thenReturn(elementId); | |
456 } | |
457 // prepare relationship | |
458 Relationship relationship = Relationship.getRelationship('my-relationship'); | |
459 int relationshipId = 1; | |
460 when(relationshipCodec.encode(relationship)).thenReturn(relationshipId); | |
461 // create RelationKeyData | |
462 RelationKeyData keyData = | |
463 new RelationKeyData.forObject( | |
464 elementCodec, | |
465 relationshipCodec, | |
466 element, | |
467 relationship); | |
468 // touch | |
469 keyData.hashCode; | |
470 // equals | |
471 expect(keyData == this, isFalse); | |
472 expect(keyData == new RelationKeyData.forData(10, 20), isFalse); | |
473 expect(keyData == keyData, isTrue); | |
474 expect( | |
475 keyData == new RelationKeyData.forData(elementId, relationshipId), | |
476 isTrue); | |
477 } | |
478 } | |
479 | |
480 | |
481 | |
482 | |
483 @ReflectiveTestCase() | |
484 class _SplitIndexStoreTest { | |
485 AnalysisContext contextA = new MockAnalysisContext('contextA'); | |
486 | |
487 AnalysisContext contextB = new MockAnalysisContext('contextB'); | |
488 | |
489 AnalysisContext contextC = new MockAnalysisContext('contextC'); | |
490 | |
491 Element elementA = new MockElement('elementA'); | |
492 Element elementB = new MockElement('elementB'); | |
493 | |
494 Element elementC = new MockElement('elementC'); | |
495 Element elementD = new MockElement('elementD'); | |
496 ElementLocation elementLocationA = | |
497 new ElementLocationImpl.con3(['/home/user/sourceA.dart', 'ClassA']); | |
498 ElementLocation elementLocationB = | |
499 new ElementLocationImpl.con3(['/home/user/sourceB.dart', 'ClassB']); | |
500 ElementLocation elementLocationC = | |
501 new ElementLocationImpl.con3(['/home/user/sourceC.dart', 'ClassC']); | |
502 ElementLocation elementLocationD = | |
503 new ElementLocationImpl.con3(['/home/user/sourceD.dart', 'ClassD']); | |
504 HtmlElement htmlElementA = new MockHtmlElement(); | |
505 HtmlElement htmlElementB = new MockHtmlElement(); | |
506 LibraryElement libraryElement = new MockLibraryElement(); | |
507 Source librarySource = new MockSource('librarySource'); | |
508 CompilationUnitElement libraryUnitElement = new MockCompilationUnitElement(); | |
509 MemoryNodeManager nodeManager = new MemoryNodeManager(); | |
510 Relationship relationship = Relationship.getRelationship('test-relationship'); | |
511 Source sourceA = new MockSource('sourceA'); | |
512 Source sourceB = new MockSource('sourceB'); | |
513 Source sourceC = new MockSource('sourceC'); | |
514 Source sourceD = new MockSource('sourceD'); | |
515 SplitIndexStore store; | |
516 CompilationUnitElement unitElementA = new MockCompilationUnitElement(); | |
517 CompilationUnitElement unitElementB = new MockCompilationUnitElement(); | |
518 CompilationUnitElement unitElementC = new MockCompilationUnitElement(); | |
519 CompilationUnitElement unitElementD = new MockCompilationUnitElement(); | |
520 void setUp() { | |
521 store = new SplitIndexStore(nodeManager); | |
522 when(contextA.isDisposed).thenReturn(false); | |
523 when(contextB.isDisposed).thenReturn(false); | |
524 when(contextC.isDisposed).thenReturn(false); | |
525 when(contextA.getElement(elementLocationA)).thenReturn(elementA); | |
526 when(contextA.getElement(elementLocationB)).thenReturn(elementB); | |
527 when(contextA.getElement(elementLocationC)).thenReturn(elementC); | |
528 when(contextA.getElement(elementLocationD)).thenReturn(elementD); | |
529 when(sourceA.fullName).thenReturn('/home/user/sourceA.dart'); | |
530 when(sourceB.fullName).thenReturn('/home/user/sourceB.dart'); | |
531 when(sourceC.fullName).thenReturn('/home/user/sourceC.dart'); | |
532 when(sourceD.fullName).thenReturn('/home/user/sourceD.dart'); | |
533 when(elementA.context).thenReturn(contextA); | |
534 when(elementB.context).thenReturn(contextA); | |
535 when(elementC.context).thenReturn(contextA); | |
536 when(elementD.context).thenReturn(contextA); | |
537 when(elementA.location).thenReturn(elementLocationA); | |
538 when(elementB.location).thenReturn(elementLocationB); | |
539 when(elementC.location).thenReturn(elementLocationC); | |
540 when(elementD.location).thenReturn(elementLocationD); | |
541 when(elementA.enclosingElement).thenReturn(unitElementA); | |
542 when(elementB.enclosingElement).thenReturn(unitElementB); | |
543 when(elementC.enclosingElement).thenReturn(unitElementC); | |
544 when(elementD.enclosingElement).thenReturn(unitElementD); | |
545 when(elementA.source).thenReturn(sourceA); | |
546 when(elementB.source).thenReturn(sourceB); | |
547 when(elementC.source).thenReturn(sourceC); | |
548 when(elementD.source).thenReturn(sourceD); | |
549 when(elementA.library).thenReturn(libraryElement); | |
550 when(elementB.library).thenReturn(libraryElement); | |
551 when(elementC.library).thenReturn(libraryElement); | |
552 when(elementD.library).thenReturn(libraryElement); | |
553 when(unitElementA.source).thenReturn(sourceA); | |
554 when(unitElementB.source).thenReturn(sourceB); | |
555 when(unitElementC.source).thenReturn(sourceC); | |
556 when(unitElementD.source).thenReturn(sourceD); | |
557 when(unitElementA.library).thenReturn(libraryElement); | |
558 when(unitElementB.library).thenReturn(libraryElement); | |
559 when(unitElementC.library).thenReturn(libraryElement); | |
560 when(unitElementD.library).thenReturn(libraryElement); | |
561 when(htmlElementA.source).thenReturn(sourceA); | |
562 when(htmlElementB.source).thenReturn(sourceB); | |
563 // library | |
564 when(libraryUnitElement.library).thenReturn(libraryElement); | |
565 when(libraryUnitElement.source).thenReturn(librarySource); | |
566 when(libraryElement.source).thenReturn(librarySource); | |
567 when(libraryElement.definingCompilationUnit).thenReturn(libraryUnitElement); | |
568 } | |
569 | |
570 void test_aboutToIndexDart_disposedContext() { | |
571 when(contextA.isDisposed).thenReturn(true); | |
572 expect(store.aboutToIndexDart(contextA, unitElementA), isFalse); | |
573 } | |
574 | |
575 void test_aboutToIndexDart_disposedContext_wrapped() { | |
576 when(contextA.isDisposed).thenReturn(true); | |
577 InstrumentedAnalysisContextImpl instrumentedContext = | |
578 new MockInstrumentedAnalysisContextImpl(); | |
579 when(instrumentedContext.basis).thenReturn(contextA); | |
580 expect(store.aboutToIndexDart(instrumentedContext, unitElementA), isFalse); | |
581 } | |
582 | |
583 Future test_aboutToIndexDart_library_first() { | |
584 when( | |
585 libraryElement.parts).thenReturn( | |
586 <CompilationUnitElement>[unitElementA, unitElementB]); | |
587 { | |
588 store.aboutToIndexDart(contextA, libraryUnitElement); | |
589 store.doneIndex(); | |
590 } | |
591 return store.getRelationships( | |
592 elementA, | |
593 relationship).then((List<Location> locations) { | |
594 assertLocations(locations, []); | |
595 }); | |
596 } | |
597 | |
598 test_aboutToIndexDart_library_secondWithoutOneUnit() { | |
599 Location locationA = mockLocation(elementA); | |
600 Location locationB = mockLocation(elementB); | |
601 { | |
602 store.aboutToIndexDart(contextA, unitElementA); | |
603 store.recordRelationship(elementA, relationship, locationA); | |
604 store.doneIndex(); | |
605 } | |
606 { | |
607 store.aboutToIndexDart(contextA, unitElementB); | |
608 store.recordRelationship(elementA, relationship, locationB); | |
609 store.doneIndex(); | |
610 } | |
611 // "A" and "B" locations | |
612 return store.getRelationships( | |
613 elementA, | |
614 relationship).then((List<Location> locations) { | |
615 assertLocations(locations, [locationA, locationB]); | |
616 // apply "libraryUnitElement", only with "B" | |
617 when(libraryElement.parts).thenReturn([unitElementB]); | |
618 { | |
619 store.aboutToIndexDart(contextA, libraryUnitElement); | |
620 store.doneIndex(); | |
621 } | |
622 }).then((_) { | |
623 return store.getRelationships( | |
624 elementA, | |
625 relationship).then((List<Location> locations) { | |
626 assertLocations(locations, [locationB]); | |
627 }); | |
628 }); | |
629 } | |
630 | |
631 void test_aboutToIndexDart_nullLibraryElement() { | |
632 when(unitElementA.library).thenReturn(null); | |
633 expect(store.aboutToIndexDart(contextA, unitElementA), isFalse); | |
634 } | |
635 | |
636 void test_aboutToIndexDart_nullLibraryUnitElement() { | |
637 when(libraryElement.definingCompilationUnit).thenReturn(null); | |
638 expect(store.aboutToIndexDart(contextA, unitElementA), isFalse); | |
639 } | |
640 | |
641 void test_aboutToIndexDart_nullUnitElement() { | |
642 expect(store.aboutToIndexDart(contextA, null), isFalse); | |
643 } | |
644 | |
645 test_aboutToIndexHtml_() { | |
646 Location locationA = mockLocation(elementA); | |
647 Location locationB = mockLocation(elementB); | |
648 { | |
649 store.aboutToIndexHtml(contextA, htmlElementA); | |
650 store.recordRelationship(elementA, relationship, locationA); | |
651 store.doneIndex(); | |
652 } | |
653 { | |
654 store.aboutToIndexHtml(contextA, htmlElementB); | |
655 store.recordRelationship(elementA, relationship, locationB); | |
656 store.doneIndex(); | |
657 } | |
658 // "A" and "B" locations | |
659 return store.getRelationships( | |
660 elementA, | |
661 relationship).then((List<Location> locations) { | |
662 assertLocations(locations, [locationA, locationB]); | |
663 }); | |
664 } | |
665 | |
666 void test_aboutToIndexHtml_disposedContext() { | |
667 when(contextA.isDisposed).thenReturn(true); | |
668 expect(store.aboutToIndexHtml(contextA, htmlElementA), isFalse); | |
669 } | |
670 | |
671 void test_clear() { | |
672 Location locationA = mockLocation(elementA); | |
673 store.aboutToIndexDart(contextA, unitElementA); | |
674 store.recordRelationship(elementA, relationship, locationA); | |
675 store.doneIndex(); | |
676 expect(nodeManager.isEmpty(), isFalse); | |
677 // clear | |
678 store.clear(); | |
679 expect(nodeManager.isEmpty(), isTrue); | |
680 } | |
681 | |
682 test_getRelationships_empty() { | |
683 return store.getRelationships( | |
684 elementA, | |
685 relationship).then((List<Location> locations) { | |
686 expect(locations, isEmpty); | |
687 }); | |
688 } | |
689 | |
690 void test_getStatistics() { | |
691 // empty initially | |
692 { | |
693 String statistics = store.statistics; | |
694 expect(statistics, contains('0 locations')); | |
695 expect(statistics, contains('0 sources')); | |
696 } | |
697 // add 2 locations | |
698 Location locationA = mockLocation(elementA); | |
699 Location locationB = mockLocation(elementB); | |
700 { | |
701 store.aboutToIndexDart(contextA, unitElementA); | |
702 store.recordRelationship(elementA, relationship, locationA); | |
703 store.doneIndex(); | |
704 } | |
705 { | |
706 store.aboutToIndexDart(contextA, unitElementB); | |
707 store.recordRelationship(elementA, relationship, locationB); | |
708 store.doneIndex(); | |
709 } | |
710 { | |
711 String statistics = store.statistics; | |
712 expect(statistics, contains('2 locations')); | |
713 expect(statistics, contains('3 sources')); | |
714 } | |
715 } | |
716 | |
717 void test_recordRelationship_nullElement() { | |
718 Location locationA = mockLocation(elementA); | |
719 store.recordRelationship(null, relationship, locationA); | |
720 store.doneIndex(); | |
721 expect(nodeManager.isEmpty(), isTrue); | |
722 } | |
723 | |
724 void test_recordRelationship_nullLocation() { | |
725 store.recordRelationship(elementA, relationship, null); | |
726 store.doneIndex(); | |
727 expect(nodeManager.isEmpty(), isTrue); | |
728 } | |
729 | |
730 test_recordRelationship_oneElement_twoNodes() { | |
731 Location locationA = mockLocation(elementA); | |
732 Location locationB = mockLocation(elementB); | |
733 { | |
734 store.aboutToIndexDart(contextA, unitElementA); | |
735 store.recordRelationship(elementA, relationship, locationA); | |
736 store.doneIndex(); | |
737 } | |
738 { | |
739 store.aboutToIndexDart(contextA, unitElementB); | |
740 store.recordRelationship(elementA, relationship, locationB); | |
741 store.doneIndex(); | |
742 } | |
743 return store.getRelationships( | |
744 elementA, | |
745 relationship).then((List<Location> locations) { | |
746 assertLocations(locations, [locationA, locationB]); | |
747 }); | |
748 } | |
749 | |
750 test_recordRelationship_oneLocation() { | |
751 Location locationA = mockLocation(elementA); | |
752 store.aboutToIndexDart(contextA, unitElementA); | |
753 store.recordRelationship(elementA, relationship, locationA); | |
754 store.doneIndex(); | |
755 return store.getRelationships( | |
756 elementA, | |
757 relationship).then((List<Location> locations) { | |
758 assertLocations(locations, [locationA]); | |
759 }); | |
760 } | |
761 | |
762 test_recordRelationship_twoLocations() { | |
763 Location locationA = mockLocation(elementA); | |
764 Location locationB = mockLocation(elementA); | |
765 store.aboutToIndexDart(contextA, unitElementA); | |
766 store.recordRelationship(elementA, relationship, locationA); | |
767 store.recordRelationship(elementA, relationship, locationB); | |
768 store.doneIndex(); | |
769 return store.getRelationships( | |
770 elementA, | |
771 relationship).then((List<Location> locations) { | |
772 assertLocations(locations, [locationA, locationB]); | |
773 }); | |
774 } | |
775 | |
776 test_removeContext() { | |
777 Location locationA = mockLocation(elementA); | |
778 Location locationB = mockLocation(elementB); | |
779 { | |
780 store.aboutToIndexDart(contextA, unitElementA); | |
781 store.recordRelationship(elementA, relationship, locationA); | |
782 store.doneIndex(); | |
783 } | |
784 { | |
785 store.aboutToIndexDart(contextA, unitElementB); | |
786 store.recordRelationship(elementA, relationship, locationB); | |
787 store.doneIndex(); | |
788 } | |
789 // "A" and "B" locations | |
790 return store.getRelationships( | |
791 elementA, | |
792 relationship).then((List<Location> locations) { | |
793 assertLocations(locations, [locationA, locationB]); | |
794 // remove "A" context | |
795 store.removeContext(contextA); | |
796 }).then((_) { | |
797 return store.getRelationships( | |
798 elementA, | |
799 relationship).then((List<Location> locations) { | |
800 assertLocations(locations, []); | |
801 }); | |
802 }); | |
803 } | |
804 | |
805 void test_removeContext_nullContext() { | |
806 store.removeContext(null); | |
807 } | |
808 | |
809 test_removeSource_library() { | |
810 Location locationA = mockLocation(elementA); | |
811 Location locationB = mockLocation(elementB); | |
812 Location locationC = mockLocation(elementC); | |
813 { | |
814 store.aboutToIndexDart(contextA, unitElementA); | |
815 store.recordRelationship(elementA, relationship, locationA); | |
816 store.doneIndex(); | |
817 } | |
818 { | |
819 store.aboutToIndexDart(contextA, unitElementB); | |
820 store.recordRelationship(elementA, relationship, locationB); | |
821 store.doneIndex(); | |
822 } | |
823 { | |
824 store.aboutToIndexDart(contextA, unitElementC); | |
825 store.recordRelationship(elementA, relationship, locationC); | |
826 store.doneIndex(); | |
827 } | |
828 // "A", "B" and "C" locations | |
829 return store.getRelationships( | |
830 elementA, | |
831 relationship).then((List<Location> locations) { | |
832 assertLocations(locations, [locationA, locationB, locationC]); | |
833 }).then((_) { | |
834 // remove "librarySource" | |
835 store.removeSource(contextA, librarySource); | |
836 return store.getRelationships( | |
837 elementA, | |
838 relationship).then((List<Location> locations) { | |
839 assertLocations(locations, []); | |
840 }); | |
841 }); | |
842 } | |
843 | |
844 void test_removeSource_nullContext() { | |
845 store.removeSource(null, sourceA); | |
846 } | |
847 | |
848 test_removeSource_unit() { | |
849 Location locationA = mockLocation(elementA); | |
850 Location locationB = mockLocation(elementB); | |
851 Location locationC = mockLocation(elementC); | |
852 { | |
853 store.aboutToIndexDart(contextA, unitElementA); | |
854 store.recordRelationship(elementA, relationship, locationA); | |
855 store.doneIndex(); | |
856 } | |
857 { | |
858 store.aboutToIndexDart(contextA, unitElementB); | |
859 store.recordRelationship(elementA, relationship, locationB); | |
860 store.doneIndex(); | |
861 } | |
862 { | |
863 store.aboutToIndexDart(contextA, unitElementC); | |
864 store.recordRelationship(elementA, relationship, locationC); | |
865 store.doneIndex(); | |
866 } | |
867 // "A", "B" and "C" locations | |
868 return store.getRelationships( | |
869 elementA, | |
870 relationship).then((List<Location> locations) { | |
871 assertLocations(locations, [locationA, locationB, locationC]); | |
872 }).then((_) { | |
873 // remove "A" source | |
874 store.removeSource(contextA, sourceA); | |
875 return store.getRelationships( | |
876 elementA, | |
877 relationship).then((List<Location> locations) { | |
878 assertLocations(locations, [locationB, locationC]); | |
879 }); | |
880 }); | |
881 } | |
882 | |
883 test_removeSources_library() { | |
884 Location locationA = mockLocation(elementA); | |
885 Location locationB = mockLocation(elementB); | |
886 { | |
887 store.aboutToIndexDart(contextA, unitElementA); | |
888 store.recordRelationship(elementA, relationship, locationA); | |
889 store.doneIndex(); | |
890 } | |
891 { | |
892 store.aboutToIndexDart(contextA, unitElementB); | |
893 store.recordRelationship(elementA, relationship, locationB); | |
894 store.doneIndex(); | |
895 } | |
896 // "A" and "B" locations | |
897 return store.getRelationships( | |
898 elementA, | |
899 relationship).then((List<Location> locations) { | |
900 assertLocations(locations, [locationA, locationB]); | |
901 }).then((_) { | |
902 // remove "librarySource" | |
903 store.removeSources(contextA, new SingleSourceContainer(librarySource)); | |
904 return store.getRelationships( | |
905 elementA, | |
906 relationship).then((List<Location> locations) { | |
907 assertLocations(locations, []); | |
908 }); | |
909 }); | |
910 } | |
911 | |
912 void test_removeSources_nullContext() { | |
913 store.removeSources(null, null); | |
914 } | |
915 | |
916 test_removeSources_unit() { | |
917 Location locationA = mockLocation(elementA); | |
918 Location locationB = mockLocation(elementB); | |
919 Location locationC = mockLocation(elementC); | |
920 { | |
921 store.aboutToIndexDart(contextA, unitElementA); | |
922 store.recordRelationship(elementA, relationship, locationA); | |
923 store.doneIndex(); | |
924 } | |
925 { | |
926 store.aboutToIndexDart(contextA, unitElementB); | |
927 store.recordRelationship(elementA, relationship, locationB); | |
928 store.doneIndex(); | |
929 } | |
930 { | |
931 store.aboutToIndexDart(contextA, unitElementC); | |
932 store.recordRelationship(elementA, relationship, locationC); | |
933 store.doneIndex(); | |
934 } | |
935 // "A", "B" and "C" locations | |
936 return store.getRelationships( | |
937 elementA, | |
938 relationship).then((List<Location> locations) { | |
939 assertLocations(locations, [locationA, locationB, locationC]); | |
940 }).then((_) { | |
941 // remove "A" source | |
942 store.removeSources(contextA, new SingleSourceContainer(sourceA)); | |
943 store.removeSource(contextA, sourceA); | |
944 return store.getRelationships( | |
945 elementA, | |
946 relationship).then((List<Location> locations) { | |
947 assertLocations(locations, [locationB, locationC]); | |
948 }); | |
949 }); | |
950 } | |
951 | |
952 test_universe_aboutToIndex() { | |
953 when(contextA.getElement(elementLocationA)).thenReturn(elementA); | |
954 when(contextB.getElement(elementLocationB)).thenReturn(elementB); | |
955 Location locationA = mockLocation(elementA); | |
956 Location locationB = mockLocation(elementB); | |
957 { | |
958 store.aboutToIndexDart(contextA, unitElementA); | |
959 store.recordRelationship( | |
960 UniverseElement.INSTANCE, | |
961 relationship, | |
962 locationA); | |
963 store.doneIndex(); | |
964 } | |
965 { | |
966 store.aboutToIndexDart(contextB, unitElementB); | |
967 store.recordRelationship( | |
968 UniverseElement.INSTANCE, | |
969 relationship, | |
970 locationB); | |
971 store.doneIndex(); | |
972 } | |
973 // get relationships | |
974 return store.getRelationships( | |
975 UniverseElement.INSTANCE, | |
976 relationship).then((List<Location> locations) { | |
977 assertLocations(locations, [locationA, locationB]); | |
978 }).then((_) { | |
979 // re-index "unitElementA" | |
980 store.aboutToIndexDart(contextA, unitElementA); | |
981 store.doneIndex(); | |
982 return store.getRelationships( | |
983 UniverseElement.INSTANCE, | |
984 relationship).then((List<Location> locations) { | |
985 assertLocations(locations, [locationB]); | |
986 }); | |
987 }); | |
988 } | |
989 | |
990 test_universe_clear() { | |
991 when(contextA.getElement(elementLocationA)).thenReturn(elementA); | |
992 when(contextB.getElement(elementLocationB)).thenReturn(elementB); | |
993 Location locationA = mockLocation(elementA); | |
994 Location locationB = mockLocation(elementB); | |
995 { | |
996 store.aboutToIndexDart(contextA, unitElementA); | |
997 store.recordRelationship( | |
998 UniverseElement.INSTANCE, | |
999 relationship, | |
1000 locationA); | |
1001 store.doneIndex(); | |
1002 } | |
1003 { | |
1004 store.aboutToIndexDart(contextA, unitElementB); | |
1005 store.recordRelationship( | |
1006 UniverseElement.INSTANCE, | |
1007 relationship, | |
1008 locationB); | |
1009 store.doneIndex(); | |
1010 } | |
1011 return store.getRelationships( | |
1012 UniverseElement.INSTANCE, | |
1013 relationship).then((List<Location> locations) { | |
1014 assertLocations(locations, [locationA, locationB]); | |
1015 }).then((_) { | |
1016 // clear | |
1017 store.clear(); | |
1018 return store.getRelationships( | |
1019 UniverseElement.INSTANCE, | |
1020 relationship).then((List<Location> locations) { | |
1021 expect(locations, isEmpty); | |
1022 }); | |
1023 }); | |
1024 } | |
1025 | |
1026 test_universe_removeContext() { | |
1027 when(contextA.getElement(elementLocationA)).thenReturn(elementA); | |
1028 when(contextB.getElement(elementLocationB)).thenReturn(elementB); | |
1029 Location locationA = mockLocation(elementA); | |
1030 Location locationB = mockLocation(elementB); | |
1031 { | |
1032 store.aboutToIndexDart(contextA, unitElementA); | |
1033 store.recordRelationship( | |
1034 UniverseElement.INSTANCE, | |
1035 relationship, | |
1036 locationA); | |
1037 store.doneIndex(); | |
1038 } | |
1039 { | |
1040 store.aboutToIndexDart(contextB, unitElementB); | |
1041 store.recordRelationship( | |
1042 UniverseElement.INSTANCE, | |
1043 relationship, | |
1044 locationB); | |
1045 store.doneIndex(); | |
1046 } | |
1047 return store.getRelationships( | |
1048 UniverseElement.INSTANCE, | |
1049 relationship).then((List<Location> locations) { | |
1050 assertLocations(locations, [locationA, locationB]); | |
1051 }).then((_) { | |
1052 // remove "contextA" | |
1053 store.removeContext(contextA); | |
1054 return store.getRelationships( | |
1055 UniverseElement.INSTANCE, | |
1056 relationship).then((List<Location> locations) { | |
1057 assertLocations(locations, [locationB]); | |
1058 }); | |
1059 }); | |
1060 } | |
1061 | |
1062 test_universe_removeSource() { | |
1063 when(contextA.getElement(elementLocationA)).thenReturn(elementA); | |
1064 when(contextB.getElement(elementLocationB)).thenReturn(elementB); | |
1065 Location locationA = mockLocation(elementA); | |
1066 Location locationB = mockLocation(elementB); | |
1067 { | |
1068 store.aboutToIndexDart(contextA, unitElementA); | |
1069 store.recordRelationship( | |
1070 UniverseElement.INSTANCE, | |
1071 relationship, | |
1072 locationA); | |
1073 store.doneIndex(); | |
1074 } | |
1075 { | |
1076 store.aboutToIndexDart(contextA, unitElementB); | |
1077 store.recordRelationship( | |
1078 UniverseElement.INSTANCE, | |
1079 relationship, | |
1080 locationB); | |
1081 store.doneIndex(); | |
1082 } | |
1083 return store.getRelationships( | |
1084 UniverseElement.INSTANCE, | |
1085 relationship).then((List<Location> locations) { | |
1086 assertLocations(locations, [locationA, locationB]); | |
1087 }).then((_) { | |
1088 // remove "sourceA" | |
1089 store.removeSource(contextA, sourceA); | |
1090 return store.getRelationships( | |
1091 UniverseElement.INSTANCE, | |
1092 relationship).then((List<Location> locations) { | |
1093 assertLocations(locations, [locationB]); | |
1094 }); | |
1095 }); | |
1096 } | |
1097 | |
1098 /** | |
1099 * Asserts that the [actual] locations have all the [expected] locations and | |
1100 * only them. | |
1101 */ | |
1102 static void assertLocations(List<Location> actual, List<Location> expected) { | |
1103 List<_LocationEqualsWrapper> actualWrappers = wrapLocations(actual); | |
1104 List<_LocationEqualsWrapper> expectedWrappers = wrapLocations(expected); | |
1105 expect(actualWrappers, unorderedEquals(expectedWrappers)); | |
1106 } | |
1107 | |
1108 /** | |
1109 * @return the new [Location] mock. | |
1110 */ | |
1111 static Location mockLocation(Element element) { | |
1112 Location location = new MockLocation(); | |
1113 when(location.element).thenReturn(element); | |
1114 when(location.offset).thenReturn(0); | |
1115 when(location.length).thenReturn(0); | |
1116 when(location.isQualified).thenReturn(true); | |
1117 when(location.isResolved).thenReturn(true); | |
1118 return location; | |
1119 } | |
1120 | |
1121 /** | |
1122 * Wraps the given locations into [LocationEqualsWrapper]. | |
1123 */ | |
1124 static List<_LocationEqualsWrapper> wrapLocations(List<Location> locations) { | |
1125 List<_LocationEqualsWrapper> wrappers = <_LocationEqualsWrapper>[]; | |
1126 for (Location location in locations) { | |
1127 wrappers.add(new _LocationEqualsWrapper(location)); | |
1128 } | |
1129 return wrappers; | |
1130 } | |
1131 } | |
OLD | NEW |