blob: e9ed6267371a465f8f546aead4547019c59a09e0 [file] [log] [blame]
// 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.codec;
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analysis_server/src/services/index/store/codec.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:unittest/unittest.dart';
import '../../../abstract_single_unit.dart';
import '../../../mocks.dart';
import '../../../reflective_tests.dart';
main() {
groupSep = ' | ';
runReflectiveTests(_ContextCodecTest);
runReflectiveTests(_ElementCodecTest);
runReflectiveTests(_RelationshipCodecTest);
runReflectiveTests(_StringCodecTest);
}
@reflectiveTest
class _ContextCodecTest {
ContextCodec codec = new ContextCodec();
void test_encode_decode() {
AnalysisContext contextA = new MockAnalysisContext('contextA');
AnalysisContext contextB = new MockAnalysisContext('contextB');
int idA = codec.encode(contextA);
int idB = codec.encode(contextB);
expect(idA, codec.encode(contextA));
expect(idB, codec.encode(contextB));
expect(codec.decode(idA), contextA);
expect(codec.decode(idB), contextB);
}
void test_remove() {
// encode
{
AnalysisContext context = new MockAnalysisContext('context');
// encode
int id = codec.encode(context);
expect(id, 0);
expect(codec.decode(id), context);
// remove
codec.remove(context);
expect(codec.decode(id), isNull);
}
// encode again
{
AnalysisContext context = new MockAnalysisContext('context');
// encode
int id = codec.encode(context);
expect(id, 1);
expect(codec.decode(id), context);
}
}
}
@reflectiveTest
class _ElementCodecTest extends AbstractSingleUnitTest {
ElementCodec codec;
AnalysisContext context = new MockAnalysisContext('context');
StringCodec stringCodec = new StringCodec();
void setUp() {
super.setUp();
codec = new ElementCodec(stringCodec);
}
void test_encodeHash_notLocal() {
resolveTestUnit('''
class A {
void mainA() {
int foo; // A
}
void mainB() {
int foo; // B
int bar;
}
}
''');
MethodElement mainA = findElement('mainA');
MethodElement mainB = findElement('mainB');
Element fooA = mainA.localVariables[0];
Element fooB = mainB.localVariables[0];
Element bar = mainB.localVariables[1];
int id_fooA = codec.encodeHash(fooA);
int id_fooB = codec.encodeHash(fooB);
int id_bar = codec.encodeHash(bar);
expect(id_fooA == id_fooB, isTrue);
expect(id_fooA == id_bar, isFalse);
}
void test_field() {
resolveTestUnit('''
class A {
int field;
}
''');
FieldElement field = findElement('field', ElementKind.FIELD);
PropertyAccessorElement getter = field.getter;
PropertyAccessorElement setter = field.setter;
{
int id = codec.encode(getter, false);
expect(codec.decode(context, id), getter);
}
{
int id = codec.encode(setter, false);
expect(codec.decode(context, id), setter);
}
{
int id = codec.encode(field, false);
expect(codec.decode(context, id), field);
}
}
void test_filePackage_uriMix() {
MethodElement buildMethodElement(Source source) {
CompilationUnitElementImpl unitElement = new CompilationUnitElementImpl('file.dart');
LibraryElementImpl libraryElement = new LibraryElementImpl(null, 'lib', 0);
ClassElementImpl classElement = new ClassElementImpl('A', 0);
MethodElementImpl methodElement = new MethodElementImpl('m', 0);
unitElement.source = source;
libraryElement.definingCompilationUnit = unitElement;
unitElement.types = [classElement];
classElement.methods = [methodElement];
return methodElement;
}
// file:
int fileId;
{
Source source = new _TestSource('/my/file.dart', 'file:///my/file.dart');
var methodElement = buildMethodElement(source);
fileId = codec.encode(methodElement, true);
}
// package:
int packageId;
{
Source source = new _TestSource('/my/file.dart', 'package:my_pkg/file.dart');
var methodElement = buildMethodElement(source);
packageId = codec.encode(methodElement, true);
}
// should be the same
expect(packageId, fileId);
}
void test_localLocalVariable() {
resolveTestUnit('''
main() {
{
foo() {
int bar; // A
}
}
{
foo() {
int bar; // B
}
}
}
''');
{
LocalVariableElement element = findNodeElementAtString('bar; // A', null);
int id = codec.encode(element, false);
expect(codec.decode(context, id), element);
}
{
LocalVariableElement element = findNodeElementAtString('bar; // B', null);
int id = codec.encode(element, false);
expect(codec.decode(context, id), element);
}
// check strings, "foo" as a single string, no "foo@17" or "bar@35"
expect(stringCodec.nameToIndex, hasLength(4));
expect(stringCodec.nameToIndex, containsPair('file:///test.dart', 0));
expect(stringCodec.nameToIndex, containsPair('main', 1));
expect(stringCodec.nameToIndex, containsPair('foo', 2));
expect(stringCodec.nameToIndex, containsPair('bar', 3));
}
void test_localVariable() {
resolveTestUnit('''
main() {
{
int foo; // A
}
{
int foo; // B
}
}
''');
{
LocalVariableElement element = findNodeElementAtString('foo; // A', null);
int id = codec.encode(element, false);
expect(codec.decode(context, id), element);
}
{
LocalVariableElement element = findNodeElementAtString('foo; // B', null);
int id = codec.encode(element, false);
expect(codec.decode(context, id), element);
}
// check strings, "foo" as a single string, no "foo@21" or "foo@47"
expect(stringCodec.nameToIndex, hasLength(3));
expect(stringCodec.nameToIndex, containsPair('file:///test.dart', 0));
expect(stringCodec.nameToIndex, containsPair('main', 1));
expect(stringCodec.nameToIndex, containsPair('foo', 2));
}
void test_notLocal() {
resolveTestUnit('''
main() {
int foo;
}
''');
LocalVariableElement element = findElement('foo');
int id = codec.encode(element, false);
expect(codec.encode(element, false), id);
expect(codec.decode(context, id), element);
// check strings
expect(stringCodec.nameToIndex, hasLength(3));
expect(stringCodec.nameToIndex, containsPair('file:///test.dart', 0));
expect(stringCodec.nameToIndex, containsPair('main', 1));
expect(stringCodec.nameToIndex, containsPair('foo', 2));
}
}
@reflectiveTest
class _RelationshipCodecTest {
StringCodec stringCodec = new StringCodec();
RelationshipCodec codec;
void setUp() {
codec = new RelationshipCodec(stringCodec);
}
void test_all() {
Relationship relationship = Relationship.getRelationship('my-relationship');
int id = codec.encode(relationship);
expect(codec.decode(id), relationship);
}
}
@reflectiveTest
class _StringCodecTest {
StringCodec codec = new StringCodec();
void test_all() {
int idA = codec.encode('aaa');
int idB = codec.encode('bbb');
expect(codec.decode(idA), 'aaa');
expect(codec.decode(idB), 'bbb');
}
}
class _TestSource implements Source {
final String fullName;
final String encoding;
_TestSource(this.fullName, this.encoding);
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}