// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library test.services.src.index.store.split_store;

import 'dart:async';

import 'package:analysis_server/src/provisional/index/index_core.dart';
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analysis_server/src/services/index/indexable_element.dart';
import 'package:analysis_server/src/services/index/store/codec.dart';
import 'package:analysis_server/src/services/index/store/memory_node_manager.dart';
import 'package:analysis_server/src/services/index/store/split_store.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:typed_mock/typed_mock.dart';
import 'package:unittest/unittest.dart';

import '../../../mocks.dart';
import '../../../utils.dart';
import 'mocks.dart';
import 'single_source_container.dart';

main() {
  initializeTestEnvironment();
  defineReflectiveTests(_FileNodeManagerTest);
  defineReflectiveTests(_IndexNodeTest);
  defineReflectiveTests(_LocationDataTest);
  defineReflectiveTests(_RelationKeyDataTest);
  defineReflectiveTests(_SplitIndexStoreTest);
}

void _assertHasLocation(List<LocationImpl> locations, IndexableElement element,
    int offset, int length,
    {bool isQualified: false, bool isResolved: true}) {
  for (LocationImpl location in locations) {
    if ((element == null || location.indexable == element) &&
        location.offset == offset &&
        location.length == length &&
        location.isQualified == isQualified &&
        location.isResolved == isResolved) {
      return;
    }
  }
  fail('Expected to find Location'
      '(element=$element, offset=$offset, length=$length)');
}

void _assertHasLocationQ(List<LocationImpl> locations, IndexableElement element,
    int offset, int length) {
  _assertHasLocation(locations, element, offset, length, isQualified: true);
}

@reflectiveTest
class _FileNodeManagerTest {
  MockLogger logger = new MockLogger();
  StringCodec stringCodec = new StringCodec();
  RelationshipCodec relationshipCodec;

  AnalysisContext context = new MockAnalysisContext('context');
  ContextCodec contextCodec = new MockContextCodec();
  int contextId = 13;

  ElementCodec elementCodec = new MockElementCodec();
  int nextElementId = 0;

  FileNodeManager nodeManager;
  FileManager fileManager = new _MockFileManager();

  void setUp() {
    relationshipCodec = new RelationshipCodec(stringCodec);
    nodeManager = new FileNodeManager(fileManager, logger, stringCodec,
        contextCodec, elementCodec, relationshipCodec);
    when(contextCodec.encode(context)).thenReturn(contextId);
    when(contextCodec.decode(contextId)).thenReturn(context);
  }

  void test_clear() {
    nodeManager.clear();
    verify(fileManager.clear()).once();
  }

  void test_getLocationCount_empty() {
    expect(nodeManager.locationCount, 0);
  }

  void test_getNode_contextNull() {
    String name = '42.index';
    // record bytes
    List<int> bytes;
    when(fileManager.write(name, anyObject)).thenInvoke((name, bs) {
      bytes = bs;
    });
    // put Node
    Future putFuture;
    {
      IndexNode node = new IndexNode(context, elementCodec, relationshipCodec);
      putFuture = nodeManager.putNode(name, node);
    }
    // do in the "put" Future
    putFuture.then((_) {
      // force "null" context
      when(contextCodec.decode(contextId)).thenReturn(null);
      // prepare input bytes
      when(fileManager.read(name)).thenReturn(new Future.value(bytes));
      // get Node
      return nodeManager.getNode(name).then((IndexNode node) {
        expect(node, isNull);
        // no exceptions
        verifyZeroInteractions(logger);
      });
    });
  }

  test_getNode_invalidVersion() {
    String name = '42.index';
    // prepare a stream with an invalid version
    when(fileManager.read(name))
        .thenReturn(new Future.value([0x01, 0x02, 0x03, 0x04]));
    // do in the Future
    return nodeManager.getNode(name).then((IndexNode node) {
      // no IndexNode
      expect(node, isNull);
      // failed
      verify(logger.logError(anyObject, anyObject)).once();
    });
  }

  test_getNode_streamException() {
    String name = '42.index';
    when(fileManager.read(name)).thenReturn(new Future(() {
      return throw new Exception();
    }));
    // do in the Future
    return nodeManager.getNode(name).then((IndexNode node) {
      expect(node, isNull);
      // failed
      verify(logger.logError(anyString, anyObject)).once();
    });
  }

