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