| Index: packages/analyzer/test/file_system/physical_resource_provider_test.dart
|
| diff --git a/packages/analyzer/test/file_system/physical_resource_provider_test.dart b/packages/analyzer/test/file_system/physical_resource_provider_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..87d976abccf34ce6f83026c14d319e6d14f61cb1
|
| --- /dev/null
|
| +++ b/packages/analyzer/test/file_system/physical_resource_provider_test.dart
|
| @@ -0,0 +1,452 @@
|
| +// 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.physical_file_system;
|
| +
|
| +import 'dart:async';
|
| +import 'dart:core' hide Resource;
|
| +import 'dart:io' as io;
|
| +
|
| +import 'package:analyzer/file_system/file_system.dart';
|
| +import 'package:analyzer/file_system/physical_file_system.dart';
|
| +import 'package:analyzer/src/generated/source_io.dart';
|
| +import 'package:path/path.dart';
|
| +import 'package:unittest/unittest.dart';
|
| +import 'package:watcher/watcher.dart';
|
| +
|
| +import '../reflective_tests.dart';
|
| +import '../utils.dart';
|
| +
|
| +main() {
|
| + initializeTestEnvironment();
|
| + runReflectiveTests(PhysicalResourceProviderTest);
|
| + runReflectiveTests(FileTest);
|
| + runReflectiveTests(FolderTest);
|
| +}
|
| +
|
| +var _isFile = new isInstanceOf<File>();
|
| +var _isFileSystemException = new isInstanceOf<FileSystemException>();
|
| +var _isFolder = new isInstanceOf<Folder>();
|
| +
|
| +@reflectiveTest
|
| +class FileTest extends _BaseTest {
|
| + String path;
|
| + File file;
|
| +
|
| + setUp() {
|
| + super.setUp();
|
| + path = join(tempPath, 'file.txt');
|
| + file = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + }
|
| +
|
| + void test_createSource() {
|
| + new io.File(path).writeAsStringSync('contents');
|
| + Source source = file.createSource();
|
| + expect(source.uriKind, UriKind.FILE_URI);
|
| + expect(source.exists(), isTrue);
|
| + expect(source.contents.data, 'contents');
|
| + }
|
| +
|
| + void test_equals_differentPaths() {
|
| + String path2 = join(tempPath, 'file2.txt');
|
| + File file2 = PhysicalResourceProvider.INSTANCE.getResource(path2);
|
| + expect(file == file2, isFalse);
|
| + }
|
| +
|
| + void test_equals_samePath() {
|
| + new io.File(path).writeAsStringSync('contents');
|
| + File file2 = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(file == file2, isTrue);
|
| + }
|
| +
|
| + void test_exists_false() {
|
| + expect(file.exists, isFalse);
|
| + }
|
| +
|
| + void test_exists_true() {
|
| + new io.File(path).writeAsStringSync('contents');
|
| + expect(file.exists, isTrue);
|
| + }
|
| +
|
| + void test_fullName() {
|
| + expect(file.path, path);
|
| + }
|
| +
|
| + void test_hashCode() {
|
| + new io.File(path).writeAsStringSync('contents');
|
| + File file2 = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(file.hashCode, equals(file2.hashCode));
|
| + }
|
| +
|
| + void test_isOrContains() {
|
| + File file = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(file.isOrContains(path), isTrue);
|
| + expect(file.isOrContains('foo'), isFalse);
|
| + }
|
| +
|
| + void test_modificationStamp_doesNotExist() {
|
| + File file = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(() {
|
| + file.modificationStamp;
|
| + }, throwsA(_isFileSystemException));
|
| + }
|
| +
|
| + void test_modificationStamp_exists() {
|
| + new io.File(path).writeAsStringSync('contents');
|
| + File file = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(file.modificationStamp, isNonNegative);
|
| + }
|
| +
|
| + void test_parent() {
|
| + Resource parent = file.parent;
|
| + expect(parent, new isInstanceOf<Folder>());
|
| + expect(parent.path, equals(tempPath));
|
| + }
|
| +
|
| + void test_readAsStringSync_doesNotExist() {
|
| + File file = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(() {
|
| + file.readAsStringSync();
|
| + }, throwsA(_isFileSystemException));
|
| + }
|
| +
|
| + void test_readAsStringSync_exists() {
|
| + new io.File(path).writeAsStringSync('abc');
|
| + File file = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(file.readAsStringSync(), 'abc');
|
| + }
|
| +
|
| + void test_shortName() {
|
| + expect(file.shortName, 'file.txt');
|
| + }
|
| +
|
| + void test_toString() {
|
| + expect(file.toString(), path);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class FolderTest extends _BaseTest {
|
| + String path;
|
| + Folder folder;
|
| +
|
| + setUp() {
|
| + super.setUp();
|
| + path = join(tempPath, 'folder');
|
| + new io.Directory(path).createSync();
|
| + folder = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + }
|
| +
|
| + void test_canonicalizePath() {
|
| + String path2 = join(tempPath, 'folder2');
|
| + String path3 = join(tempPath, 'folder3');
|
| + expect(folder.canonicalizePath('baz'), equals(join(path, 'baz')));
|
| + expect(folder.canonicalizePath(path2), equals(path2));
|
| + expect(folder.canonicalizePath(join('..', 'folder2')), equals(path2));
|
| + expect(
|
| + folder.canonicalizePath(join(path2, '..', 'folder3')), equals(path3));
|
| + expect(
|
| + folder.canonicalizePath(join('.', 'baz')), equals(join(path, 'baz')));
|
| + expect(folder.canonicalizePath(join(path2, '.', 'baz')),
|
| + equals(join(path2, 'baz')));
|
| + }
|
| +
|
| + void test_contains() {
|
| + expect(folder.contains(join(path, 'aaa.txt')), isTrue);
|
| + expect(folder.contains(join(path, 'aaa', 'bbb.txt')), isTrue);
|
| + expect(folder.contains(join(tempPath, 'baz.txt')), isFalse);
|
| + expect(folder.contains(path), isFalse);
|
| + }
|
| +
|
| + void test_equals_differentPaths() {
|
| + String path2 = join(tempPath, 'folder2');
|
| + new io.Directory(path2).createSync();
|
| + Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path2);
|
| + expect(folder == folder2, isFalse);
|
| + }
|
| +
|
| + void test_equals_samePath() {
|
| + Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(folder == folder2, isTrue);
|
| + }
|
| +
|
| + void test_getChild_doesNotExist() {
|
| + var child = folder.getChild('no-such-resource');
|
| + expect(child, isNotNull);
|
| + expect(child.exists, isFalse);
|
| + }
|
| +
|
| + void test_getChild_file() {
|
| + new io.File(join(path, 'myFile')).createSync();
|
| + var child = folder.getChild('myFile');
|
| + expect(child, _isFile);
|
| + expect(child.exists, isTrue);
|
| + }
|
| +
|
| + void test_getChild_folder() {
|
| + new io.Directory(join(path, 'myFolder')).createSync();
|
| + var child = folder.getChild('myFolder');
|
| + expect(child, _isFolder);
|
| + expect(child.exists, isTrue);
|
| + }
|
| +
|
| + void test_getChildAssumingFolder_doesNotExist() {
|
| + Folder child = folder.getChildAssumingFolder('no-such-resource');
|
| + expect(child, isNotNull);
|
| + expect(child.exists, isFalse);
|
| + }
|
| +
|
| + void test_getChildAssumingFolder_file() {
|
| + new io.File(join(path, 'myFile')).createSync();
|
| + Folder child = folder.getChildAssumingFolder('myFile');
|
| + expect(child, isNotNull);
|
| + expect(child.exists, isFalse);
|
| + }
|
| +
|
| + void test_getChildAssumingFolder_folder() {
|
| + new io.Directory(join(path, 'myFolder')).createSync();
|
| + Folder child = folder.getChildAssumingFolder('myFolder');
|
| + expect(child, isNotNull);
|
| + expect(child.exists, isTrue);
|
| + }
|
| +
|
| + void test_getChildren_doesNotExist() {
|
| + folder = folder.getChildAssumingFolder('no-such-folder');
|
| + expect(() {
|
| + folder.getChildren();
|
| + }, throwsA(_isFileSystemException));
|
| + }
|
| +
|
| + void test_getChildren_exists() {
|
| + // create 2 files and 1 folder
|
| + new io.File(join(path, 'a.txt')).createSync();
|
| + new io.Directory(join(path, 'bFolder')).createSync();
|
| + new io.File(join(path, 'c.txt')).createSync();
|
| + // prepare 3 children
|
| + List<Resource> children = folder.getChildren();
|
| + expect(children, hasLength(3));
|
| + children.sort((a, b) => a.shortName.compareTo(b.shortName));
|
| + // check that each child exists
|
| + children.forEach((child) {
|
| + expect(child.exists, true);
|
| + });
|
| + // check names
|
| + expect(children[0].shortName, 'a.txt');
|
| + expect(children[1].shortName, 'bFolder');
|
| + expect(children[2].shortName, 'c.txt');
|
| + // check types
|
| + expect(children[0], _isFile);
|
| + expect(children[1], _isFolder);
|
| + expect(children[2], _isFile);
|
| + }
|
| +
|
| + void test_hashCode() {
|
| + Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + expect(folder.hashCode, equals(folder2.hashCode));
|
| + }
|
| +
|
| + void test_isOrContains() {
|
| + expect(folder.isOrContains(path), isTrue);
|
| + expect(folder.isOrContains(join(path, 'aaa.txt')), isTrue);
|
| + expect(folder.isOrContains(join(path, 'aaa', 'bbb.txt')), isTrue);
|
| + expect(folder.isOrContains(join(tempPath, 'baz.txt')), isFalse);
|
| + }
|
| +
|
| + void test_parent() {
|
| + Resource parent = folder.parent;
|
| + expect(parent, new isInstanceOf<Folder>());
|
| + expect(parent.path, equals(tempPath));
|
| +
|
| + // Since the OS is in control of where tempPath is, we don't know how
|
| + // far it should be from the root. So just verify that each call to
|
| + // parent results in a a folder with a shorter path, and that we
|
| + // reach the root eventually.
|
| + while (true) {
|
| + Resource grandParent = parent.parent;
|
| + if (grandParent == null) {
|
| + break;
|
| + }
|
| + expect(grandParent, new isInstanceOf<Folder>());
|
| + expect(grandParent.path.length, lessThan(parent.path.length));
|
| + parent = grandParent;
|
| + }
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class PhysicalResourceProviderTest extends _BaseTest {
|
| + void test_getStateLocation_uniqueness() {
|
| + PhysicalResourceProvider provider = PhysicalResourceProvider.INSTANCE;
|
| + String idOne = 'one';
|
| + Folder folderOne = provider.getStateLocation(idOne);
|
| + expect(folderOne, isNotNull);
|
| + String idTwo = 'two';
|
| + Folder folderTwo = provider.getStateLocation(idTwo);
|
| + expect(folderTwo, isNotNull);
|
| + expect(folderTwo, isNot(equals(folderOne)));
|
| + expect(provider.getStateLocation(idOne), equals(folderOne));
|
| + }
|
| +
|
| + test_watchFile_delete() {
|
| + var path = join(tempPath, 'foo');
|
| + var file = new io.File(path);
|
| + file.writeAsStringSync('contents 1');
|
| + return _watchingFile(path, (changesReceived) {
|
| + expect(changesReceived, hasLength(0));
|
| + file.deleteSync();
|
| + return _delayed(() {
|
| + expect(changesReceived, hasLength(1));
|
| + if (io.Platform.isWindows) {
|
| + // See https://github.com/dart-lang/sdk/issues/23762
|
| + // Not sure why this breaks under Windows, but testing to see whether
|
| + // we are running Windows causes the type to change. For now we print
|
| + // the type out of curriosity.
|
| + print(
|
| + 'PhysicalResourceProviderTest:test_watchFile_delete received an event with type = ${changesReceived[0].type}');
|
| + } else {
|
| + expect(changesReceived[0].type, equals(ChangeType.REMOVE));
|
| + }
|
| + expect(changesReceived[0].path, equals(path));
|
| + });
|
| + });
|
| + }
|
| +
|
| + test_watchFile_modify() {
|
| + var path = join(tempPath, 'foo');
|
| + var file = new io.File(path);
|
| + file.writeAsStringSync('contents 1');
|
| + return _watchingFile(path, (changesReceived) {
|
| + expect(changesReceived, hasLength(0));
|
| + file.writeAsStringSync('contents 2');
|
| + return _delayed(() {
|
| + expect(changesReceived, hasLength(1));
|
| + expect(changesReceived[0].type, equals(ChangeType.MODIFY));
|
| + expect(changesReceived[0].path, equals(path));
|
| + });
|
| + });
|
| + }
|
| +
|
| + test_watchFolder_createFile() {
|
| + return _watchingFolder(tempPath, (changesReceived) {
|
| + expect(changesReceived, hasLength(0));
|
| + var path = join(tempPath, 'foo');
|
| + new io.File(path).writeAsStringSync('contents');
|
| + return _delayed(() {
|
| + // There should be an "add" event indicating that the file was added.
|
| + // Depending on how long it took to write the contents, it may be
|
| + // followed by "modify" events.
|
| + expect(changesReceived, isNotEmpty);
|
| + expect(changesReceived[0].type, equals(ChangeType.ADD));
|
| + expect(changesReceived[0].path, equals(path));
|
| + for (int i = 1; i < changesReceived.length; i++) {
|
| + expect(changesReceived[i].type, equals(ChangeType.MODIFY));
|
| + expect(changesReceived[i].path, equals(path));
|
| + }
|
| + });
|
| + });
|
| + }
|
| +
|
| + test_watchFolder_deleteFile() {
|
| + var path = join(tempPath, 'foo');
|
| + var file = new io.File(path);
|
| + file.writeAsStringSync('contents 1');
|
| + return _watchingFolder(tempPath, (changesReceived) {
|
| + expect(changesReceived, hasLength(0));
|
| + file.deleteSync();
|
| + return _delayed(() {
|
| + expect(changesReceived, hasLength(1));
|
| + expect(changesReceived[0].type, equals(ChangeType.REMOVE));
|
| + expect(changesReceived[0].path, equals(path));
|
| + });
|
| + });
|
| + }
|
| +
|
| + test_watchFolder_modifyFile() {
|
| + var path = join(tempPath, 'foo');
|
| + var file = new io.File(path);
|
| + file.writeAsStringSync('contents 1');
|
| + return _watchingFolder(tempPath, (changesReceived) {
|
| + expect(changesReceived, hasLength(0));
|
| + file.writeAsStringSync('contents 2');
|
| + return _delayed(() {
|
| + expect(changesReceived, hasLength(1));
|
| + expect(changesReceived[0].type, equals(ChangeType.MODIFY));
|
| + expect(changesReceived[0].path, equals(path));
|
| + });
|
| + });
|
| + }
|
| +
|
| + test_watchFolder_modifyFile_inSubDir() {
|
| + var subdirPath = join(tempPath, 'foo');
|
| + new io.Directory(subdirPath).createSync();
|
| + var path = join(tempPath, 'bar');
|
| + var file = new io.File(path);
|
| + file.writeAsStringSync('contents 1');
|
| + return _watchingFolder(tempPath, (changesReceived) {
|
| + expect(changesReceived, hasLength(0));
|
| + file.writeAsStringSync('contents 2');
|
| + return _delayed(() {
|
| + expect(changesReceived, hasLength(1));
|
| + expect(changesReceived[0].type, equals(ChangeType.MODIFY));
|
| + expect(changesReceived[0].path, equals(path));
|
| + });
|
| + });
|
| + }
|
| +
|
| + Future _delayed(computation()) {
|
| + // Give the tests 1 second to detect the changes. While it may only
|
| + // take up to a few hundred ms, a whole second gives a good margin
|
| + // for when running tests.
|
| + return new Future.delayed(new Duration(seconds: 1), computation);
|
| + }
|
| +
|
| + _watchingFile(String path, test(List<WatchEvent> changesReceived)) {
|
| + // Delay before we start watching the file. This is necessary
|
| + // because on MacOS, file modifications that occur just before we
|
| + // start watching are sometimes misclassified as happening just after
|
| + // we start watching.
|
| + return _delayed(() {
|
| + File file = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + var changesReceived = <WatchEvent>[];
|
| + var subscription = file.changes.listen(changesReceived.add);
|
| + // Delay running the rest of the test to allow file.changes propogate.
|
| + return _delayed(() => test(changesReceived)).whenComplete(() {
|
| + subscription.cancel();
|
| + });
|
| + });
|
| + }
|
| +
|
| + _watchingFolder(String path, test(List<WatchEvent> changesReceived)) {
|
| + // Delay before we start watching the folder. This is necessary
|
| + // because on MacOS, file modifications that occur just before we
|
| + // start watching are sometimes misclassified as happening just after
|
| + // we start watching.
|
| + return _delayed(() {
|
| + Folder folder = PhysicalResourceProvider.INSTANCE.getResource(path);
|
| + var changesReceived = <WatchEvent>[];
|
| + var subscription = folder.changes.listen(changesReceived.add);
|
| + // Delay running the rest of the test to allow folder.changes to
|
| + // take a snapshot of the current directory state. Otherwise it
|
| + // won't be able to reliably distinguish new files from modified
|
| + // ones.
|
| + return _delayed(() => test(changesReceived)).whenComplete(() {
|
| + subscription.cancel();
|
| + });
|
| + });
|
| + }
|
| +}
|
| +
|
| +class _BaseTest {
|
| + io.Directory tempDirectory;
|
| + String tempPath;
|
| +
|
| + setUp() {
|
| + tempDirectory = io.Directory.systemTemp.createTempSync('test_resource');
|
| + tempPath = tempDirectory.absolute.path;
|
| + }
|
| +
|
| + tearDown() {
|
| + tempDirectory.deleteSync(recursive: true);
|
| + }
|
| +}
|
|
|