  test_getNode_streamNull() {
    String name = '42.index';
    when(fileManager.read(name)).thenReturn(new Future.value(null));
    // do in the Future
    return nodeManager.getNode(name).then((IndexNode node) {
      expect(node, isNull);
      // OK
      verifyZeroInteractions(logger);
    });
  }

  void test_newNode() {
    IndexNode node = nodeManager.newNode(context);
    expect(node.context, context);
    expect(node.locationCount, 0);
  }

  test_putNode_getNode() {
    String name = '42.index';
    // record bytes
    List<int> bytes;
    when(fileManager.write(name, anyObject)).thenInvoke((name, bs) {
      bytes = bs;
    });
    // prepare elements
    IndexableElement elementA = _mockElement();
    IndexableElement elementB = _mockElement();
    IndexableElement elementC = _mockElement();
    RelationshipImpl relationship =
        RelationshipImpl.getRelationship('my-relationship');
    // put Node
    Future putFuture;
    {
      // prepare relations
      int relationshipId = relationshipCodec.encode(relationship);
      RelationKeyData key =
          new RelationKeyData.forData(0, 1, 2, relationshipId);
      List<LocationData> locations = [
        new LocationData.forData(3, 4, 5, 1, 10, 2),
        new LocationData.forData(6, 7, 8, 2, 20, 3)
      ];
      Map<RelationKeyData, List<LocationData>> relations = {key: locations};
      // prepare Node
      IndexNode node = new _MockIndexNode();
      when(node.context).thenReturn(context);
      when(node.relations).thenReturn(relations);
      when(node.locationCount).thenReturn(2);
      // put Node
      putFuture = nodeManager.putNode(name, node);
    }
    // do in the Future
    putFuture.then((_) {
      // has locations
      expect(nodeManager.locationCount, 2);
      // prepare input bytes
      when(fileManager.read(name)).thenReturn(new Future.value(bytes));
      // get Node
      return nodeManager.getNode(name).then((IndexNode node) {
        expect(2, node.locationCount);
        {
          List<LocationImpl> locations =
              node.getRelationships(elementA, relationship);
          expect(locations, hasLength(2));
          _assertHasLocation(locations, elementB, 1, 10);
          _assertHasLocationQ(locations, elementC, 2, 20);
        }
      });
    });
  }

  test_putNode_streamException() {
    String name = '42.index';
    Exception exception = new Exception();
    when(fileManager.write(name, anyObject)).thenReturn(new Future(() {
      return throw exception;
    }));
    // prepare IndexNode
    IndexNode node = new _MockIndexNode();
    when(node.context).thenReturn(context);
    when(node.locationCount).thenReturn(0);
    when(node.relations).thenReturn({});
    // try to put
    return nodeManager.putNode(name, node).then((_) {
      // failed
      verify(logger.logError(anyString, anyObject)).once();
    });
  }

  void test_removeNode() {
    String name = '42.index';
    nodeManager.removeNode(name);
    verify(fileManager.delete(name)).once();
  }

  IndexableElement _mockElement() {
    int id1 = nextElementId++;
    int id2 = nextElementId++;
    int id3 = nextElementId++;
    Element element = new MockElement();
    IndexableObject indexable = new IndexableElement(element);
    when(elementCodec.encode1(indexable)).thenReturn(id1);
    when(elementCodec.encode2(indexable)).thenReturn(id2);
    when(elementCodec.encode3(indexable)).thenReturn(id3);
    when(elementCodec.decode(context, id1, id2, id3)).thenReturn(indexable);
    return indexable;
  }
}

@reflectiveTest
class _IndexNodeTest {
  AnalysisContext context = new MockAnalysisContext('context');
  ElementCodec elementCodec = new MockElementCodec();
  int nextElementId = 0;
  IndexNode node;
  RelationshipCodec relationshipCodec;
  StringCodec stringCodec = new StringCodec();

  void setUp() {
    relationshipCodec = new RelationshipCodec(stringCodec);
    node = new IndexNode(context, elementCodec, relationshipCodec);
  }

  void test_getContext() {
    expect(node.context, context);
  }

