// Copyright (c) 2015, 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 'dart:convert'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine, Logger; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart'; import 'package:analyzer/src/generated/utilities_dart.dart' as utils; import 'package:analyzer/src/source/package_map_resolver.dart'; import 'package:analyzer/src/source/source_resource.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:package_config/packages.dart'; import 'package:package_config/packages_file.dart' as pkgfile show parse; import 'package:package_config/src/packages_impl.dart'; import 'package:path/path.dart' as pathos; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'test_support.dart'; main() { runPackageMapTests(); defineReflectiveSuite(() { defineReflectiveTests(SourceFactoryTest); }); } Source createSource({String path, String uri}) => //TODO(pquitslund): find some way to pass an actual URI into source creation new MemoryResourceProvider() .getFile(path) .createSource(uri != null ? Uri.parse(uri) : null); void runPackageMapTests() { MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); final Uri baseUri = new Uri.file('test/base'); final List testResolvers = [ new ResourceUriResolver(resourceProvider) ]; Packages createPackageMap(Uri base, String configFileContents) { List bytes = utf8.encode(configFileContents); Map map = pkgfile.parse(bytes, base); return new MapPackages(map); } Map> getPackageMap(String config) { Packages packages = createPackageMap(baseUri, config); SourceFactory factory = new SourceFactory(testResolvers, packages); return factory.packageMap; } String resolvePackageUri( {String uri, String config, Source containingSource, UriResolver customResolver}) { Packages packages = createPackageMap(baseUri, config); List resolvers = testResolvers.toList(); if (customResolver != null) { resolvers.add(customResolver); } SourceFactory factory = new SourceFactory(resolvers, packages); expect(AnalysisEngine.instance.logger, Logger.NULL); var logger = new TestLogger(); AnalysisEngine.instance.logger = logger; try { Source source = factory.resolveUri(containingSource, uri); expect(logger.log, []); return source != null ? source.fullName : null; } finally { AnalysisEngine.instance.logger = Logger.NULL; } } Uri restorePackageUri( {Source source, String config, UriResolver customResolver}) { Packages packages = createPackageMap(baseUri, config); List resolvers = testResolvers.toList(); if (customResolver != null) { resolvers.add(customResolver); } SourceFactory factory = new SourceFactory(resolvers, packages); return factory.restoreUri(source); } String _p(String path) => resourceProvider.convertPath(path); Uri _u(String path) => resourceProvider.pathContext.toUri(_p(path)); group('SourceFactoryTest', () { group('package mapping', () { group('resolveUri', () { test('URI in mapping', () { String uri = resolvePackageUri(config: ''' unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')} async:${_u('/home/somebody/.pub/cache/async-1.1.0/lib/')} quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')} ''', uri: 'package:unittest/unittest.dart'); expect( uri, equals(_p( '/home/somebody/.pub/cache/unittest-0.9.9/lib/unittest.dart'))); }); test('URI not in mapping', () { String uri = resolvePackageUri(config: ''' unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')} async:${_u('/home/somebody/.pub/cache/async-1.1.0/lib/')} quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')} ''', uri: 'package:foo/foo.dart'); expect(uri, isNull); }); test('Non-package URI', () { var testResolver = new CustomUriResolver(uriPath: _p('/test.dart')); String uri = resolvePackageUri(config: ''' unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')} ''', uri: 'custom:custom.dart', customResolver: testResolver); expect(uri, testResolver.uriPath); }); test('Bad package URI', () { String uri = resolvePackageUri(config: '', uri: 'package:foo'); expect(uri, isNull); }); test('Invalid URI', () { // TODO(pquitslund): fix clients to handle errors appropriately // CLI: print message 'invalid package file format' // SERVER: best case tell user somehow and recover... expect( () => resolvePackageUri( config: 'foo:<:&%>', uri: 'package:foo/bar.dart'), throwsA(new TypeMatcher())); }); test('Valid URI that cannot be further resolved', () { String uri = resolvePackageUri( config: 'foo:http://www.google.com', uri: 'package:foo/bar.dart'); expect(uri, isNull); }); test('Relative URIs', () { Source containingSource = createSource( path: _p('/foo/bar/baz/foo.dart'), uri: 'package:foo/foo.dart'); String uri = resolvePackageUri( config: 'foo:${_u('/foo/bar/baz')}', uri: 'bar.dart', containingSource: containingSource); expect(uri, isNotNull); expect(uri, equals(_p('/foo/bar/baz/bar.dart'))); }); }); group('restoreUri', () { test('URI in mapping', () { Uri uri = restorePackageUri( config: ''' unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')} async:${_u('/home/somebody/.pub/cache/async-1.1.0/lib/')} quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')} ''', source: new FileSource(resourceProvider.getFile(_p( '/home/somebody/.pub/cache/unittest-0.9.9/lib/unittest.dart')))); expect(uri, isNotNull); expect(uri.toString(), equals('package:unittest/unittest.dart')); }); }); group('packageMap', () { test('non-file URIs filtered', () { Map> map = getPackageMap(''' quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')} foo:http://www.google.com '''); expect(map.keys, unorderedEquals(['quiver'])); }); }); }); }); group('URI utils', () { group('URI', () { test('startsWith', () { expect(utils.startsWith(Uri.parse('/foo/bar/'), Uri.parse('/foo/')), isTrue); expect(utils.startsWith(Uri.parse('/foo/bar/'), Uri.parse('/foo/bar/')), isTrue); expect(utils.startsWith(Uri.parse('/foo/bar'), Uri.parse('/foo/b')), isFalse); // Handle odd URIs (https://github.com/dart-lang/sdk/issues/24126) expect(utils.startsWith(Uri.parse('/foo/bar'), Uri.parse('')), isFalse); expect(utils.startsWith(Uri.parse(''), Uri.parse('/foo/bar')), isFalse); }); }); }); } class AbsoluteUriResolver extends UriResolver { final MemoryResourceProvider resourceProvider; AbsoluteUriResolver(this.resourceProvider); @override Source resolveAbsolute(Uri uri, [Uri actualUri]) { return new FileSource( resourceProvider.getFile(resourceProvider.pathContext.fromUri(uri)), actualUri); } } class CustomUriResolver extends UriResolver { String uriPath; CustomUriResolver({this.uriPath}); @override Source resolveAbsolute(Uri uri, [Uri actualUri]) => createSource(path: uriPath); } @reflectiveTest class SourceFactoryTest with ResourceProviderMixin { void test_creation() { expect(new SourceFactory([]), isNotNull); } void test_fromEncoding_invalidUri() { SourceFactory factory = new SourceFactory([]); expect(() => factory.fromEncoding("<:&%>"), throwsArgumentError); } void test_fromEncoding_noResolver() { SourceFactory factory = new SourceFactory([]); expect(() => factory.fromEncoding("foo:/does/not/exist.dart"), throwsArgumentError); } void test_fromEncoding_valid() { String encoding = "file:///does/not/exist.dart"; SourceFactory factory = new SourceFactory( [new UriResolver_SourceFactoryTest_test_fromEncoding_valid(encoding)]); expect(factory.fromEncoding(encoding), isNotNull); } void test_resolveUri_absolute() { UriResolver_absolute resolver = new UriResolver_absolute(); SourceFactory factory = new SourceFactory([resolver]); factory.resolveUri(null, "dart:core"); expect(resolver.invoked, isTrue); } void test_resolveUri_nonAbsolute_absolute() { SourceFactory factory = new SourceFactory([new AbsoluteUriResolver(resourceProvider)]); String sourcePath = convertPath('/does/not/exist.dart'); String targetRawPath = '/does/not/matter.dart'; String targetPath = convertPath(targetRawPath); String targetUri = toUri(targetRawPath).toString(); Source sourceSource = new FileSource(getFile(sourcePath)); Source result = factory.resolveUri(sourceSource, targetUri); expect(result.fullName, targetPath); } void test_resolveUri_nonAbsolute_relative() { SourceFactory factory = new SourceFactory([new AbsoluteUriResolver(resourceProvider)]); Source containingSource = new FileSource(getFile('/does/not/have.dart')); Source result = factory.resolveUri(containingSource, 'exist.dart'); expect(result.fullName, convertPath('/does/not/exist.dart')); } void test_resolveUri_nonAbsolute_relative_package() { MemoryResourceProvider provider = new MemoryResourceProvider(); pathos.Context context = provider.pathContext; String packagePath = context.joinAll([context.separator, 'path', 'to', 'package']); String libPath = context.joinAll([packagePath, 'lib']); String dirPath = context.joinAll([libPath, 'dir']); String firstPath = context.joinAll([dirPath, 'first.dart']); String secondPath = context.joinAll([dirPath, 'second.dart']); provider.newFolder(packagePath); Folder libFolder = provider.newFolder(libPath); provider.newFolder(dirPath); File firstFile = provider.newFile(firstPath, ''); provider.newFile(secondPath, ''); PackageMapUriResolver resolver = new PackageMapUriResolver(provider, { 'package': [libFolder] }); SourceFactory factory = new SourceFactory([resolver]); Source librarySource = firstFile.createSource(Uri.parse('package:package/dir/first.dart')); Source result = factory.resolveUri(librarySource, 'second.dart'); expect(result, isNotNull); expect(result.fullName, secondPath); expect(result.uri.toString(), 'package:package/dir/second.dart'); } void test_restoreUri() { File file1 = getFile("/some/file1.dart"); File file2 = getFile("/some/file2.dart"); Source source1 = new FileSource(file1); Source source2 = new FileSource(file2); Uri expected1 = Uri.parse("file:///my_file.dart"); SourceFactory factory = new SourceFactory([new UriResolver_restoreUri(source1, expected1)]); expect(factory.restoreUri(source1), same(expected1)); expect(factory.restoreUri(source2), same(null)); } } class UriResolver_absolute extends UriResolver { bool invoked = false; UriResolver_absolute(); @override Source resolveAbsolute(Uri uri, [Uri actualUri]) { invoked = true; return null; } } class UriResolver_restoreUri extends UriResolver { Source source1; Uri expected1; UriResolver_restoreUri(this.source1, this.expected1); @override Source resolveAbsolute(Uri uri, [Uri actualUri]) => null; @override Uri restoreAbsolute(Source source) { if (identical(source, source1)) { return expected1; } return null; } } class UriResolver_SourceFactoryTest_test_fromEncoding_valid extends UriResolver { String encoding; UriResolver_SourceFactoryTest_test_fromEncoding_valid(this.encoding); @override Source resolveAbsolute(Uri uri, [Uri actualUri]) { if (uri.toString() == encoding) { return new TestSource(); } return null; } }