| // 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 {} |