  void test_recordRelationship() {
    IndexableElement elementA = _mockElement();
    IndexableElement elementB = _mockElement();
    IndexableElement elementC = _mockElement();
    RelationshipImpl relationship =
        RelationshipImpl.getRelationship('my-relationship');
    LocationImpl locationA = new LocationImpl(elementB, 1, 2);
    LocationImpl locationB = new LocationImpl(elementC, 10, 20);
    // empty initially
    expect(node.locationCount, 0);
    // record
    node.recordRelationship(elementA, relationship, locationA);
    expect(node.locationCount, 1);
    node.recordRelationship(elementA, relationship, locationB);
    expect(node.locationCount, 2);
    // get relations
    expect(node.getRelationships(elementB, relationship), isEmpty);
    {
      List<LocationImpl> locations =
          node.getRelationships(elementA, relationship);
      expect(locations, hasLength(2));
      _assertHasLocation(locations, null, 1, 2);
      _assertHasLocation(locations, null, 10, 20);
    }
    // verify relations map
    {
      Map<RelationKeyData, List<LocationData>> relations = node.relations;
      expect(relations, hasLength(1));
      List<LocationData> locations = relations.values.first;
      expect(locations, hasLength(2));
    }
  }

  void test_setRelations() {
    IndexableElement elementA = _mockElement();
    IndexableElement elementB = _mockElement();
    IndexableElement elementC = _mockElement();
    RelationshipImpl relationship =
        RelationshipImpl.getRelationship('my-relationship');
    // record
    {
      int relationshipId = relationshipCodec.encode(relationship);
      RelationKeyData key =
          new RelationKeyData.forData(0, 1, 2, relationshipId);
      List<LocationData> locations = [
        new LocationData.forData(3, 4, 5, 1, 10, 2),
        new LocationData.forData(6, 7, 8, 2, 20, 3)
      ];
      node.relations = {key: locations};
    }
    // request
    List<LocationImpl> locations =
        node.getRelationships(elementA, relationship);
    expect(locations, hasLength(2));
    _assertHasLocation(locations, elementB, 1, 10);
    _assertHasLocationQ(locations, elementC, 2, 20);
  }

  IndexableElement _mockElement() {
    int id1 = nextElementId++;
    int id2 = nextElementId++;
    int id3 = nextElementId++;
    Element element = new MockElement();
    IndexableElement indexable = new IndexableElement(element);
    when(elementCodec.encode1(indexable)).thenReturn(id1);
    when(elementCodec.encode2(indexable)).thenReturn(id2);
    when(elementCodec.encode3(indexable)).thenReturn(id3);
    when(elementCodec.decode(context, id1, id2, id3)).thenReturn(indexable);
    return indexable;
  }
}

@reflectiveTest
class _LocationDataTest {
  AnalysisContext context = new MockAnalysisContext('context');
  ElementCodec elementCodec = new MockElementCodec();
  StringCodec stringCodec = new StringCodec();

  void test_newForData() {
    Element element = new MockElement();
    IndexableElement indexable = new IndexableElement(element);
    when(elementCodec.decode(context, 11, 12, 13)).thenReturn(indexable);
    LocationData locationData = new LocationData.forData(11, 12, 13, 1, 2, 0);
    LocationImpl location = locationData.getLocation(context, elementCodec);
    expect(location.indexable, indexable);
    expect(location.offset, 1);
    expect(location.length, 2);
    expect(location.isQualified, isFalse);
    expect(location.isResolved, isFalse);
  }

  void test_newForObject() {
    // prepare Element
    Element element = new MockElement();
    IndexableElement indexable = new IndexableElement(element);
    when(elementCodec.encode1(indexable)).thenReturn(11);
    when(elementCodec.encode2(indexable)).thenReturn(12);
    when(elementCodec.encode3(indexable)).thenReturn(13);
    when(elementCodec.decode(context, 11, 12, 13)).thenReturn(indexable);
    // create
    LocationImpl location = new LocationImpl(indexable, 1, 2);
    LocationData locationData =
        new LocationData.forObject(elementCodec, location);
    // touch 'hashCode'
    locationData.hashCode;
    // ==
    expect(
        locationData == new LocationData.forData(11, 12, 13, 1, 2, 2), isTrue);
    // getLocation()
    {
      LocationImpl newLocation =
          locationData.getLocation(context, elementCodec);
      expect(newLocation.indexable, indexable);
      expect(newLocation.offset, 1);
      expect(newLocation.length, 2);
    }
    // no Element - no Location
    {
      when(elementCodec.decode(context, 11, 12, 13)).thenReturn(null);
      LocationImpl newLocation =
          locationData.getLocation(context, elementCodec);
      expect(newLocation, isNull);
    }
  }
}

/**
 * [LocationImpl] has no [==] and [hashCode], so to compare locations by value we
 * need to wrap them into such object.
 */
class _LocationEqualsWrapper {
  final LocationImpl location;

  _LocationEqualsWrapper(this.location);

  @override
  int get hashCode {
    return 31 * (31 * location.indexable.hashCode + location.offset) +
        location.length;
  }

  @override
  bool operator ==(Object other) {
    if (other is _LocationEqualsWrapper) {
      return other.location.offset == location.offset &&
          other.location.length == location.length &&
          other.location.indexable == location.indexable;
    }
    return false;
  }
}

class _MockFileManager extends TypedMock implements FileManager {}

class _MockIndexNode extends TypedMock implements IndexNode {}

@reflectiveTest
class _RelationKeyDataTest {
  AnalysisContext context = new MockAnalysisContext('context');
  ElementCodec elementCodec = new MockElementCodec();
  RelationshipCodec relationshipCodec = new MockRelationshipCodec();
  StringCodec stringCodec = new StringCodec();

  void test_newFromData() {
    RelationKeyData keyData = new RelationKeyData.forData(11, 12, 13, 2);
    // equals
    expect(keyData == this, isFalse);
    expect(keyData == new RelationKeyData.forData(11, 12, 13, 20), isFalse);
    expect(keyData == keyData, isTrue);
    expect(keyData == new RelationKeyData.forData(11, 12, 13, 2), isTrue);
  }

  void test_newFromObjects() {
    // prepare Element
    IndexableElement indexable;
    {
      Element element = new MockElement();
      indexable = new IndexableElement(element);
      ElementLocation location = new ElementLocationImpl.con3(['foo', 'bar']);
      when(element.location).thenReturn(location);
      when(context.getElement(location)).thenReturn(indexable);
      when(elementCodec.encode1(indexable)).thenReturn(11);
      when(elementCodec.encode2(indexable)).thenReturn(12);
      when(elementCodec.encode3(indexable)).thenReturn(13);
    }
    // prepare relationship
    RelationshipImpl relationship =
        RelationshipImpl.getRelationship('my-relationship');
    int relationshipId = 1;
    when(relationshipCodec.encode(relationship)).thenReturn(relationshipId);
    // create RelationKeyData
    RelationKeyData keyData = new RelationKeyData.forObject(
        elementCodec, relationshipCodec, indexable, relationship);
    // touch
    keyData.hashCode;
    // equals
    expect(keyData == this, isFalse);
    expect(keyData == new RelationKeyData.forData(11, 12, 13, 20), isFalse);
    expect(keyData == keyData, isTrue);
    expect(keyData == new RelationKeyData.forData(11, 12, 13, relationshipId),
        isTrue);
  }
}

@reflectiveTest
class _SplitIndexStoreTest {
  AnalysisContext contextA = new MockAnalysisContext('contextA');
  AnalysisContext contextB = new MockAnalysisContext('contextB');
  AnalysisContext contextC = new MockAnalysisContext('contextC');

  Element elementA = new MockElement('elementA');
  Element elementB = new MockElement('elementB');
  Element elementC = new MockElement('elementC');
  Element elementD = new MockElement('elementD');

  IndexableElement indexableA;
  IndexableElement indexableB;
  IndexableElement indexableC;
  IndexableElement indexableD;

  Source librarySource = new MockSource('librarySource');
  CompilationUnitElement libraryUnitElement = new MockCompilationUnitElement();
  LibraryElement libraryElement = new MockLibraryElement();

  Source librarySourceB = new MockSource('librarySourceB');
  LibraryElement libraryElementB = new MockLibraryElement();
  CompilationUnitElement libraryUnitElementB = new MockCompilationUnitElement();

