Unverified Commit 6fddb7ee authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tools] Handle full device when creating a temp directory (#53691)

parent 3a0d8377
...@@ -52,7 +52,8 @@ const FileSystem _kLocalFs = LocalFileSystem(); ...@@ -52,7 +52,8 @@ const FileSystem _kLocalFs = LocalFileSystem();
/// By default it uses local disk-based implementation. Override this in tests /// By default it uses local disk-based implementation. Override this in tests
/// with [MemoryFileSystem]. /// with [MemoryFileSystem].
FileSystem get fs => ErrorHandlingFileSystem( FileSystem get fs => ErrorHandlingFileSystem(
context.get<FileSystem>() ?? _kLocalFs, delegate: context.get<FileSystem>() ?? _kLocalFs,
platform: platform,
); );
final FileSystemUtils _defaultFileSystemUtils = FileSystemUtils( final FileSystemUtils _defaultFileSystemUtils = FileSystemUtils(
......
...@@ -10,8 +10,6 @@ import 'package:platform/platform.dart'; ...@@ -10,8 +10,6 @@ import 'package:platform/platform.dart';
import 'package:path/path.dart' as path; // ignore: package_path_import import 'package:path/path.dart' as path; // ignore: package_path_import
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/testbed.dart';
class MockFile extends Mock implements File {} class MockFile extends Mock implements File {}
class MockFileSystem extends Mock implements FileSystem {} class MockFileSystem extends Mock implements FileSystem {}
...@@ -23,29 +21,16 @@ final Platform windowsPlatform = FakePlatform( ...@@ -23,29 +21,16 @@ final Platform windowsPlatform = FakePlatform(
environment: <String, String>{} environment: <String, String>{}
); );
void main() { final Platform linuxPlatform = FakePlatform(
group('throws ToolExit on Windows', () { operatingSystem: 'linux',
const int kDeviceFull = 112; environment: <String, String>{}
const int kUserMappedSectionOpened = 1224; );
Testbed testbed;
MockFileSystem mockFileSystem;
ErrorHandlingFileSystem fs;
setUp(() {
mockFileSystem = MockFileSystem();
fs = ErrorHandlingFileSystem(mockFileSystem);
when(mockFileSystem.path).thenReturn(MockPathContext());
testbed = Testbed(overrides: <Type, Generator>{
Platform: () => windowsPlatform,
});
});
void writeTests({ void setupWriteMocks({
String testName, FileSystem mockFileSystem,
ErrorHandlingFileSystem fs,
int errorCode, int errorCode,
String expectedMessage, }) {
}) {
test(testName, () => testbed.run(() async {
final MockFile mockFile = MockFile(); final MockFile mockFile = MockFile();
when(mockFileSystem.file(any)).thenReturn(mockFile); when(mockFileSystem.file(any)).thenReturn(mockFile);
when(mockFile.writeAsBytes( when(mockFile.writeAsBytes(
...@@ -74,9 +59,48 @@ void main() { ...@@ -74,9 +59,48 @@ void main() {
encoding: anyNamed('encoding'), encoding: anyNamed('encoding'),
flush: anyNamed('flush'), flush: anyNamed('flush'),
)).thenThrow(FileSystemException('', '', OSError('', errorCode))); )).thenThrow(FileSystemException('', '', OSError('', errorCode)));
}
void setupCreateTempMocks({
FileSystem mockFileSystem,
ErrorHandlingFileSystem fs,
int errorCode,
}) {
final MockDirectory mockDirectory = MockDirectory();
when(mockFileSystem.directory(any)).thenReturn(mockDirectory);
when(mockDirectory.createTemp(any)).thenAnswer((_) async {
throw FileSystemException('', '', OSError('', errorCode));
});
when(mockDirectory.createTempSync(any))
.thenThrow(FileSystemException('', '', OSError('', errorCode)));
}
void main() {
group('throws ToolExit on Windows', () {
const int kDeviceFull = 112;
const int kUserMappedSectionOpened = 1224;
MockFileSystem mockFileSystem;
ErrorHandlingFileSystem fs;
setUp(() {
mockFileSystem = MockFileSystem();
fs = ErrorHandlingFileSystem(
delegate: mockFileSystem,
platform: windowsPlatform,
);
when(mockFileSystem.path).thenReturn(MockPathContext());
});
testWithoutContext('when writing to a full device', () async {
setupWriteMocks(
mockFileSystem: mockFileSystem,
fs: fs,
errorCode: kDeviceFull,
);
final File file = fs.file('file'); final File file = fs.file('file');
const String expectedMessage = 'The target device is full';
expect(() async => await file.writeAsBytes(<int>[0]), expect(() async => await file.writeAsBytes(<int>[0]),
throwsToolExit(message: expectedMessage)); throwsToolExit(message: expectedMessage));
expect(() async => await file.writeAsString(''), expect(() async => await file.writeAsString(''),
...@@ -85,31 +109,112 @@ void main() { ...@@ -85,31 +109,112 @@ void main() {
throwsToolExit(message: expectedMessage)); throwsToolExit(message: expectedMessage));
expect(() => file.writeAsStringSync(''), expect(() => file.writeAsStringSync(''),
throwsToolExit(message: expectedMessage)); throwsToolExit(message: expectedMessage));
})); });
}
testWithoutContext('when the file is being used by another program', () async {
setupWriteMocks(
mockFileSystem: mockFileSystem,
fs: fs,
errorCode: kUserMappedSectionOpened,
);
final File file = fs.file('file');
writeTests( const String expectedMessage = 'The file is being used by another program';
testName: 'when writing to a full device', expect(() async => await file.writeAsBytes(<int>[0]),
throwsToolExit(message: expectedMessage));
expect(() async => await file.writeAsString(''),
throwsToolExit(message: expectedMessage));
expect(() => file.writeAsBytesSync(<int>[0]),
throwsToolExit(message: expectedMessage));
expect(() => file.writeAsStringSync(''),
throwsToolExit(message: expectedMessage));
});
testWithoutContext('when creating a temporary dir on a full device', () async {
setupCreateTempMocks(
mockFileSystem: mockFileSystem,
fs: fs,
errorCode: kDeviceFull, errorCode: kDeviceFull,
expectedMessage: 'The target device is full',
); );
writeTests(
testName: 'when the file is being used by another program', final Directory directory = fs.directory('directory');
errorCode: kUserMappedSectionOpened,
expectedMessage: 'The file is being used by another program', const String expectedMessage = 'The target device is full';
expect(() async => await directory.createTemp('prefix'),
throwsToolExit(message: expectedMessage));
expect(() => directory.createTempSync('prefix'),
throwsToolExit(message: expectedMessage));
});
});
group('throws ToolExit on Linux', () {
const int enospc= 28;
MockFileSystem mockFileSystem;
ErrorHandlingFileSystem fs;
setUp(() {
mockFileSystem = MockFileSystem();
fs = ErrorHandlingFileSystem(
delegate: mockFileSystem,
platform: linuxPlatform,
);
when(mockFileSystem.path).thenReturn(MockPathContext());
});
testWithoutContext('when writing to a full device', () async {
setupWriteMocks(
mockFileSystem: mockFileSystem,
fs: fs,
errorCode: enospc,
);
final File file = fs.file('file');
const String expectedMessage = 'The target device is full';
expect(() async => await file.writeAsBytes(<int>[0]),
throwsToolExit(message: expectedMessage));
expect(() async => await file.writeAsString(''),
throwsToolExit(message: expectedMessage));
expect(() => file.writeAsBytesSync(<int>[0]),
throwsToolExit(message: expectedMessage));
expect(() => file.writeAsStringSync(''),
throwsToolExit(message: expectedMessage));
});
testWithoutContext('when creating a temporary dir on a full device', () async {
setupCreateTempMocks(
mockFileSystem: mockFileSystem,
fs: fs,
errorCode: enospc,
); );
final Directory directory = fs.directory('directory');
const String expectedMessage = 'The target device is full';
expect(() async => await directory.createTemp('prefix'),
throwsToolExit(message: expectedMessage));
expect(() => directory.createTempSync('prefix'),
throwsToolExit(message: expectedMessage));
});
}); });
test('Caches path context correctly', () { testWithoutContext('Caches path context correctly', () {
final MockFileSystem mockFileSystem = MockFileSystem(); final MockFileSystem mockFileSystem = MockFileSystem();
final FileSystem fs = ErrorHandlingFileSystem(mockFileSystem); final FileSystem fs = ErrorHandlingFileSystem(
delegate: mockFileSystem,
platform: const LocalPlatform(),
);
expect(identical(fs.path, fs.path), true); expect(identical(fs.path, fs.path), true);
}); });
test('Clears cache when CWD changes', () { testWithoutContext('Clears cache when CWD changes', () {
final MockFileSystem mockFileSystem = MockFileSystem(); final MockFileSystem mockFileSystem = MockFileSystem();
final FileSystem fs = ErrorHandlingFileSystem(mockFileSystem); final FileSystem fs = ErrorHandlingFileSystem(
delegate: mockFileSystem,
platform: const LocalPlatform(),
);
final Object firstPath = fs.path; final Object firstPath = fs.path;
...@@ -119,8 +224,11 @@ void main() { ...@@ -119,8 +224,11 @@ void main() {
expect(identical(firstPath, fs.path), false); expect(identical(firstPath, fs.path), false);
}); });
test('Throws type error if Directory type is set to curentDirectory with LocalFileSystem', () { testWithoutContext('Throws type error if Directory type is set to curentDirectory with LocalFileSystem', () {
final FileSystem fs = ErrorHandlingFileSystem(const LocalFileSystem()); final FileSystem fs = ErrorHandlingFileSystem(
delegate: const LocalFileSystem(),
platform: const LocalPlatform(),
);
final MockDirectory directory = MockDirectory(); final MockDirectory directory = MockDirectory();
when(directory.path).thenReturn('path'); when(directory.path).thenReturn('path');
...@@ -128,17 +236,23 @@ void main() { ...@@ -128,17 +236,23 @@ void main() {
}); });
group('toString() gives toString() of delegate', () { group('toString() gives toString() of delegate', () {
test('ErrorHandlingFileSystem', () { testWithoutContext('ErrorHandlingFileSystem', () {
final MockFileSystem mockFileSystem = MockFileSystem(); final MockFileSystem mockFileSystem = MockFileSystem();
final FileSystem fs = ErrorHandlingFileSystem(mockFileSystem); final FileSystem fs = ErrorHandlingFileSystem(
delegate: mockFileSystem,
platform: const LocalPlatform(),
);
expect(mockFileSystem.toString(), isNotNull); expect(mockFileSystem.toString(), isNotNull);
expect(fs.toString(), equals(mockFileSystem.toString())); expect(fs.toString(), equals(mockFileSystem.toString()));
}); });
test('ErrorHandlingFile', () { testWithoutContext('ErrorHandlingFile', () {
final MockFileSystem mockFileSystem = MockFileSystem(); final MockFileSystem mockFileSystem = MockFileSystem();
final FileSystem fs = ErrorHandlingFileSystem(mockFileSystem); final FileSystem fs = ErrorHandlingFileSystem(
delegate: mockFileSystem,
platform: const LocalPlatform(),
);
final MockFile mockFile = MockFile(); final MockFile mockFile = MockFile();
when(mockFileSystem.file(any)).thenReturn(mockFile); when(mockFileSystem.file(any)).thenReturn(mockFile);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment