Revert "Devfs cleanup and testing (#33374)" (#33673)
This reverts commit 445505d6f2d4a0b658385f0ef735d3a826ca49ab.
diff --git a/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart b/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart
index 0d2a3a2..648a092 100644
--- a/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart
@@ -74,7 +74,7 @@
final String entryKey = 'packages/$packageName/$packageFont';
expect(bundle.entries.containsKey(entryKey), true);
expect(
- utf8.decode(bundle.entries[entryKey].contentsAsBytes()),
+ utf8.decode(await bundle.entries[entryKey].contentsAsBytes()),
packageFont,
);
}
@@ -82,14 +82,14 @@
for (String localFont in localFonts) {
expect(bundle.entries.containsKey(localFont), true);
expect(
- utf8.decode(bundle.entries[localFont].contentsAsBytes()),
+ utf8.decode(await bundle.entries[localFont].contentsAsBytes()),
localFont,
);
}
}
expect(
- json.decode(utf8.decode(bundle.entries['FontManifest.json'].contentsAsBytes())),
+ json.decode(utf8.decode(await bundle.entries['FontManifest.json'].contentsAsBytes())),
json.decode(expectedAssetManifest),
);
}
diff --git a/packages/flutter_tools/test/asset_bundle_package_test.dart b/packages/flutter_tools/test/asset_bundle_package_test.dart
index 1e67c11..2ea7946 100644
--- a/packages/flutter_tools/test/asset_bundle_package_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_package_test.dart
@@ -79,14 +79,14 @@
final String entryKey = Uri.encodeFull('packages/$packageName/$asset');
expect(bundle.entries.containsKey(entryKey), true, reason: 'Cannot find key on bundle: $entryKey');
expect(
- utf8.decode(bundle.entries[entryKey].contentsAsBytes()),
+ utf8.decode(await bundle.entries[entryKey].contentsAsBytes()),
asset,
);
}
}
expect(
- utf8.decode(bundle.entries['AssetManifest.json'].contentsAsBytes()),
+ utf8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
expectedAssetManifest,
);
}
@@ -126,11 +126,11 @@
expect(bundle.entries.length, 3); // LICENSE, AssetManifest, FontManifest
const String expectedAssetManifest = '{}';
expect(
- utf8.decode(bundle.entries['AssetManifest.json'].contentsAsBytes()),
+ utf8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
expectedAssetManifest,
);
expect(
- utf8.decode(bundle.entries['FontManifest.json'].contentsAsBytes()),
+ utf8.decode(await bundle.entries['FontManifest.json'].contentsAsBytes()),
'[]',
);
}, overrides: <Type, Generator>{
@@ -153,11 +153,11 @@
expect(bundle.entries.length, 3); // LICENSE, AssetManifest, FontManifest
const String expectedAssetManifest = '{}';
expect(
- utf8.decode(bundle.entries['AssetManifest.json'].contentsAsBytes()),
+ utf8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
expectedAssetManifest,
);
expect(
- utf8.decode(bundle.entries['FontManifest.json'].contentsAsBytes()),
+ utf8.decode(await bundle.entries['FontManifest.json'].contentsAsBytes()),
'[]',
);
}, overrides: <Type, Generator>{
diff --git a/packages/flutter_tools/test/asset_bundle_test.dart b/packages/flutter_tools/test/asset_bundle_test.dart
index 6bd084e..6d99cde 100644
--- a/packages/flutter_tools/test/asset_bundle_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_test.dart
@@ -50,7 +50,7 @@
expect(bundle.entries.length, 1);
const String expectedAssetManifest = '{}';
expect(
- utf8.decode(bundle.entries['AssetManifest.json'].contentsAsBytes()),
+ utf8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
expectedAssetManifest,
);
}, overrides: <Type, Generator>{
diff --git a/packages/flutter_tools/test/asset_bundle_variant_test.dart b/packages/flutter_tools/test/asset_bundle_variant_test.dart
index 77bdbfd..9a7b9f5 100644
--- a/packages/flutter_tools/test/asset_bundle_variant_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_variant_test.dart
@@ -76,7 +76,7 @@
// The main asset file, /a/b/c/foo, and its variants exist.
for (String asset in assets) {
expect(bundle.entries.containsKey(asset), true);
- expect(utf8.decode(bundle.entries[asset].contentsAsBytes()), asset);
+ expect(utf8.decode(await bundle.entries[asset].contentsAsBytes()), asset);
}
fs.file(fixPath('a/b/c/foo')).deleteSync();
@@ -88,7 +88,7 @@
expect(bundle.entries.containsKey('a/b/c/foo'), false);
for (String asset in assets.skip(1)) {
expect(bundle.entries.containsKey(asset), true);
- expect(utf8.decode(bundle.entries[asset].contentsAsBytes()), asset);
+ expect(utf8.decode(await bundle.entries[asset].contentsAsBytes()), asset);
}
}, overrides: <Type, Generator>{
FileSystem: () => testFileSystem,
diff --git a/packages/flutter_tools/test/asset_test.dart b/packages/flutter_tools/test/asset_test.dart
index af961eb..bb8f259 100644
--- a/packages/flutter_tools/test/asset_test.dart
+++ b/packages/flutter_tools/test/asset_test.dart
@@ -7,7 +7,6 @@
import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/cache.dart';
-import 'package:flutter_tools/src/convert.dart';
import 'src/common.dart';
import 'src/context.dart';
@@ -66,5 +65,5 @@
}
Future<String> getValueAsString(String key, AssetBundle asset) async {
- return utf8.decode(asset.entries[key].contentsAsBytes());
+ return String.fromCharCodes(await asset.entries[key].contentsAsBytes());
}
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());
}
+
diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart
index 1d1da52..8c318bc 100644
--- a/packages/flutter_tools/test/src/mocks.dart
+++ b/packages/flutter_tools/test/src/mocks.dart
@@ -14,6 +14,7 @@
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
+import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/ios/simulators.dart';
@@ -477,6 +478,30 @@
}
}
+class MockDevFSOperations extends BasicMock implements DevFSOperations {
+ Map<Uri, DevFSContent> devicePathToContent = <Uri, DevFSContent>{};
+
+ @override
+ Future<Uri> create(String fsName) async {
+ messages.add('create $fsName');
+ return Uri.parse('file:///$fsName');
+ }
+
+ @override
+ Future<dynamic> destroy(String fsName) async {
+ messages.add('destroy $fsName');
+ }
+
+ @override
+ Future<dynamic> writeFile(String fsName, Uri deviceUri, DevFSContent content) async {
+ String message = 'writeFile $fsName $deviceUri';
+ if (content is DevFSFileContent) {
+ message += ' ${content.file.path}';
+ }
+ messages.add(message);
+ devicePathToContent[deviceUri] = content;
+ }
+}
class MockResidentCompiler extends BasicMock implements ResidentCompiler {
@override