  ElementCodec elementCodec = new MockElementCodec();
  MemoryNodeManager nodeManager = new MemoryNodeManager();
  RelationshipImpl relationship =
      RelationshipImpl.getRelationship('test-relationship');
  Source sourceA = new MockSource('sourceA');
  Source sourceB = new MockSource('sourceB');
  Source sourceC = new MockSource('sourceC');
  Source sourceD = new MockSource('sourceD');
  SplitIndexStore store;
  CompilationUnitElement unitElementA = new MockCompilationUnitElement();
  CompilationUnitElement unitElementB = new MockCompilationUnitElement();
  CompilationUnitElement unitElementC = new MockCompilationUnitElement();
  CompilationUnitElement unitElementD = new MockCompilationUnitElement();

  void setUp() {
    indexableA = new IndexableElement(elementA);
    indexableB = new IndexableElement(elementB);
    indexableC = new IndexableElement(elementC);
    indexableD = new IndexableElement(elementD);

    nodeManager.elementCodec = elementCodec;
    store = new SplitIndexStore(
        nodeManager, <IndexObjectManager>[new DartUnitIndexObjectManager()]);
    when(elementCodec.encode1(indexableA)).thenReturn(11);
    when(elementCodec.encode2(indexableA)).thenReturn(12);
    when(elementCodec.encode3(indexableA)).thenReturn(13);
    when(elementCodec.encode1(indexableB)).thenReturn(21);
    when(elementCodec.encode2(indexableB)).thenReturn(22);
    when(elementCodec.encode3(indexableB)).thenReturn(23);
    when(elementCodec.encode1(indexableC)).thenReturn(31);
    when(elementCodec.encode2(indexableC)).thenReturn(32);
    when(elementCodec.encode3(indexableC)).thenReturn(33);
    when(elementCodec.encode1(indexableD)).thenReturn(41);
    when(elementCodec.encode2(indexableD)).thenReturn(42);
    when(elementCodec.encode3(indexableD)).thenReturn(43);
    when(elementCodec.decode(contextA, 11, 12, 13)).thenReturn(indexableA);
    when(elementCodec.decode(contextA, 21, 22, 23)).thenReturn(indexableB);
    when(elementCodec.decode(contextA, 31, 32, 33)).thenReturn(indexableC);
    when(elementCodec.decode(contextA, 41, 42, 43)).thenReturn(indexableD);
    when(contextA.isDisposed).thenReturn(false);
    when(contextB.isDisposed).thenReturn(false);
    when(contextC.isDisposed).thenReturn(false);
    when(sourceA.fullName).thenReturn('/home/user/sourceA.dart');
    when(sourceB.fullName).thenReturn('/home/user/sourceB.dart');
    when(sourceC.fullName).thenReturn('/home/user/sourceC.dart');
    when(sourceD.fullName).thenReturn('/home/user/sourceD.dart');
    when(elementA.context).thenReturn(contextA);
    when(elementB.context).thenReturn(contextA);
    when(elementC.context).thenReturn(contextA);
    when(elementD.context).thenReturn(contextA);
    when(elementA.enclosingElement).thenReturn(unitElementA);
    when(elementB.enclosingElement).thenReturn(unitElementB);
    when(elementC.enclosingElement).thenReturn(unitElementC);
    when(elementD.enclosingElement).thenReturn(unitElementD);
    when(elementA.source).thenReturn(sourceA);
    when(elementB.source).thenReturn(sourceB);
    when(elementC.source).thenReturn(sourceC);
    when(elementD.source).thenReturn(sourceD);
    when(elementA.library).thenReturn(libraryElement);
    when(elementB.library).thenReturn(libraryElement);
    when(elementC.library).thenReturn(libraryElement);
    when(elementD.library).thenReturn(libraryElement);
    when(unitElementA.source).thenReturn(sourceA);
    when(unitElementB.source).thenReturn(sourceB);
    when(unitElementC.source).thenReturn(sourceC);
    when(unitElementD.source).thenReturn(sourceD);
    when(unitElementA.library).thenReturn(libraryElement);
    when(unitElementB.library).thenReturn(libraryElement);
    when(unitElementC.library).thenReturn(libraryElement);
    when(unitElementD.library).thenReturn(libraryElement);
    // library
    when(librarySource.fullName).thenReturn('/home/user/librarySource.dart');
    when(libraryUnitElement.library).thenReturn(libraryElement);
    when(libraryUnitElement.source).thenReturn(librarySource);
    when(libraryElement.source).thenReturn(librarySource);
    when(libraryElement.definingCompilationUnit).thenReturn(libraryUnitElement);
    // library B
    when(librarySourceB.fullName).thenReturn('/home/user/librarySource.dart');
    when(libraryUnitElementB.library).thenReturn(libraryElementB);
    when(libraryUnitElementB.source).thenReturn(librarySourceB);
    when(libraryElementB.source).thenReturn(librarySourceB);
    when(libraryElementB.definingCompilationUnit)
        .thenReturn(libraryUnitElementB);
  }

