| 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.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 } |
| OLD | NEW |