Revert "Devfs cleanup and testing (#33374)" (#33673)
This reverts commit 445505d6f2d4a0b658385f0ef735d3a826ca49ab.
diff --git a/packages/flutter_tools/test/devfs_test.dart b/packages/flutter_tools/test/devfs_test.dart
index 1887e74..b8d93d4 100644
--- a/packages/flutter_tools/test/devfs_test.dart
+++ b/packages/flutter_tools/test/devfs_test.dart
@@ -4,17 +4,15 @@
import 'dart:async';
import 'dart:convert';
+import 'dart:io'; // ignore: dart_io_import
import 'package:file/file.dart';
import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
-import 'package:mockito/mockito.dart';
import 'src/common.dart';
import 'src/context.dart';
@@ -22,39 +20,17 @@
void main() {
FileSystem fs;
- MockPlatform mockPlatform;
+ String filePath;
+ Directory tempDir;
+ String basePath;
+ DevFS devFS;
- setUp(() {
- fs = MemoryFileSystem(style: FileSystemStyle.posix);
- mockPlatform = MockPlatform();
- when(mockPlatform.pathSeparator).thenReturn('/');
- when(mockPlatform.isWindows).thenReturn(false);
+ setUpAll(() {
+ fs = MemoryFileSystem();
+ filePath = fs.path.join('lib', 'foo.txt');
});
group('DevFSContent', () {
- test('copyToFile', () {
- final String filePath = fs.path.join('lib', 'foo.txt');
- final File file = fs.file(filePath)
- ..createSync(recursive: true)
- ..writeAsStringSync('hello, world');
- final DevFSByteContent byteContent = DevFSByteContent(<int>[4, 5, 6]);
- final DevFSStringContent stringContent = DevFSStringContent('some string');
- final DevFSFileContent fileContent = DevFSFileContent(file);
-
- final File byteDestination = fs.file('byte_dest');
- final File stringDestination = fs.file('string_dest');
- final File fileDestination = fs.file('file_dest');
-
- byteContent.copyToFile(byteDestination);
- expect(byteDestination.readAsBytesSync(), <int>[4, 5, 6]);
-
- stringContent.copyToFile(stringDestination);
- expect(stringDestination.readAsStringSync(), 'some string');
-
- fileContent.copyToFile(fileDestination);
- expect(fileDestination.readAsStringSync(), 'hello, world');
- });
-
test('bytes', () {
final DevFSByteContent content = DevFSByteContent(<int>[4, 5, 6]);
expect(content.bytes, orderedEquals(<int>[4, 5, 6]));
@@ -65,7 +41,6 @@
expect(content.isModified, isTrue);
expect(content.isModified, isFalse);
});
-
test('string', () {
final DevFSStringContent content = DevFSStringContent('some string');
expect(content.string, 'some string');
@@ -83,9 +58,7 @@
expect(content.isModified, isTrue);
expect(content.isModified, isFalse);
});
-
testUsingContext('file', () async {
- final String filePath = fs.path.join('lib', 'foo.txt');
final File file = fs.file(filePath);
final DevFSFileContent content = DevFSFileContent(file);
expect(content.isModified, isFalse);
@@ -100,9 +73,10 @@
expect(content.isModifiedAfter(null), isTrue);
file.writeAsBytesSync(<int>[2, 3, 4], flush: true);
+ expect(content.fileDependencies, <String>[filePath]);
expect(content.isModified, isTrue);
expect(content.isModified, isFalse);
- expect(content.contentsAsBytes(), <int>[2, 3, 4]);
+ expect(await content.contentsAsBytes(), <int>[2, 3, 4]);
updateFileModificationTime(file.path, fiveSecondsAgo, 0);
expect(content.isModified, isFalse);
expect(content.isModified, isFalse);
@@ -113,56 +87,36 @@
expect(content.isModified, isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
- }, skip: platform.isWindows); // Still flaky, but only on CI :(
+ }, skip: Platform.isWindows); // TODO(jonahwilliams): fix or disable this functionality.
});
group('devfs remote', () {
- DevFS devFS;
- MockResidentCompiler residentCompiler;
- MockDevFSOperations mockDevFSOperations;
- int created;
- int destroyed;
- List<String> writtenFiles;
- bool exists;
+ MockVMService vmService;
+ final MockResidentCompiler residentCompiler = MockResidentCompiler();
- setUp(() async {
- mockDevFSOperations = MockDevFSOperations();
- devFS = DevFS.operations(mockDevFSOperations, 'test', fs.currentDirectory);
- residentCompiler = MockResidentCompiler();
- created = 0;
- destroyed = 0;
- exists = false;
- writtenFiles = <String>[];
- when(mockDevFSOperations.create('test')).thenAnswer((Invocation invocation) async {
- if (exists) {
- throw rpc.RpcException(1001, 'already exists');
- }
- exists = true;
- created += 1;
- return Uri.parse(InternetAddress.loopbackIPv4.toString());
- });
- when(mockDevFSOperations.destroy('test')).thenAnswer((Invocation invocation) async {
- exists = false;
- destroyed += 1;
- });
- when(mockDevFSOperations.write(any)).thenAnswer((Invocation invocation) async {
- final Map<Uri, DevFSContent> entries = invocation.positionalArguments.first;
- writtenFiles.addAll(entries.keys.map((Uri uri) => uri.toFilePath()));
- });
+ setUpAll(() async {
+ tempDir = _newTempDir(fs);
+ basePath = tempDir.path;
+ vmService = MockVMService();
+ await vmService.setUp();
+ });
+ tearDownAll(() async {
+ await vmService.tearDown();
+ _cleanupTempDirs();
});
testUsingContext('create dev file system', () async {
// simulate workspace
- final String filePath = fs.path.join('lib', 'foo.txt');
- final File file = fs.file(filePath);
+ final File file = fs.file(fs.path.join(basePath, filePath));
await file.parent.create(recursive: true);
file.writeAsBytesSync(<int>[1, 2, 3]);
// simulate package
await _createPackage(fs, 'somepkg', 'somefile.txt');
- await devFS.create();
- expect(created, 1);
+ devFS = DevFS(vmService, 'test', tempDir);
+ await devFS.create();
+ vmService.expectMessages(<String>['create test']);
expect(devFS.assetPathsToEvict, isEmpty);
final UpdateFSReport report = await devFS.update(
@@ -172,8 +126,9 @@
trackWidgetCreation: false,
invalidatedFiles: <Uri>[],
);
-
- expect(writtenFiles.single, contains('foo.txt.dill'));
+ vmService.expectMessages(<String>[
+ 'writeFile test lib/foo.txt.dill',
+ ]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(report.syncedBytes, 22);
expect(report.success, true);
@@ -182,8 +137,9 @@
});
testUsingContext('delete dev file system', () async {
+ expect(vmService.messages, isEmpty, reason: 'prior test timeout');
await devFS.destroy();
- expect(destroyed, 1);
+ vmService.expectMessages(<String>['destroy test']);
expect(devFS.assetPathsToEvict, isEmpty);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
@@ -191,27 +147,26 @@
testUsingContext('cleanup preexisting file system', () async {
// simulate workspace
- final String filePath = fs.path.join('lib', 'foo.txt');
- final File file = fs.file(filePath);
+ final File file = fs.file(fs.path.join(basePath, filePath));
await file.parent.create(recursive: true);
file.writeAsBytesSync(<int>[1, 2, 3]);
// simulate package
await _createPackage(fs, 'somepkg', 'somefile.txt');
+ devFS = DevFS(vmService, 'test', tempDir);
await devFS.create();
- expect(created, 1);
+ vmService.expectMessages(<String>['create test']);
expect(devFS.assetPathsToEvict, isEmpty);
// Try to create again.
await devFS.create();
- expect(created, 2);
- expect(destroyed, 1);
+ vmService.expectMessages(<String>['create test', 'destroy test', 'create test']);
expect(devFS.assetPathsToEvict, isEmpty);
// Really destroy.
await devFS.destroy();
- expect(destroyed, 2);
+ vmService.expectMessages(<String>['destroy test']);
expect(devFS.assetPathsToEvict, isEmpty);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
@@ -219,20 +174,113 @@
});
}
-class MockVMService extends Mock implements VMService {}
+class MockVMService extends BasicMock implements VMService {
+ MockVMService() {
+ _vm = MockVM(this);
+ }
-class MockDevFSOperations extends Mock implements DevFSOperations {}
+ Uri _httpAddress;
+ HttpServer _server;
+ MockVM _vm;
-class MockPlatform extends Mock implements Platform {}
+ @override
+ Uri get httpAddress => _httpAddress;
+ @override
+ VM get vm => _vm;
+
+ Future<void> setUp() async {
+ try {
+ _server = await HttpServer.bind(InternetAddress.loopbackIPv6, 0);
+ _httpAddress = Uri.parse('http://[::1]:${_server.port}');
+ } on SocketException {
+ // Fall back to IPv4 if the host doesn't support binding to IPv6 localhost
+ _server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
+ _httpAddress = Uri.parse('http://127.0.0.1:${_server.port}');
+ }
+ _server.listen((HttpRequest request) {
+ final String fsName = request.headers.value('dev_fs_name');
+ final String devicePath = utf8.decode(base64.decode(request.headers.value('dev_fs_uri_b64')));
+ messages.add('writeFile $fsName $devicePath');
+ request.drain<List<int>>().then<void>((List<int> value) {
+ request.response
+ ..write('Got it')
+ ..close();
+ });
+ });
+ }
+
+ Future<void> tearDown() async {
+ await _server?.close();
+ }
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class MockVM implements VM {
+ MockVM(this._service);
+
+ final MockVMService _service;
+ final Uri _baseUri = Uri.parse('file:///tmp/devfs/test');
+ bool _devFSExists = false;
+
+ static const int kFileSystemAlreadyExists = 1001;
+
+ @override
+ Future<Map<String, dynamic>> createDevFS(String fsName) async {
+ _service.messages.add('create $fsName');
+ if (_devFSExists) {
+ throw rpc.RpcException(kFileSystemAlreadyExists, 'File system already exists');
+ }
+ _devFSExists = true;
+ return <String, dynamic>{'uri': '$_baseUri'};
+ }
+
+ @override
+ Future<Map<String, dynamic>> deleteDevFS(String fsName) async {
+ _service.messages.add('destroy $fsName');
+ _devFSExists = false;
+ return <String, dynamic>{'type': 'Success'};
+ }
+
+ @override
+ Future<Map<String, dynamic>> invokeRpcRaw(
+ String method, {
+ Map<String, dynamic> params = const <String, dynamic>{},
+ Duration timeout,
+ bool timeoutFatal = true,
+ }) async {
+ _service.messages.add('$method $params');
+ return <String, dynamic>{'success': true};
+ }
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+
+final List<Directory> _tempDirs = <Directory>[];
final Map <String, Uri> _packages = <String, Uri>{};
+Directory _newTempDir(FileSystem fs) {
+ final Directory tempDir = fs.systemTempDirectory.createTempSync('flutter_devfs${_tempDirs.length}_test.');
+ _tempDirs.add(tempDir);
+ return tempDir;
+}
+
+void _cleanupTempDirs() {
+ while (_tempDirs.isNotEmpty)
+ tryToDelete(_tempDirs.removeLast());
+}
Future<void> _createPackage(FileSystem fs, String pkgName, String pkgFileName, { bool doubleSlash = false }) async {
- String pkgFilePath = fs.path.join(pkgName, 'lib', pkgFileName);
+ final Directory pkgTempDir = _newTempDir(fs);
+ String pkgFilePath = fs.path.join(pkgTempDir.path, pkgName, 'lib', pkgFileName);
if (doubleSlash) {
// Force two separators into the path.
- pkgFilePath = fs.path.join(pkgName, 'lib', pkgFileName);
+ final String doubleSlash = fs.path.separator + fs.path.separator;
+ pkgFilePath = pkgTempDir.path + doubleSlash + fs.path.join(pkgName, 'lib', pkgFileName);
}
final File pkgFile = fs.file(pkgFilePath);
await pkgFile.parent.create(recursive: true);
@@ -242,5 +290,6 @@
_packages.forEach((String pkgName, Uri pkgUri) {
sb.writeln('$pkgName:$pkgUri');
});
- fs.file('.packages').writeAsStringSync(sb.toString());
+ fs.file(fs.path.join(_tempDirs[0].path, '.packages')).writeAsStringSync(sb.toString());
}
+