  void test_aboutToIndexDart_disposedContext() {
    when(contextA.isDisposed).thenReturn(true);
    expect(store.aboutToIndex(contextA, unitElementA), isFalse);
  }

  Future test_aboutToIndexDart_library_first() {
    when(libraryElement.parts)
        .thenReturn(<CompilationUnitElement>[unitElementA, unitElementB]);
    {
      store.aboutToIndex(contextA, libraryUnitElement);
      store.doneIndex();
    }
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, []);
    });
  }

  test_aboutToIndexDart_library_secondWithoutOneUnit() {
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableB);
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordRelationship(indexableA, relationship, locationA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordRelationship(indexableA, relationship, locationB);
      store.doneIndex();
    }
    // "A" and "B" locations
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, [locationA, locationB]);
      // apply "libraryUnitElement", only with "B"
      when(libraryElement.parts).thenReturn([unitElementB]);
      {
        store.aboutToIndex(contextA, libraryUnitElement);
        store.doneIndex();
      }
    }).then((_) {
      return store
          .getRelationships(indexableA, relationship)
          .then((List<LocationImpl> locations) {
        assertLocations(locations, [locationB]);
      });
    });
  }

  void test_aboutToIndexDart_nullContext() {
    expect(store.aboutToIndex(null, unitElementA), isFalse);
  }

  void test_aboutToIndexDart_nullLibraryElement() {
    when(unitElementA.library).thenReturn(null);
    expect(store.aboutToIndex(contextA, unitElementA), isFalse);
  }

  void test_aboutToIndexDart_nullLibraryUnitElement() {
    when(libraryElement.definingCompilationUnit).thenReturn(null);
    expect(store.aboutToIndex(contextA, unitElementA), isFalse);
  }

  void test_aboutToIndexDart_nullUnitElement() {
    expect(store.aboutToIndex(contextA, null), isFalse);
  }

  test_cancelIndexDart() {
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableA);
    store.aboutToIndex(contextA, unitElementA);
    store.recordRelationship(indexableA, relationship, locationA);
    store.recordRelationship(indexableA, relationship, locationB);
    store.recordTopLevelDeclaration(elementA);
    store.cancelIndex();
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, []);
      expect(store.getTopLevelDeclarations((name) => true), isEmpty);
    });
  }

  void test_clear() {
    LocationImpl locationA = mockLocation(indexableA);
    store.aboutToIndex(contextA, unitElementA);
    store.recordRelationship(indexableA, relationship, locationA);
    store.doneIndex();
    expect(nodeManager.isEmpty(), isFalse);
    // clear
    store.clear();
    expect(nodeManager.isEmpty(), isTrue);
  }

  test_getRelationships_empty() {
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      expect(locations, isEmpty);
    });
  }

  void test_getStatistics() {
    // empty initially
    {
      String statistics = store.statistics;
      expect(statistics, contains('0 locations'));
      expect(statistics, contains('0 sources'));
    }
    // add 2 locations
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableB);
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordRelationship(indexableA, relationship, locationA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordRelationship(indexableA, relationship, locationB);
      store.doneIndex();
    }
    {
      String statistics = store.statistics;
      expect(statistics, contains('2 locations'));
      expect(statistics, contains('3 sources'));
    }
  }

  void test_recordRelationship_multiplyDefinedElement() {
    Element multiplyElement =
        new MultiplyDefinedElementImpl(contextA, <Element>[elementA, elementB]);
    LocationImpl location = mockLocation(indexableA);
    store.recordRelationship(
        new IndexableElement(multiplyElement), relationship, location);
    store.doneIndex();
    expect(nodeManager.isEmpty(), isTrue);
  }

  void test_recordRelationship_nullElement() {
    LocationImpl locationA = mockLocation(indexableA);
    store.recordRelationship(null, relationship, locationA);
    store.doneIndex();
    expect(nodeManager.isEmpty(), isTrue);
  }

  void test_recordRelationship_nullLocation() {
    store.recordRelationship(indexableA, relationship, null);
    store.doneIndex();
    expect(nodeManager.isEmpty(), isTrue);
  }

  test_recordRelationship_oneElement_twoNodes() {
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableB);
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordRelationship(indexableA, relationship, locationA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordRelationship(indexableA, relationship, locationB);
      store.doneIndex();
    }
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, [locationA, locationB]);
    });
  }

  test_recordRelationship_oneLocation() {
    LocationImpl locationA = mockLocation(indexableA);
    store.aboutToIndex(contextA, unitElementA);
    store.recordRelationship(indexableA, relationship, locationA);
    store.doneIndex();
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, [locationA]);
    });
  }

  test_recordRelationship_twoLocations() {
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableA);
    store.aboutToIndex(contextA, unitElementA);
    store.recordRelationship(indexableA, relationship, locationA);
    store.recordRelationship(indexableA, relationship, locationB);
    store.doneIndex();
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, [locationA, locationB]);
    });
  }

  test_removeContext() {
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableB);
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordRelationship(indexableA, relationship, locationA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordRelationship(indexableA, relationship, locationB);
      store.doneIndex();
    }
    // "A" and "B" locations
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, [locationA, locationB]);
      // remove "A" context
      store.removeContext(contextA);
    }).then((_) {
      return store
          .getRelationships(indexableA, relationship)
          .then((List<LocationImpl> locations) {
        assertLocations(locations, []);
      });
    });
  }

  void test_removeContext_nullContext() {
    store.removeContext(null);
  }

  test_removeSource_library() async {
    when(elementB.library).thenReturn(libraryElementB);
    when(unitElementB.library).thenReturn(libraryElementB);
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableB);
    LocationImpl locationC = mockLocation(indexableC);
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordRelationship(indexableD, relationship, locationA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordRelationship(indexableD, relationship, locationB);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementC);
      store.recordRelationship(indexableD, relationship, locationC);
      store.doneIndex();
    }
    // "A", "B" and "C" locations
    {
      var locations = await store.getRelationships(indexableD, relationship);
      assertLocations(locations, [locationA, locationB, locationC]);
    }
    // remove "librarySource"
    store.removeSource(contextA, librarySource);
    // only "B" location, which is in "librarySourceB"
    {
      var locations = await store.getRelationships(indexableD, relationship);
      assertLocations(locations, [locationB]);
    }
  }

  void test_removeSource_nullContext() {
    store.removeSource(null, sourceA);
  }

  test_removeSource_unit() {
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableB);
    LocationImpl locationC = mockLocation(indexableC);
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordRelationship(indexableA, relationship, locationA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordRelationship(indexableA, relationship, locationB);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementC);
      store.recordRelationship(indexableA, relationship, locationC);
      store.doneIndex();
    }
    // "A", "B" and "C" locations
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, [locationA, locationB, locationC]);
    }).then((_) {
      // remove "A" source
      store.removeSource(contextA, sourceA);
      return store
          .getRelationships(indexableA, relationship)
          .then((List<LocationImpl> locations) {
        assertLocations(locations, [locationB, locationC]);
      });
    });
  }

  test_removeSources_library() {
    LocationImpl locationA = mockLocation(indexableA);
    LocationImpl locationB = mockLocation(indexableB);
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordRelationship(indexableA, relationship, locationA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordRelationship(indexableA, relationship, locationB);
      store.doneIndex();
    }
    // "A" and "B" locations
    return store
        .getRelationships(indexableA, relationship)
        .then((List<LocationImpl> locations) {
      assertLocations(locations, [locationA, locationB]);
    }).then((_) {
      // remove "librarySource"
      store.removeSources(contextA, new SingleSourceContainer(librarySource));
      return store
          .getRelationships(indexableA, relationship)
          .then((List<LocationImpl> locations) {
        assertLocations(locations, []);
      });
    });
  }

  void test_removeSources_nullContext() {
    store.removeSources(null, null);
  }

  void test_removeSources_unit() {
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordTopLevelDeclaration(elementA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementB);
      store.recordTopLevelDeclaration(elementB);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextA, unitElementC);
      store.recordTopLevelDeclaration(elementC);
      store.doneIndex();
    }
    // A, B, C elements
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementA, elementB, elementC]));
    }
    // remove "A" source
    store.removeSources(contextA, new SingleSourceContainer(sourceA));
    store.removeSource(contextA, sourceA);
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementB, elementC]));
    }
  }

  void test_universe_aboutToIndex() {
    when(elementCodec.decode(contextA, 11, 12, 13))
        .thenReturn(new IndexableElement(elementA));
    when(elementCodec.decode(contextB, 21, 22, 23))
        .thenReturn(new IndexableElement(elementB));
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordTopLevelDeclaration(elementA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextB, unitElementB);
      store.recordTopLevelDeclaration(elementB);
      store.doneIndex();
    }
    // elementA, elementB
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementA, elementB]));
    }
    // re-index "unitElementA"
    {
      store.aboutToIndex(contextA, unitElementA);
      store.doneIndex();
    }
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementB]));
    }
  }

  void test_universe_clear() {
    when(elementCodec.decode(contextA, 11, 12, 13))
        .thenReturn(new IndexableElement(elementA));
    when(elementCodec.decode(contextB, 21, 22, 23))
        .thenReturn(new IndexableElement(elementB));
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordTopLevelDeclaration(elementA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextB, unitElementB);
      store.recordTopLevelDeclaration(elementB);
      store.doneIndex();
    }
    // elementA, elementB
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementA, elementB]));
    }
    // clear
    store.clear();
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, isEmpty);
    }
  }

  void test_universe_removeContext() {
    when(elementCodec.decode(contextA, 11, 12, 13))
        .thenReturn(new IndexableElement(elementA));
    when(elementCodec.decode(contextB, 21, 22, 23))
        .thenReturn(new IndexableElement(elementB));
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordTopLevelDeclaration(elementA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextB, unitElementB);
      store.recordTopLevelDeclaration(elementB);
      store.doneIndex();
    }
    // elementA, elementB
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementA, elementB]));
    }
    // remove "contextA"
    store.removeContext(contextA);
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementB]));
    }
  }

  void test_universe_removeSource() {
    when(elementCodec.decode(contextA, 11, 12, 13))
        .thenReturn(new IndexableElement(elementA));
    when(elementCodec.decode(contextB, 21, 22, 23))
        .thenReturn(new IndexableElement(elementB));
    {
      store.aboutToIndex(contextA, unitElementA);
      store.recordTopLevelDeclaration(elementA);
      store.doneIndex();
    }
    {
      store.aboutToIndex(contextB, unitElementB);
      store.recordTopLevelDeclaration(elementB);
      store.doneIndex();
    }
    // elementA, elementB
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementA, elementB]));
    }
    // remove "sourceA"
    store.removeSource(contextA, sourceA);
    {
      List<Element> elements = store.getTopLevelDeclarations(anyName);
      expect(elements, unorderedEquals([elementB]));
    }
  }

  static bool anyName(String name) => true;

  /**
   * Asserts that the [actual] locations have all the [expected] locations and
   * only them.
   */
  static void assertLocations(
      List<LocationImpl> actual, List<LocationImpl> expected) {
    List<_LocationEqualsWrapper> actualWrappers = wrapLocations(actual);
    List<_LocationEqualsWrapper> expectedWrappers = wrapLocations(expected);
    expect(actualWrappers, unorderedEquals(expectedWrappers));
  }

  /**
   * @return the new [LocationImpl] mock.
   */
  static LocationImpl mockLocation(IndexableElement indexable) {
    LocationImpl location = new MockLocation();
    when(location.indexable).thenReturn(indexable);
    when(location.offset).thenReturn(0);
    when(location.length).thenReturn(0);
    when(location.isQualified).thenReturn(true);
    when(location.isResolved).thenReturn(true);
    return location;
  }

  /**
   * Wraps the given locations into [LocationEqualsWrapper].
   */
  static List<_LocationEqualsWrapper> wrapLocations(
      List<LocationImpl> locations) {
    List<_LocationEqualsWrapper> wrappers = <_LocationEqualsWrapper>[];
    for (LocationImpl location in locations) {
      wrappers.add(new _LocationEqualsWrapper(location));
    }
    return wrappers;
  }
}
