blob: f33b2f8b6989283432f440b7890ff90c21d0768d [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.context.directory.manager;
import 'mocks.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analysis_server/src/context_directory_manager.dart';
import 'package:analysis_server/src/package_map_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:path/path.dart';
import 'package:unittest/unittest.dart';
class TestContextDirectoryManager extends ContextDirectoryManager {
TestContextDirectoryManager(
MemoryResourceProvider resourceProvider, PackageMapProvider packageMapProvider)
: super(resourceProvider, packageMapProvider);
/**
* Source of timestamps stored in [currentContextFilePaths].
*/
int now = 0;
final Set<String> currentContextPaths = new Set<String>();
/**
* Map from context to (map from file path to timestamp of last event)
*/
final Map<String, Map<String, int>> currentContextFilePaths = <String, Map<String, int>>{};
/**
* Map from context to package map
*/
final Map<String, Map<String, List<Folder>>> currentContextPackageMaps =
<String, Map<String, List<Folder>>>{};
@override
void addContext(Folder folder, Map<String, List<Folder>> packageMap) {
String path = folder.path;
currentContextPaths.add(path);
currentContextFilePaths[path] = <String, int>{};
currentContextPackageMaps[path] = packageMap;
}
@override
void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
Map<String, int> filePaths = currentContextFilePaths[contextFolder.path];
for (Source source in changeSet.addedSources) {
expect(filePaths, isNot(contains(source.fullName)));
filePaths[source.fullName] = now;
}
for (Source source in changeSet.removedSources) {
expect(filePaths, contains(source.fullName));
filePaths.remove(source.fullName);
}
for (Source source in changeSet.changedSources) {
expect(filePaths, contains(source.fullName));
filePaths[source.fullName] = now;
}
}
@override
void removeContext(Folder folder) {
String path = folder.path;
currentContextPaths.remove(path);
currentContextFilePaths.remove(path);
currentContextPackageMaps.remove(path);
}
@override
void updateContextPackageMap(Folder contextFolder,
Map<String, List<Folder>> packageMap) {
currentContextPackageMaps[contextFolder.path]= packageMap;
}
}
main() {
groupSep = ' | ';
group('ContextDirectoryManager', () {
TestContextDirectoryManager manager;
MemoryResourceProvider resourceProvider;
MockPackageMapProvider packageMapProvider;
setUp(() {
resourceProvider = new MemoryResourceProvider();
packageMapProvider = new MockPackageMapProvider();
manager = new TestContextDirectoryManager(resourceProvider, packageMapProvider);
});
test('add folder with pubspec', () {
String projPath = '/my/proj';
String pubspecPath = posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFolder(projPath);
resourceProvider.newFile(pubspecPath, 'pubspec');
manager.setRoots(<String>[projPath], <String>[]);
expect(manager.currentContextPaths, hasLength(1));
expect(manager.currentContextPaths, contains(projPath));
expect(manager.currentContextFilePaths[projPath], hasLength(0));
});
test('newly added folders get proper package map', () {
String projPath = '/my/proj';
String packagePath = '/package/foo';
resourceProvider.newFolder(projPath);
Folder packageFolder = resourceProvider.newFolder(packagePath);
packageMapProvider.packageMap = {'foo': [packageFolder]};
manager.setRoots(<String>[projPath], <String>[]);
expect(manager.currentContextPackageMaps[projPath],
equals(packageMapProvider.packageMap));
});
test('add folder without pubspec', () {
String projPath = '/my/proj';
resourceProvider.newFolder(projPath);
packageMapProvider.packageMap = null;
manager.setRoots(<String>[projPath], <String>[]);
expect(manager.currentContextPaths, hasLength(1));
expect(manager.currentContextPaths, contains(projPath));
expect(manager.currentContextFilePaths[projPath], hasLength(0));
});
test('add folder with dart file', () {
String projPath = '/my/proj';
resourceProvider.newFolder(projPath);
String filePath = posix.join(projPath, 'foo.dart');
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[]);
var filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, hasLength(1));
expect(filePaths, contains(filePath));
});
test('add folder with dummy link', () {
String projPath = '/my/proj';
resourceProvider.newFolder(projPath);
String filePath = posix.join(projPath, 'foo.dart');
resourceProvider.newDummyLink(filePath);
manager.setRoots(<String>[projPath], <String>[]);
var filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, isEmpty);
});
test('add folder with dart file in subdir', () {
String projPath = '/my/proj';
resourceProvider.newFolder(projPath);
String filePath = posix.join(projPath, 'foo', 'bar.dart');
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[]);
var filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, hasLength(1));
expect(filePaths, contains(filePath));
});
test('remove folder with pubspec', () {
String projPath = '/my/proj';
String pubspecPath = posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFolder(projPath);
resourceProvider.newFile(pubspecPath, 'pubspec');
manager.setRoots(<String>[projPath], <String>[]);
manager.setRoots(<String>[], <String>[]);
expect(manager.currentContextPaths, hasLength(0));
expect(manager.currentContextFilePaths, hasLength(0));
});
test('remove folder without pubspec', () {
String projPath = '/my/proj';
resourceProvider.newFolder(projPath);
packageMapProvider.packageMap = null;
manager.setRoots(<String>[projPath], <String>[]);
manager.setRoots(<String>[], <String>[]);
expect(manager.currentContextPaths, hasLength(0));
expect(manager.currentContextFilePaths, hasLength(0));
});
test('ignore files in packages dir', () {
String projPath = '/my/proj';
resourceProvider.newFolder(projPath);
String pubspecPath = posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'pubspec');
String filePath1 = posix.join(projPath, 'packages', 'file1.dart');
resourceProvider.newFile(filePath1, 'contents');
manager.setRoots(<String>[projPath], <String>[]);
Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, hasLength(0));
String filePath2 = posix.join(projPath, 'packages', 'file2.dart');
resourceProvider.newFile(filePath2, 'contents');
return pumpEventQueue().then((_) {
expect(filePaths, hasLength(0));
});
});
group('isInAnalysisRoot', () {
test('in root', () {
String projPath = '/project';
resourceProvider.newFolder(projPath);
manager.setRoots(<String>[projPath], <String>[]);
expect(manager.isInAnalysisRoot('/project/test.dart'), isTrue);
});
test('not in root', () {
String projPath = '/project';
resourceProvider.newFolder(projPath);
manager.setRoots(<String>[projPath], <String>[]);
expect(manager.isInAnalysisRoot('/test.dart'), isFalse);
});
});
group('detect context modifications', () {
String projPath;
setUp(() {
projPath = '/my/proj';
resourceProvider.newFolder(projPath);
});
test('Add dummy link', () {
manager.setRoots(<String>[projPath], <String>[]);
Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, isEmpty);
String filePath = posix.join(projPath, 'foo.dart');
resourceProvider.newDummyLink(filePath);
return pumpEventQueue().then((_) {
expect(filePaths, isEmpty);
});
});
test('Add file', () {
manager.setRoots(<String>[projPath], <String>[]);
Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, hasLength(0));
String filePath = posix.join(projPath, 'foo.dart');
resourceProvider.newFile(filePath, 'contents');
return pumpEventQueue().then((_) {
expect(filePaths, hasLength(1));
expect(filePaths, contains(filePath));
});
});
test('Add file in subdirectory', () {
manager.setRoots(<String>[projPath], <String>[]);
Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, hasLength(0));
String filePath = posix.join(projPath, 'foo', 'bar.dart');
resourceProvider.newFile(filePath, 'contents');
return pumpEventQueue().then((_) {
expect(filePaths, hasLength(1));
expect(filePaths, contains(filePath));
});
});
test('Delete file', () {
String filePath = posix.join(projPath, 'foo.dart');
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[]);
Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, hasLength(1));
expect(filePaths, contains(filePath));
resourceProvider.deleteFile(filePath);
return pumpEventQueue().then((_) => expect(filePaths, hasLength(0)));
});
test('Modify file', () {
String filePath = posix.join(projPath, 'foo.dart');
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[]);
Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
expect(filePaths, hasLength(1));
expect(filePaths, contains(filePath));
expect(filePaths[filePath], equals(manager.now));
manager.now++;
resourceProvider.modifyFile(filePath, 'new contents');
return pumpEventQueue().then((_) => expect(filePaths[filePath], equals(
manager.now)));
});
test('Modify package map dependency', () {
String dependencyPath = posix.join(projPath, 'dep');
resourceProvider.newFile(dependencyPath, 'contents');
String dartFilePath = posix.join(projPath, 'main.dart');
resourceProvider.newFile(dartFilePath, 'contents');
packageMapProvider.dependencies.add(dependencyPath);
manager.setRoots(<String>[projPath], <String>[]);
expect(manager.currentContextPackageMaps[projPath],
equals(packageMapProvider.packageMap));
String packagePath = '/package/foo';
resourceProvider.newFolder(packagePath);
packageMapProvider.packageMap = {'foo': projPath};
// Changing a .dart file in the project shouldn't cause a new
// package map to be picked up.
resourceProvider.modifyFile(dartFilePath, 'new contents');
return pumpEventQueue().then((_) {
expect(manager.currentContextPackageMaps[projPath], isEmpty);
// However, changing the package map dependency should.
resourceProvider.modifyFile(dependencyPath, 'new contents');
return pumpEventQueue().then((_) {
expect(manager.currentContextPackageMaps[projPath],
equals(packageMapProvider.packageMap));
});
});
});
test('Modify package map dependency - packageMapProvider failure', () {
String dependencyPath = posix.join(projPath, 'dep');
resourceProvider.newFile(dependencyPath, 'contents');
String dartFilePath = posix.join(projPath, 'main.dart');
resourceProvider.newFile(dartFilePath, 'contents');
packageMapProvider.dependencies.add(dependencyPath);
manager.setRoots(<String>[projPath], <String>[]);
expect(manager.currentContextPackageMaps[projPath],
equals(packageMapProvider.packageMap));
// Change the package map dependency so that the packageMapProvider is
// re-run, and arrange for it to return null from computePackageMap().
packageMapProvider.packageMap = null;
resourceProvider.modifyFile(dependencyPath, 'new contents');
return pumpEventQueue().then((_) {
// The package map should have been changed to null.
expect(manager.currentContextPackageMaps[projPath], isNull);
});
});
});
});
}