// 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/analysis/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 {
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

class _MockIndexNode extends TypedMock implements IndexNode {
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

@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_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;
  }
}
