blob: 73266b957286234db50a47c71ae669ff0831ec0b [file] [log] [blame]
// Copyright (c) 2016, 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.
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ResynthesizerResultProviderTest);
defineReflectiveTests(SummaryDataStoreTest);
});
}
/// A matcher for ConflictingSummaryException.
const Matcher isConflictingSummaryException =
const _ConflictingSummaryException();
UnlinkedPublicNamespace _namespaceWithParts(List<String> parts) {
UnlinkedPublicNamespace namespace = new _UnlinkedPublicNamespaceMock();
when(namespace.parts).thenReturn(parts);
return namespace;
}
@reflectiveTest
class ResynthesizerResultProviderTest {
SourceFactory sourceFactory = new _SourceFactoryMock();
InternalAnalysisContext context = new _InternalAnalysisContextMock();
UniversalCachePartition cachePartition;
Source source1 = new _SourceMock('package:p1/u1.dart', '/p1/lib/u1.dart');
Source source2 = new _SourceMock('package:p1/u2.dart', '/p1/lib/u2.dart');
Source source3 = new _SourceMock('package:p2/u1.dart', '/p2/lib/u1.dart');
CacheEntry entry1;
CacheEntry entry2;
CacheEntry entry3;
PackageBundle bundle = new _PackageBundleMock();
UnlinkedUnit unlinkedUnit1 = new _UnlinkedUnitMock();
UnlinkedUnit unlinkedUnit2 = new _UnlinkedUnitMock();
LinkedLibrary linkedLibrary = new _LinkedLibraryMock();
SummaryDataStore dataStore = new SummaryDataStore(<String>[]);
_TestResynthesizerResultProvider provider;
void setUp() {
cachePartition = new UniversalCachePartition(context);
entry1 = new CacheEntry(source1);
entry2 = new CacheEntry(source2);
entry3 = new CacheEntry(source3);
cachePartition.put(entry1);
cachePartition.put(entry2);
cachePartition.put(entry3);
when(sourceFactory.resolveUri(any, 'package:p1/u1.dart'))
.thenReturn(source1);
when(sourceFactory.resolveUri(any, 'package:p1/u2.dart'))
.thenReturn(source2);
when(context.sourceFactory).thenReturn(sourceFactory);
when(bundle.unlinkedUnitUris)
.thenReturn(<String>['package:p1/u1.dart', 'package:p1/u2.dart']);
when(bundle.unlinkedUnits)
.thenReturn(<UnlinkedUnit>[unlinkedUnit1, unlinkedUnit2]);
when(bundle.linkedLibraryUris).thenReturn(<String>['package:p1/u1.dart']);
when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary]);
dataStore.addBundle('/p1.ds', bundle);
when(unlinkedUnit1.isPartOf).thenReturn(false);
when(unlinkedUnit2.isPartOf).thenReturn(true);
var namespace1 = _namespaceWithParts(['package:p1/u2.dart']);
var namespace2 = _namespaceWithParts([]);
when(unlinkedUnit1.publicNamespace).thenReturn(namespace1);
when(unlinkedUnit2.publicNamespace).thenReturn(namespace2);
provider = new _TestResynthesizerResultProvider(context, dataStore);
provider.sourcesWithResults.add(source1);
provider.sourcesWithResults.add(source2);
}
test_compute_CONTAINING_LIBRARIES_librarySource() {
bool success = provider.compute(entry1, CONTAINING_LIBRARIES);
expect(success, isTrue);
expect(entry1.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
}
test_compute_CONTAINING_LIBRARIES_partSource() {
bool success = provider.compute(entry2, CONTAINING_LIBRARIES);
expect(success, isTrue);
expect(entry2.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
}
test_compute_LINE_INFO_emptyLineStarts() {
when(unlinkedUnit1.lineStarts).thenReturn(<int>[]);
bool success = provider.compute(entry1, LINE_INFO);
expect(success, isFalse);
}
test_compute_LINE_INFO_hasLineStarts() {
when(unlinkedUnit1.lineStarts).thenReturn(<int>[10, 20, 30]);
bool success = provider.compute(entry1, LINE_INFO);
expect(success, isTrue);
expect(entry1.getValue(LINE_INFO).lineStarts, <int>[10, 20, 30]);
}
test_compute_MODIFICATION_TIME_hasResult() {
bool success = provider.compute(entry1, MODIFICATION_TIME);
expect(success, isTrue);
expect(entry1.getValue(MODIFICATION_TIME), 0);
}
test_compute_MODIFICATION_TIME_noResult() {
bool success = provider.compute(entry3, MODIFICATION_TIME);
expect(success, isFalse);
expect(entry3.getState(MODIFICATION_TIME), CacheState.INVALID);
}
test_compute_SOURCE_KIND_librarySource() {
bool success = provider.compute(entry1, SOURCE_KIND);
expect(success, isTrue);
expect(entry1.getValue(SOURCE_KIND), SourceKind.LIBRARY);
}
test_compute_SOURCE_KIND_librarySource_isPartOf() {
when(unlinkedUnit1.isPartOf).thenReturn(true);
bool success = provider.compute(entry1, SOURCE_KIND);
expect(success, isTrue);
expect(entry1.getValue(SOURCE_KIND), SourceKind.PART);
}
test_compute_SOURCE_KIND_noResults() {
bool success = provider.compute(entry3, SOURCE_KIND);
expect(success, isFalse);
expect(entry3.getState(SOURCE_KIND), CacheState.INVALID);
}
test_compute_SOURCE_KIND_partSource() {
bool success = provider.compute(entry2, SOURCE_KIND);
expect(success, isTrue);
expect(entry2.getValue(SOURCE_KIND), SourceKind.PART);
}
}
@reflectiveTest
class SummaryDataStoreTest {
SummaryDataStore dataStore =
new SummaryDataStore(<String>[], disallowOverlappingSummaries: true);
PackageBundle bundle1 = new _PackageBundleMock();
PackageBundle bundle2 = new _PackageBundleMock();
UnlinkedUnit unlinkedUnit11 = new _UnlinkedUnitMock();
UnlinkedUnit unlinkedUnit12 = new _UnlinkedUnitMock();
UnlinkedUnit unlinkedUnit21 = new _UnlinkedUnitMock();
LinkedLibrary linkedLibrary1 = new _LinkedLibraryMock();
LinkedLibrary linkedLibrary2 = new _LinkedLibraryMock();
void setUp() {
_setupDataStore(dataStore);
}
test_addBundle() {
expect(dataStore.bundles, unorderedEquals([bundle1, bundle2]));
expect(dataStore.uriToSummaryPath,
containsPair('package:p1/u1.dart', '/p1.ds'));
// unlinkedMap
expect(dataStore.unlinkedMap, hasLength(3));
expect(dataStore.unlinkedMap,
containsPair('package:p1/u1.dart', unlinkedUnit11));
expect(dataStore.unlinkedMap,
containsPair('package:p1/u2.dart', unlinkedUnit12));
expect(dataStore.unlinkedMap,
containsPair('package:p2/u1.dart', unlinkedUnit21));
// linkedMap
expect(dataStore.linkedMap, hasLength(2));
expect(dataStore.linkedMap,
containsPair('package:p1/u1.dart', linkedLibrary1));
expect(dataStore.linkedMap,
containsPair('package:p2/u1.dart', linkedLibrary2));
}
test_addBundle_dartUris() {
PackageBundle bundle = new _PackageBundleMock();
when(bundle.unlinkedUnitUris).thenReturn(<String>['dart:core']);
when(bundle.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit11]);
when(bundle.linkedLibraryUris).thenReturn(<String>['dart:core']);
when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
when(bundle.apiSignature).thenReturn('signature');
dataStore.addBundle('/p3.ds', bundle);
}
test_addBundle_fileUris() {
PackageBundle bundle = new _PackageBundleMock();
when(bundle.unlinkedUnitUris).thenReturn(<String>['file:/foo.dart']);
when(bundle.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit11]);
when(bundle.linkedLibraryUris).thenReturn(<String>['file:/foo.dart']);
when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
when(bundle.apiSignature).thenReturn('signature');
dataStore.addBundle('/p3.ds', bundle);
}
test_addBundle_multiProject() {
PackageBundle bundle = new _PackageBundleMock();
when(bundle.unlinkedUnitUris)
.thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
when(bundle.unlinkedUnits)
.thenReturn(<UnlinkedUnit>[unlinkedUnit21, unlinkedUnit11]);
when(bundle.linkedLibraryUris)
.thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
when(bundle.linkedLibraries)
.thenReturn(<LinkedLibrary>[linkedLibrary2, linkedLibrary1]);
when(bundle.apiSignature).thenReturn('signature');
// p3 conflicts (overlaps) with existing summaries.
expect(() => dataStore.addBundle('/p3.ds', bundle),
throwsA(isConflictingSummaryException));
}
test_addBundle_multiProjectOverlap() {
SummaryDataStore dataStore2 =
new SummaryDataStore(<String>[], disallowOverlappingSummaries: false);
_setupDataStore(dataStore2);
PackageBundle bundle = new _PackageBundleMock();
when(bundle.unlinkedUnitUris)
.thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
when(bundle.unlinkedUnits)
.thenReturn(<UnlinkedUnit>[unlinkedUnit21, unlinkedUnit11]);
when(bundle.linkedLibraryUris)
.thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
when(bundle.linkedLibraries)
.thenReturn(<LinkedLibrary>[linkedLibrary2, linkedLibrary1]);
when(bundle.apiSignature).thenReturn('signature');
// p3 conflicts (overlaps) with existing summaries, but now allowed.
dataStore2.addBundle('/p3.ds', bundle);
}
test_getContainingLibraryUris_libraryUri() {
String partUri = 'package:p1/u1.dart';
List<String> uris = dataStore.getContainingLibraryUris(partUri);
expect(uris, unorderedEquals([partUri]));
}
test_getContainingLibraryUris_partUri() {
String partUri = 'package:p1/u2.dart';
List<String> uris = dataStore.getContainingLibraryUris(partUri);
expect(uris, unorderedEquals(['package:p1/u1.dart']));
}
test_getContainingLibraryUris_unknownUri() {
String partUri = 'package:notInStore/foo.dart';
List<String> uris = dataStore.getContainingLibraryUris(partUri);
expect(uris, isNull);
}
void _setupDataStore(SummaryDataStore store) {
var namespace1 = _namespaceWithParts(['package:p1/u2.dart']);
var namespace2 = _namespaceWithParts([]);
// bundle1
when(unlinkedUnit11.publicNamespace).thenReturn(namespace1);
when(unlinkedUnit12.publicNamespace).thenReturn(namespace2);
when(bundle1.unlinkedUnitUris)
.thenReturn(<String>['package:p1/u1.dart', 'package:p1/u2.dart']);
when(bundle1.unlinkedUnits)
.thenReturn(<UnlinkedUnit>[unlinkedUnit11, unlinkedUnit12]);
when(bundle1.linkedLibraryUris).thenReturn(<String>['package:p1/u1.dart']);
when(bundle1.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
when(bundle1.apiSignature).thenReturn('signature1');
store.addBundle('/p1.ds', bundle1);
// bundle2
when(unlinkedUnit21.publicNamespace).thenReturn(namespace2);
when(bundle2.unlinkedUnitUris).thenReturn(<String>['package:p2/u1.dart']);
when(bundle2.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit21]);
when(bundle2.linkedLibraryUris).thenReturn(<String>['package:p2/u1.dart']);
when(bundle2.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary2]);
when(bundle2.apiSignature).thenReturn('signature2');
store.addBundle('/p2.ds', bundle2);
}
}
class _ConflictingSummaryException extends TypeMatcher {
const _ConflictingSummaryException() : super("ConflictingSummaryException");
bool matches(item, Map matchState) => item is ConflictingSummaryException;
}
class _InternalAnalysisContextMock extends Mock
implements InternalAnalysisContext {}
class _LinkedLibraryMock extends Mock implements LinkedLibrary {}
class _PackageBundleMock extends Mock implements PackageBundle {}
class _SourceFactoryMock extends Mock implements SourceFactory {}
class _SourceMock implements Source {
final Uri uri;
final String fullName;
_SourceMock(String uriStr, this.fullName) : uri = Uri.parse(uriStr);
@override
Source get librarySource => null;
@override
Source get source => this;
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
String toString() => '$uri ($fullName)';
}
class _TestResynthesizerResultProvider extends ResynthesizerResultProvider {
final Set<Source> sourcesWithResults = new Set<Source>();
_TestResynthesizerResultProvider(
InternalAnalysisContext context, SummaryDataStore dataStore)
: super(context, dataStore);
@override
bool hasResultsForSource(Source source) {
return sourcesWithResults.contains(source);
}
}
class _UnlinkedPublicNamespaceMock extends Mock
implements UnlinkedPublicNamespace {}
class _UnlinkedUnitMock extends Mock implements UnlinkedUnit {}