| // 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: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'; |
| |
| |
| var _isFile = new isInstanceOf<File>(); |
| var _isFolder = new isInstanceOf<Folder>(); |
| |
| |
| main() { |
| groupSep = ' | '; |
| |
| group('PhysicalResourceProvider', () { |
| io.Directory tempDirectory; |
| String tempPath; |
| |
| setUp(() { |
| tempDirectory = io.Directory.systemTemp.createTempSync('test_resource'); |
| tempPath = tempDirectory.absolute.path; |
| }); |
| |
| tearDown(() { |
| tempDirectory.deleteSync(recursive: true); |
| }); |
| |
| group('Watch', () { |
| |
| 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); |
| } |
| |
| 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(); |
| }); |
| }); |
| } |
| |
| test('create file', () => watchingFolder(tempPath, (changesReceived) { |
| expect(changesReceived, hasLength(0)); |
| var path = join(tempPath, 'foo'); |
| new io.File(path).writeAsStringSync('contents'); |
| return delayed(() { |
| expect(changesReceived, hasLength(1)); |
| expect(changesReceived[0].type, equals(ChangeType.ADD)); |
| expect(changesReceived[0].path, equals(path)); |
| }); |
| })); |
| |
| test('modify file', () { |
| 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('modify file in subdir', () { |
| 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)); |
| }); |
| }); |
| }); |
| |
| test('delete file', () { |
| 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)); |
| }); |
| }); |
| }); |
| }); |
| |
| group('File', () { |
| String path; |
| File file; |
| |
| setUp(() { |
| path = join(tempPath, 'file.txt'); |
| file = PhysicalResourceProvider.INSTANCE.getResource(path); |
| }); |
| |
| 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'); |
| }); |
| |
| group('exists', () { |
| test('false', () { |
| expect(file.exists, isFalse); |
| }); |
| |
| test('true', () { |
| new io.File(path).writeAsStringSync('contents'); |
| expect(file.exists, isTrue); |
| }); |
| }); |
| |
| test('fullName', () { |
| expect(file.path, path); |
| }); |
| |
| test('hashCode', () { |
| new io.File(path).writeAsStringSync('contents'); |
| File file2 = PhysicalResourceProvider.INSTANCE.getResource(path); |
| expect(file.hashCode, equals(file2.hashCode)); |
| }); |
| |
| test('equality: same path', () { |
| new io.File(path).writeAsStringSync('contents'); |
| File file2 = PhysicalResourceProvider.INSTANCE.getResource(path); |
| expect(file == file2, isTrue); |
| }); |
| |
| test('equality: different paths', () { |
| String path2 = join(tempPath, 'file2.txt'); |
| File file2 = PhysicalResourceProvider.INSTANCE.getResource(path2); |
| expect(file == file2, isFalse); |
| }); |
| |
| test('isOrContains', () { |
| File file = PhysicalResourceProvider.INSTANCE.getResource(path); |
| expect(file.isOrContains(path), isTrue); |
| expect(file.isOrContains('foo'), isFalse); |
| }); |
| |
| test('shortName', () { |
| expect(file.shortName, 'file.txt'); |
| }); |
| |
| test('toString', () { |
| expect(file.toString(), path); |
| }); |
| |
| test('parent', () { |
| Resource parent = file.parent; |
| expect(parent, new isInstanceOf<Folder>()); |
| expect(parent.path, equals(tempPath)); |
| }); |
| }); |
| |
| group('Folder', () { |
| String path; |
| Folder folder; |
| |
| setUp(() { |
| path = join(tempPath, 'folder'); |
| new io.Directory(path).createSync(); |
| folder = PhysicalResourceProvider.INSTANCE.getResource(path); |
| }); |
| |
| test('hashCode', () { |
| Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path); |
| expect(folder.hashCode, equals(folder2.hashCode)); |
| }); |
| |
| test('equality: same path', () { |
| Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path); |
| expect(folder == folder2, isTrue); |
| }); |
| |
| test('equality: different paths', () { |
| String path2 = join(tempPath, 'folder2'); |
| new io.Directory(path2).createSync(); |
| Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path2); |
| expect(folder == folder2, isFalse); |
| }); |
| |
| 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); |
| }); |
| |
| 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); |
| }); |
| |
| group('getChild', () { |
| test('does not exist', () { |
| var child = folder.getChild('no-such-resource'); |
| expect(child, isNotNull); |
| expect(child.exists, isFalse); |
| }); |
| |
| test('file', () { |
| new io.File(join(path, 'myFile')).createSync(); |
| var child = folder.getChild('myFile'); |
| expect(child, _isFile); |
| expect(child.exists, isTrue); |
| }); |
| |
| test('folder', () { |
| new io.Directory(join(path, 'myFolder')).createSync(); |
| var child = folder.getChild('myFolder'); |
| expect(child, _isFolder); |
| expect(child.exists, isTrue); |
| }); |
| }); |
| |
| test('getChildren', () { |
| // 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); |
| }); |
| |
| 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; |
| } |
| }); |
| |
| 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'))); |
| }); |
| }); |
| }); |
| } |