| // 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. |
| |
| import 'package:analyzer/file_system/file_system.dart'; |
| import 'package:analyzer/file_system/memory_file_system.dart'; |
| import 'package:analyzer/src/generated/engine.dart' show TimestampedData; |
| import 'package:analyzer/src/generated/source.dart'; |
| import 'package:analyzer/src/generated/utilities_dart.dart'; |
| import 'package:path/path.dart' as path; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| import 'package:watcher/watcher.dart'; |
| |
| import 'file_system_test_support.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(FileSystemExceptionTest); |
| defineReflectiveTests(MemoryFileSourceExistingTest); |
| defineReflectiveTests(MemoryFileSourceNotExistingTest); |
| defineReflectiveTests(MemoryFileTest); |
| defineReflectiveTests(MemoryFolderTest); |
| defineReflectiveTests(MemoryResourceProviderTest); |
| }); |
| } |
| |
| abstract class BaseTest extends FileSystemTestSupport { |
| /// The resource provider to be used by the tests. Tests should use [provider] |
| /// to access the resource provider. |
| MemoryResourceProvider? _provider; |
| |
| /// The absolute path to the temporary directory in which all of the tests are |
| /// to work. |
| @override |
| late final String tempPath; |
| |
| /// A path to a folder within the [tempPath] that can be used by tests. |
| @override |
| late final String defaultFolderPath; |
| |
| /// A path to a file within the [defaultFolderPath] that can be used by tests. |
| @override |
| late final String defaultFilePath; |
| |
| /// The content used for the file at the [defaultFilePath] if it is created |
| /// and no other content is provided. |
| @override |
| String get defaultFileContent => 'a'; |
| |
| @override |
| bool get hasSymbolicLinkSupport => true; |
| |
| /// Return the resource provider to be used by the tests. |
| @override |
| MemoryResourceProvider get provider => _provider ??= createProvider(); |
| |
| @override |
| void createLink({required String path, required String target}) { |
| provider.newLink(path, target); |
| } |
| |
| /// Create the resource provider to be used by the tests. Subclasses can |
| /// override this method to change the class of resource provider that is |
| /// used. |
| MemoryResourceProvider createProvider() => MemoryResourceProvider(); |
| |
| @override |
| File getFile({required bool exists, String? content, String? filePath}) { |
| if (filePath == null) { |
| filePath = defaultFilePath; |
| } else { |
| filePath = provider.convertPath(filePath); |
| } |
| if (exists) { |
| provider.newFile(filePath, content ?? defaultFileContent); |
| } |
| return provider.getFile(filePath); |
| } |
| |
| @override |
| Folder getFolder({required bool exists, String? folderPath}) { |
| if (folderPath == null) { |
| folderPath = defaultFolderPath; |
| } else { |
| folderPath = provider.convertPath(folderPath); |
| } |
| if (exists) { |
| provider.newFolder(folderPath); |
| } |
| return provider.getFolder(folderPath); |
| } |
| |
| setUp() { |
| tempPath = provider.convertPath('/temp'); |
| defaultFolderPath = join(tempPath, 'bar'); |
| defaultFilePath = join(tempPath, 'bar', 'test.dart'); |
| } |
| } |
| |
| @reflectiveTest |
| class FileSystemExceptionTest { |
| test_constructor() { |
| var exception = FileSystemException('/my/path', 'my message'); |
| expect(exception.path, '/my/path'); |
| expect(exception.message, 'my message'); |
| expect(exception.toString(), |
| 'FileSystemException(path=/my/path; message=my message)'); |
| } |
| } |
| |
| @reflectiveTest |
| class MemoryFileSourceExistingTest extends BaseTest { |
| late final String sourcePath; |
| late final Source source; |
| |
| @override |
| setUp() { |
| super.setUp(); |
| File file = getFile(exists: true); |
| sourcePath = file.path; |
| source = file.createSource(); |
| } |
| |
| test_contents() { |
| TimestampedData<String> contents = source.contents; |
| expect(contents.data, defaultFileContent); |
| } |
| |
| test_equals_false_differentFile() { |
| File fileA = getFile(exists: false, filePath: join(tempPath, 'a.dart')); |
| File fileB = getFile(exists: false, filePath: join(tempPath, 'b.dart')); |
| Source sourceA = fileA.createSource(); |
| Source sourceB = fileB.createSource(); |
| |
| expect(sourceA == sourceB, isFalse); |
| } |
| |
| test_equals_false_notMemorySource() { |
| expect(source == Object(), isFalse); |
| } |
| |
| test_equals_true_sameFile() { |
| Source sourceA = getFile(exists: false).createSource(); |
| Source sourceB = getFile(exists: false).createSource(); |
| |
| expect(sourceA == sourceB, isTrue); |
| } |
| |
| test_equals_true_self() { |
| expect(source == source, isTrue); |
| } |
| |
| test_exists() { |
| expect(source.exists(), isTrue); |
| } |
| |
| test_fullName() { |
| expect(source.fullName, sourcePath); |
| } |
| |
| test_hashCode() { |
| expect(source.hashCode, isNotNull); |
| } |
| |
| test_resolveRelative() { |
| Uri relative = resolveRelativeUri( |
| source.uri, |
| provider.pathContext |
| .toUri(provider.pathContext.join('bar', 'baz.dart'))); |
| expect( |
| relative, |
| provider.pathContext |
| .toUri(provider.convertPath('/temp/bar/bar/baz.dart'))); |
| } |
| |
| test_resolveRelative_dart() { |
| File file = getFile( |
| exists: false, |
| filePath: provider.convertPath('/sdk/lib/core/core.dart')); |
| Source source = file.createSource(Uri.parse('dart:core')); |
| |
| Uri resolved = resolveRelativeUri(source.uri, Uri.parse('int.dart')); |
| expect(resolved.toString(), 'dart:core/int.dart'); |
| } |
| |
| test_shortName() { |
| expect(source.shortName, 'test.dart'); |
| } |
| } |
| |
| @reflectiveTest |
| class MemoryFileSourceNotExistingTest extends BaseTest { |
| late final String sourcePath; |
| late final Source source; |
| |
| @override |
| setUp() { |
| super.setUp(); |
| File file = getFile(exists: false); |
| sourcePath = file.path; |
| source = file.createSource(); |
| } |
| |
| test_contents() { |
| expect(() => source.contents, throwsA(isFileSystemException)); |
| } |
| |
| test_exists() { |
| expect(source.exists(), isFalse); |
| } |
| |
| test_fullName() { |
| expect(source.fullName, sourcePath); |
| } |
| |
| test_modificationStamp() { |
| expect(source.modificationStamp, -1); |
| } |
| |
| test_resolveRelative() { |
| Uri relative = resolveRelativeUri( |
| source.uri, |
| provider.pathContext |
| .toUri(provider.pathContext.join('bar', 'baz.dart'))); |
| expect( |
| relative, |
| provider.pathContext |
| .toUri(provider.convertPath('/temp/bar/bar/baz.dart'))); |
| } |
| |
| test_shortName() { |
| expect(source.shortName, 'test.dart'); |
| } |
| } |
| |
| @reflectiveTest |
| class MemoryFileTest extends BaseTest with FileTestMixin { |
| @override |
| test_delete_notExisting() { |
| File file = getFile(exists: false); |
| expect(file.exists, isFalse); |
| |
| expect(() => file.delete(), throwsA(const TypeMatcher<ArgumentError>())); |
| } |
| |
| @override |
| test_renameSync_notExisting() { |
| String oldPath = join(tempPath, 'file.txt'); |
| String newPath = join(tempPath, 'new-file.txt'); |
| File oldFile = getFile(exists: true, filePath: oldPath); |
| |
| File newFile = oldFile.renameSync(newPath); |
| expect(oldFile.path, oldPath); |
| expect(oldFile.exists, isFalse); |
| expect(newFile.path, newPath); |
| expect(newFile.exists, isTrue); |
| expect(newFile.readAsStringSync(), defaultFileContent); |
| } |
| |
| @override |
| test_writeAsBytesSync_notExisting() { |
| File file = getFile(exists: false); |
| |
| file.writeAsBytesSync(<int>[99, 99]); |
| expect(file.exists, true); |
| expect(file.readAsBytesSync(), <int>[99, 99]); |
| } |
| |
| @override |
| test_writeAsStringSync_notExisting() { |
| File file = getFile(exists: false); |
| |
| file.writeAsStringSync('cc'); |
| expect(file.exists, true); |
| expect(file.readAsStringSync(), 'cc'); |
| } |
| } |
| |
| @reflectiveTest |
| class MemoryFolderTest extends BaseTest with FolderTestMixin { |
| test_isRoot_false() { |
| var path = provider.convertPath('/foo'); |
| expect(provider.getFolder(path).isRoot, isFalse); |
| } |
| |
| test_isRoot_true() { |
| var path = provider.convertPath('/'); |
| expect(provider.getFolder(path).isRoot, isTrue); |
| } |
| } |
| |
| @reflectiveTest |
| class MemoryResourceProviderTest extends BaseTest |
| with ResourceProviderTestMixin { |
| test_deleteFile_existing() { |
| File file = getFile(exists: true); |
| expect(file.exists, isTrue); |
| |
| provider.deleteFile(defaultFilePath); |
| expect(file.exists, isFalse); |
| } |
| |
| test_deleteFile_folder() { |
| Folder folder = getFolder(exists: true); |
| |
| expect(() => provider.deleteFile(defaultFolderPath), throwsArgumentError); |
| expect(folder.exists, isTrue); |
| } |
| |
| test_deleteFile_notExisting() { |
| File file = getFile(exists: false); |
| |
| expect(() => provider.deleteFile(defaultFilePath), throwsArgumentError); |
| expect(file.exists, isFalse); |
| } |
| |
| test_modifyFile_existing_file() { |
| File file = getFile(exists: true); |
| |
| provider.modifyFile(file.path, 'contents 2'); |
| expect(file.readAsStringSync(), 'contents 2'); |
| } |
| |
| test_modifyFile_existing_folder() { |
| getFolder(exists: true); |
| |
| expect(() => provider.modifyFile(defaultFolderPath, 'contents'), |
| throwsArgumentError); |
| expect(provider.getResource(defaultFolderPath), isFolder); |
| } |
| |
| test_modifyFile_notExisting() { |
| getFile(exists: false); |
| |
| expect(() => provider.modifyFile(defaultFilePath, 'contents'), |
| throwsArgumentError); |
| Resource file = provider.getResource(defaultFilePath); |
| expect(file, isFile); |
| expect(file.exists, isFalse); |
| } |
| |
| test_newFileWithBytes() { |
| List<int> bytes = <int>[1, 2, 3, 4, 5]; |
| |
| provider.newFileWithBytes(defaultFilePath, bytes); |
| Resource file = provider.getResource(defaultFilePath); |
| expect(file, isFile); |
| expect(file.exists, isTrue); |
| expect((file as File).readAsBytesSync(), bytes); |
| } |
| |
| test_newFolder_emptyPath() { |
| expect(() => provider.newFolder(''), throwsArgumentError); |
| } |
| |
| test_newFolder_existing_file() { |
| getFile(exists: true); |
| |
| expect(() => provider.newFolder(defaultFilePath), throwsArgumentError); |
| } |
| |
| test_newFolder_existing_folder() { |
| Folder folder = getFolder(exists: true); |
| |
| Folder newFolder = provider.newFolder(folder.path); |
| expect(newFolder, folder); |
| } |
| |
| test_newFolder_notAbsolute() { |
| expect(() => provider.newFolder('not/absolute'), throwsArgumentError); |
| } |
| |
| test_newLink_folder() { |
| provider.newLink( |
| provider.convertPath('/test/lib/foo'), |
| provider.convertPath('/test/lib'), |
| ); |
| |
| provider.newFile( |
| provider.convertPath('/test/lib/a.dart'), |
| 'aaa', |
| ); |
| |
| { |
| var path = '/test/lib/foo/a.dart'; |
| var convertedPath = provider.convertPath(path); |
| var file = provider.getFile(convertedPath); |
| expect(file.exists, true); |
| expect(file.modificationStamp, isNonNegative); |
| expect(file.readAsStringSync(), 'aaa'); |
| } |
| |
| { |
| var path = '/test/lib/foo/foo/a.dart'; |
| var convertedPath = provider.convertPath(path); |
| var file = provider.getFile(convertedPath); |
| expect(file.exists, true); |
| expect(file.modificationStamp, isNonNegative); |
| expect(file.readAsStringSync(), 'aaa'); |
| } |
| } |
| |
| @override |
| test_pathContext() { |
| if (path.style == path.Style.windows) { |
| // On Windows the path context is replaced by one whose current directory |
| // is the root of the 'C' drive. |
| path.Context context = provider.pathContext; |
| expect(context.style, path.Style.windows); |
| expect(context.current, 'C:\\'); |
| } else { |
| super.test_pathContext(); |
| } |
| } |
| |
| test_watch_createFile() { |
| String rootPath = provider.convertPath('/my/path'); |
| provider.newFolder(rootPath); |
| return _watchingFolder(rootPath, (changesReceived) { |
| expect(changesReceived, hasLength(0)); |
| String path = provider.pathContext.join(rootPath, 'foo'); |
| |
| provider.newFile(path, 'contents'); |
| return _delayed(() { |
| expect(changesReceived, hasLength(1)); |
| expect(changesReceived[0].type, equals(ChangeType.ADD)); |
| expect(changesReceived[0].path, equals(path)); |
| }); |
| }); |
| } |
| |
| test_watch_deleteFile() { |
| String rootPath = provider.convertPath('/my/path'); |
| provider.newFolder(rootPath); |
| String path = provider.pathContext.join(rootPath, 'foo'); |
| provider.newFile(path, 'contents 1'); |
| return _watchingFolder(rootPath, (changesReceived) { |
| expect(changesReceived, hasLength(0)); |
| |
| provider.deleteFile(path); |
| return _delayed(() { |
| expect(changesReceived, hasLength(1)); |
| expect(changesReceived[0].type, equals(ChangeType.REMOVE)); |
| expect(changesReceived[0].path, equals(path)); |
| }); |
| }); |
| } |
| |
| test_watch_modifyFile() { |
| String rootPath = provider.convertPath('/my/path'); |
| provider.newFolder(rootPath); |
| String path = provider.pathContext.join(rootPath, 'foo'); |
| provider.newFile(path, 'contents 1'); |
| return _watchingFolder(rootPath, (changesReceived) { |
| expect(changesReceived, hasLength(0)); |
| |
| provider.modifyFile(path, 'contents 2'); |
| return _delayed(() { |
| expect(changesReceived, hasLength(1)); |
| expect(changesReceived[0].type, equals(ChangeType.MODIFY)); |
| expect(changesReceived[0].path, equals(path)); |
| }); |
| }); |
| } |
| |
| test_watch_modifyFile_inSubDir() { |
| String rootPath = provider.convertPath('/my/path'); |
| provider.newFolder(rootPath); |
| String subdirPath = provider.pathContext.join(rootPath, 'foo'); |
| provider.newFolder(subdirPath); |
| String path = provider.pathContext.join(rootPath, 'bar'); |
| provider.newFile(path, 'contents 1'); |
| return _watchingFolder(rootPath, (changesReceived) { |
| expect(changesReceived, hasLength(0)); |
| |
| provider.modifyFile(path, 'contents 2'); |
| return _delayed(() { |
| expect(changesReceived, hasLength(1)); |
| expect(changesReceived[0].type, equals(ChangeType.MODIFY)); |
| expect(changesReceived[0].path, equals(path)); |
| }); |
| }); |
| } |
| |
| Future _delayed(Function() computation) { |
| return Future.delayed(Duration.zero, computation); |
| } |
| |
| _watchingFolder( |
| String path, Function(List<WatchEvent> changesReceived) test) { |
| var folder = provider.getResource(path) as Folder; |
| var changesReceived = <WatchEvent>[]; |
| folder.changes.listen(changesReceived.add); |
| return test(changesReceived); |
| } |
| } |