CrashReportSender dependency injection (#54924)
diff --git a/packages/flutter_tools/lib/runner.dart b/packages/flutter_tools/lib/runner.dart
index 6b94d86..9520b11 100644
--- a/packages/flutter_tools/lib/runner.dart
+++ b/packages/flutter_tools/lib/runner.dart
@@ -7,7 +7,7 @@
import 'package:args/command_runner.dart';
import 'package:intl/intl.dart' as intl;
import 'package:intl/intl_standalone.dart' as intl_standalone;
-import 'package:meta/meta.dart';
+import 'package:http/http.dart' as http;
import 'src/base/common.dart';
import 'src/base/context.dart';
@@ -27,13 +27,13 @@
Future<int> run(
List<String> args,
List<FlutterCommand> commands, {
- bool muteCommandLogging = false,
- bool verbose = false,
- bool verboseHelp = false,
- bool reportCrashes,
- String flutterVersion,
- Map<Type, Generator> overrides,
-}) async {
+ bool muteCommandLogging = false,
+ bool verbose = false,
+ bool verboseHelp = false,
+ bool reportCrashes,
+ String flutterVersion,
+ Map<Type, Generator> overrides,
+ }) async {
if (muteCommandLogging) {
// Remove the verbose option; for help and doctor, users don't need to see
// verbose logs.
@@ -121,7 +121,14 @@
// Report to both [Usage] and [CrashReportSender].
globals.flutterUsage.sendException(error);
- await CrashReportSender.instance.sendReport(
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: http.Client(),
+ usage: globals.flutterUsage,
+ platform: globals.platform,
+ logger: globals.logger,
+ operatingSystemUtils: globals.os,
+ );
+ await crashReportSender.sendReport(
error: error,
stackTrace: stackTrace,
getFlutterVersion: getFlutterVersion,
@@ -184,18 +191,10 @@
String _crashException(dynamic error) => '${error.runtimeType}: $error';
-/// File system used by the crash reporting logic.
-///
-/// We do not want to use the file system stored in the context because it may
-/// be recording. Additionally, in the case of a crash we do not trust the
-/// integrity of the [AppContext].
-@visibleForTesting
-FileSystem crashFileSystem = const LocalFileSystem();
-
/// Saves the crash report to a local file.
Future<File> _createLocalCrashReport(List<String> args, dynamic error, StackTrace stackTrace, String doctorText) async {
File crashFile = globals.fsUtils.getUniqueFile(
- crashFileSystem.currentDirectory,
+ globals.fs.currentDirectory,
'flutter',
'log',
);
@@ -219,7 +218,7 @@
} on FileSystemException catch (_) {
// Fallback to the system temporary directory.
crashFile = globals.fsUtils.getUniqueFile(
- crashFileSystem.systemTempDirectory,
+ globals.fs.systemTempDirectory,
'flutter',
'log',
);
diff --git a/packages/flutter_tools/lib/src/reporting/crash_reporting.dart b/packages/flutter_tools/lib/src/reporting/crash_reporting.dart
index ee52f55..04425ec 100644
--- a/packages/flutter_tools/lib/src/reporting/crash_reporting.dart
+++ b/packages/flutter_tools/lib/src/reporting/crash_reporting.dart
@@ -35,28 +35,29 @@
/// environment is behind a firewall and unable to send crash reports to
/// Google, or when you wish to use your own server for collecting crash
/// reports from Flutter Tools.
-/// * In tests call [initializeWith] and provide a mock implementation of
-/// [http.Client].
class CrashReportSender {
- CrashReportSender._(this._client);
+ CrashReportSender({
+ @required http.Client client,
+ @required Usage usage,
+ @required Platform platform,
+ @required Logger logger,
+ @required OperatingSystemUtils operatingSystemUtils,
+ }) : _client = client,
+ _usage = usage,
+ _platform = platform,
+ _logger = logger,
+ _operatingSystemUtils = operatingSystemUtils;
- static CrashReportSender _instance;
-
- static CrashReportSender get instance => _instance ?? CrashReportSender._(http.Client());
+ final http.Client _client;
+ final Usage _usage;
+ final Platform _platform;
+ final Logger _logger;
+ final OperatingSystemUtils _operatingSystemUtils;
bool _crashReportSent = false;
- /// Overrides the default [http.Client] with [client] for testing purposes.
- @visibleForTesting
- static void initializeWith(http.Client client) {
- _instance = CrashReportSender._(client);
- }
-
- final http.Client _client;
- final Usage _usage = globals.flutterUsage;
-
Uri get _baseUrl {
- final String overrideUrl = globals.platform.environment['FLUTTER_CRASH_SERVER_BASE_URL'];
+ final String overrideUrl = _platform.environment['FLUTTER_CRASH_SERVER_BASE_URL'];
if (overrideUrl != null) {
return Uri.parse(overrideUrl);
@@ -90,7 +91,7 @@
return;
}
- globals.printTrace('Sending crash report to Google.');
+ _logger.printTrace('Sending crash report to Google.');
final Uri uri = _baseUrl.replace(
queryParameters: <String, String>{
@@ -103,8 +104,8 @@
req.fields['uuid'] = _usage.clientId;
req.fields['product'] = _kProductId;
req.fields['version'] = flutterVersion;
- req.fields['osName'] = globals.platform.operatingSystem;
- req.fields['osVersion'] = globals.os.name; // this actually includes version
+ req.fields['osName'] = _platform.operatingSystem;
+ req.fields['osVersion'] = _operatingSystemUtils.name; // this actually includes version
req.fields['type'] = _kDartTypeId;
req.fields['error_runtime_type'] = '${error.runtimeType}';
req.fields['error_message'] = '$error';
@@ -120,20 +121,20 @@
if (resp.statusCode == 200) {
final String reportId = await http.ByteStream(resp.stream)
- .bytesToString();
- globals.printTrace('Crash report sent (report ID: $reportId)');
+ .bytesToString();
+ _logger.printTrace('Crash report sent (report ID: $reportId)');
_crashReportSent = true;
} else {
- globals.printError('Failed to send crash report. Server responded with HTTP status code ${resp.statusCode}');
+ _logger.printError('Failed to send crash report. Server responded with HTTP status code ${resp.statusCode}');
}
// Catch all exceptions to print the message that makes clear that the
// crash logger crashed.
} catch (sendError, sendStackTrace) { // ignore: avoid_catches_without_on_clauses
if (sendError is SocketException || sendError is HttpException) {
- globals.printError('Failed to send crash report due to a network error: $sendError');
+ _logger.printError('Failed to send crash report due to a network error: $sendError');
} else {
// If the sender itself crashes, just print. We did our best.
- globals.printError('Crash report sender itself crashed: $sendError\n$sendStackTrace');
+ _logger.printError('Crash report sender itself crashed: $sendError\n$sendStackTrace');
}
}
}
diff --git a/packages/flutter_tools/lib/src/reporting/reporting.dart b/packages/flutter_tools/lib/src/reporting/reporting.dart
index e583eb4..3666946 100644
--- a/packages/flutter_tools/lib/src/reporting/reporting.dart
+++ b/packages/flutter_tools/lib/src/reporting/reporting.dart
@@ -10,11 +10,13 @@
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:meta/meta.dart';
+import 'package:platform/platform.dart';
import 'package:usage/usage_io.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
+import '../base/os.dart';
import '../base/process.dart';
import '../base/time.dart';
import '../build_system/exceptions.dart';
diff --git a/packages/flutter_tools/test/general.shard/crash_reporting_test.dart b/packages/flutter_tools/test/general.shard/crash_reporting_test.dart
index fe401d7..5162581 100644
--- a/packages/flutter_tools/test/general.shard/crash_reporting_test.dart
+++ b/packages/flutter_tools/test/general.shard/crash_reporting_test.dart
@@ -5,160 +5,205 @@
import 'dart:async';
import 'dart:convert';
-import 'package:file/file.dart';
-import 'package:file/local.dart';
import 'package:file/memory.dart';
-import 'package:flutter_tools/runner.dart' as tools;
-import 'package:flutter_tools/src/base/common.dart';
-import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/cache.dart';
+import 'package:flutter_tools/src/base/logger.dart';
+import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
-import 'package:flutter_tools/src/runner/flutter_command.dart';
-import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:http/http.dart';
import 'package:http/testing.dart';
-import 'package:quiver/testing/async.dart';
+import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import '../src/common.dart';
import '../src/context.dart';
void main() {
- group('crash reporting', () {
- setUpAll(() {
- Cache.disableLocking();
- });
+ BufferLogger logger;
+ MockUsage mockUsage;
+ Platform platform;
+ OperatingSystemUtils operatingSystemUtils;
+ setUp(() async {
+ logger = BufferLogger.test();
+
+ mockUsage = MockUsage();
+ when(mockUsage.clientId).thenReturn('00000000-0000-4000-0000-000000000000');
+
+ platform = FakePlatform(environment: <String, String>{}, operatingSystem: 'linux');
+ operatingSystemUtils = OperatingSystemUtils(
+ fileSystem: MemoryFileSystem.test(),
+ logger: logger,
+ platform: platform,
+ processManager: FakeProcessManager.any(),
+ );
+
+ MockCrashReportSender.sendCalls = 0;
+ });
+
+ Future<void> verifyCrashReportSent(RequestInfo crashInfo, {
+ int crashes = 1,
+ }) async {
+ // Verify that we sent the crash report.
+ expect(crashInfo.method, 'POST');
+ expect(crashInfo.uri, Uri(
+ scheme: 'https',
+ host: 'clients2.google.com',
+ port: 443,
+ path: '/cr/report',
+ queryParameters: <String, String>{
+ 'product': 'Flutter_Tools',
+ 'version': 'test-version',
+ },
+ ));
+ expect(crashInfo.fields['uuid'], '00000000-0000-4000-0000-000000000000');
+ expect(crashInfo.fields['product'], 'Flutter_Tools');
+ expect(crashInfo.fields['version'], 'test-version');
+ expect(crashInfo.fields['osName'], 'linux');
+ expect(crashInfo.fields['osVersion'], 'Linux');
+ expect(crashInfo.fields['type'], 'DartError');
+ expect(crashInfo.fields['error_runtime_type'], 'StateError');
+ expect(crashInfo.fields['error_message'], 'Bad state: Test bad state error');
+ expect(crashInfo.fields['comments'], 'crash');
+
+ expect(logger.traceText, contains('Sending crash report to Google.'));
+ expect(logger.traceText, contains('Crash report sent (report ID: test-report-id)'));
+ }
+
+ testWithoutContext('suppress analytics', () async {
+ when(mockUsage.suppressAnalytics).thenReturn(true);
+
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: CrashingCrashReportSender(const SocketException('no internets')),
+ usage: mockUsage,
+ platform: platform,
+ logger: logger,
+ operatingSystemUtils: operatingSystemUtils,
+ );
+
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
+
+ expect(logger.traceText, isEmpty);
+ });
+
+ group('allow analytics', () {
setUp(() async {
- tools.crashFileSystem = MemoryFileSystem();
- setExitFunctionForTests((_) { });
- MockCrashReportSender.sendCalls = 0;
+ when(mockUsage.suppressAnalytics).thenReturn(false);
});
- tearDown(() {
- tools.crashFileSystem = const LocalFileSystem();
- restoreExitFunction();
- });
-
- testUsingContext('should send crash reports', () async {
+ testWithoutContext('should send crash reports', () async {
final RequestInfo requestInfo = RequestInfo();
- CrashReportSender.initializeWith(MockCrashReportSender(requestInfo));
- final int exitCode = await tools.run(
- <String>['crash'],
- <FlutterCommand>[_CrashCommand()],
- reportCrashes: true,
- flutterVersion: 'test-version',
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: MockCrashReportSender(requestInfo),
+ usage: mockUsage,
+ platform: platform,
+ logger: logger,
+ operatingSystemUtils: operatingSystemUtils,
);
- expect(exitCode, 1);
+
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
await verifyCrashReportSent(requestInfo);
- }, overrides: <Type, Generator>{
- Stdio: () => _NoStderr(),
});
- testUsingContext('should print an explanatory message when there is a SocketException', () async {
- final Completer<int> exitCodeCompleter = Completer<int>();
- setExitFunctionForTests((int exitCode) {
- exitCodeCompleter.complete(exitCode);
- });
+ testWithoutContext('should print an explanatory message when there is a SocketException', () async {
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: CrashingCrashReportSender(const SocketException('no internets')),
+ usage: mockUsage,
+ platform: platform,
+ logger: logger,
+ operatingSystemUtils: operatingSystemUtils,
+ );
- CrashReportSender.initializeWith(
- CrashingCrashReportSender(const SocketException('no internets')));
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
- unawaited(tools.run(
- <String>['crash'],
- <FlutterCommand>[_CrashAsyncCommand()],
- reportCrashes: true,
- flutterVersion: 'test-version',
- ));
- expect(await exitCodeCompleter.future, 1);
- expect(testLogger.errorText, contains('Failed to send crash report due to a network error'));
- }, overrides: <Type, Generator>{
- Stdio: () => _NoStderr(),
+ expect(logger.errorText, contains('Failed to send crash report due to a network error'));
});
- testUsingContext('should print an explanatory message when there is an HttpException', () async {
- final Completer<int> exitCodeCompleter = Completer<int>();
- setExitFunctionForTests((int exitCode) {
- exitCodeCompleter.complete(exitCode);
- });
+ testWithoutContext('should print an explanatory message when there is an HttpException', () async {
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: CrashingCrashReportSender(const HttpException('no internets')),
+ usage: mockUsage,
+ platform: platform,
+ logger: logger,
+ operatingSystemUtils: operatingSystemUtils,
+ );
- CrashReportSender.initializeWith(
- CrashingCrashReportSender(const HttpException('no internets')));
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
- unawaited(tools.run(
- <String>['crash'],
- <FlutterCommand>[_CrashAsyncCommand()],
- reportCrashes: true,
- flutterVersion: 'test-version',
- ));
- expect(await exitCodeCompleter.future, 1);
- expect(testLogger.errorText, contains('Failed to send crash report due to a network error'));
- }, overrides: <Type, Generator>{
- Stdio: () => _NoStderr(),
+ expect(logger.errorText, contains('Failed to send crash report due to a network error'));
});
- testUsingContext('should send crash reports when async throws', () async {
- final Completer<int> exitCodeCompleter = Completer<int>();
- setExitFunctionForTests((int exitCode) {
- exitCodeCompleter.complete(exitCode);
- });
-
+ testWithoutContext('should send only one crash report when sent many times', () async {
final RequestInfo requestInfo = RequestInfo();
- CrashReportSender.initializeWith(MockCrashReportSender(requestInfo));
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: MockCrashReportSender(requestInfo),
+ usage: mockUsage,
+ platform: platform,
+ logger: logger,
+ operatingSystemUtils: operatingSystemUtils,
+ );
- unawaited(tools.run(
- <String>['crash'],
- <FlutterCommand>[_CrashAsyncCommand()],
- reportCrashes: true,
- flutterVersion: 'test-version',
- ));
- expect(await exitCodeCompleter.future, 1);
- await verifyCrashReportSent(requestInfo);
- }, overrides: <Type, Generator>{
- Stdio: () => _NoStderr(),
- });
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
- testUsingContext('should send only one crash report when async throws many', () async {
- final Completer<int> exitCodeCompleter = Completer<int>();
- setExitFunctionForTests((int exitCode) {
- if (!exitCodeCompleter.isCompleted) {
- exitCodeCompleter.complete(exitCode);
- }
- });
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
- final RequestInfo requestInfo = RequestInfo();
- final MockCrashReportSender sender = MockCrashReportSender(requestInfo);
- CrashReportSender.initializeWith(sender);
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
- FakeAsync().run((FakeAsync time) {
- time.elapse(const Duration(seconds: 1));
- unawaited(tools.run(
- <String>['crash'],
- <FlutterCommand>[_MultiCrashAsyncCommand(crashes: 4)],
- reportCrashes: true,
- flutterVersion: 'test-version',
- ));
- time.elapse(const Duration(seconds: 1));
- time.flushMicrotasks();
- });
- expect(await exitCodeCompleter.future, 1);
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
+
expect(MockCrashReportSender.sendCalls, 1);
await verifyCrashReportSent(requestInfo, crashes: 4);
- }, overrides: <Type, Generator>{
- DoctorValidatorsProvider: () => FakeDoctorValidatorsProvider(),
- Stdio: () => _NoStderr(),
});
- testUsingContext('should not send a crash report if on a user-branch', () async {
+ testWithoutContext('should not send a crash report if on a user-branch', () async {
String method;
Uri uri;
- CrashReportSender.initializeWith(MockClient((Request request) async {
+ final MockClient mockClient = MockClient((Request request) async {
method = request.method;
uri = request.url;
@@ -166,41 +211,60 @@
'test-report-id',
200,
);
- }));
+ });
- final int exitCode = await tools.run(
- <String>['crash'],
- <FlutterCommand>[_CrashCommand()],
- reportCrashes: true,
- flutterVersion: '[user-branch]/v1.2.3',
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: mockClient,
+ usage: mockUsage,
+ platform: platform,
+ logger: logger,
+ operatingSystemUtils: operatingSystemUtils,
);
- expect(exitCode, 1);
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => '[user-branch]/v1.2.3',
+ command: 'crash',
+ );
// Verify that the report wasn't sent
expect(method, null);
expect(uri, null);
- expect(testLogger.traceText, isNot(contains('Crash report sent')));
- }, overrides: <Type, Generator>{
- Stdio: () => _NoStderr(),
+ expect(logger.traceText, isNot(contains('Crash report sent')));
});
- testUsingContext('can override base URL', () async {
+ testWithoutContext('can override base URL', () async {
Uri uri;
- CrashReportSender.initializeWith(MockClient((Request request) async {
+ final MockClient mockClient = MockClient((Request request) async {
uri = request.url;
return Response('test-report-id', 200);
- }));
+ });
- final int exitCode = await tools.run(
- <String>['crash'],
- <FlutterCommand>[_CrashCommand()],
- reportCrashes: true,
- flutterVersion: 'test-version',
+ final Platform environmentPlatform = FakePlatform(
+ operatingSystem: 'linux',
+ environment: <String, String>{
+ 'HOME': '/',
+ 'FLUTTER_CRASH_SERVER_BASE_URL': 'https://localhost:12345/fake_server',
+ },
+ script: Uri(scheme: 'data'),
);
- expect(exitCode, 1);
+ final CrashReportSender crashReportSender = CrashReportSender(
+ client: mockClient,
+ usage: mockUsage,
+ platform: environmentPlatform,
+ logger: logger,
+ operatingSystemUtils: operatingSystemUtils,
+ );
+
+ await crashReportSender.sendReport(
+ error: StateError('Test bad state error'),
+ stackTrace: null,
+ getFlutterVersion: () => 'test-version',
+ command: 'crash',
+ );
// Verify that we sent the crash report.
expect(uri, isNotNull);
@@ -214,16 +278,6 @@
'version': 'test-version',
},
));
- }, overrides: <Type, Generator>{
- Platform: () => FakePlatform(
- operatingSystem: 'linux',
- environment: <String, String>{
- 'HOME': '/',
- 'FLUTTER_CRASH_SERVER_BASE_URL': 'https://localhost:12345/fake_server',
- },
- script: Uri(scheme: 'data'),
- ),
- Stdio: () => _NoStderr(),
});
});
}
@@ -234,42 +288,6 @@
Map<String, String> fields;
}
-Future<void> verifyCrashReportSent(RequestInfo crashInfo, {
- int crashes = 1,
-}) async {
- // Verify that we sent the crash report.
- expect(crashInfo.method, 'POST');
- expect(crashInfo.uri, Uri(
- scheme: 'https',
- host: 'clients2.google.com',
- port: 443,
- path: '/cr/report',
- queryParameters: <String, String>{
- 'product': 'Flutter_Tools',
- 'version': 'test-version',
- },
- ));
- expect(crashInfo.fields['uuid'], '00000000-0000-4000-0000-000000000000');
- expect(crashInfo.fields['product'], 'Flutter_Tools');
- expect(crashInfo.fields['version'], 'test-version');
- expect(crashInfo.fields['osName'], globals.platform.operatingSystem);
- expect(crashInfo.fields['osVersion'], 'fake OS name and version');
- expect(crashInfo.fields['type'], 'DartError');
- expect(crashInfo.fields['error_runtime_type'], 'StateError');
- expect(crashInfo.fields['error_message'], 'Bad state: Test bad state error');
- expect(crashInfo.fields['comments'], 'crash');
-
- expect(testLogger.traceText, contains('Sending crash report to Google.'));
- expect(testLogger.traceText, contains('Crash report sent (report ID: test-report-id)'));
-
- // Verify that we've written the crash report to disk.
- final List<String> writtenFiles =
- (await tools.crashFileSystem.directory('/').list(recursive: true).toList())
- .map((FileSystemEntity e) => e.path).toList();
- expect(writtenFiles, hasLength(crashes));
- expect(writtenFiles, contains('flutter_01.log'));
-}
-
class MockCrashReportSender extends MockClient {
MockCrashReportSender(RequestInfo crashInfo) : super((Request request) async {
MockCrashReportSender.sendCalls++;
@@ -283,14 +301,14 @@
utf8.decode(request.bodyBytes)
.split('--$boundary')
.map<List<String>>((String part) {
- final Match nameMatch = RegExp(r'name="(.*)"').firstMatch(part);
- if (nameMatch == null) {
- return null;
- }
- final String name = nameMatch[1];
- final String value = part.split('\n').skip(2).join('\n').trim();
- return <String>[name, value];
- })
+ final Match nameMatch = RegExp(r'name="(.*)"').firstMatch(part);
+ if (nameMatch == null) {
+ return null;
+ }
+ final String name = nameMatch[1];
+ final String value = part.split('\n').skip(2).join('\n').trim();
+ return <String>[name, value];
+ })
.where((List<String> pair) => pair != null),
key: (dynamic key) {
final List<String> pair = key as List<String>;
@@ -317,78 +335,6 @@
});
}
-/// Throws a random error to simulate a CLI crash.
-class _CrashCommand extends FlutterCommand {
-
- @override
- String get description => 'Simulates a crash';
-
- @override
- String get name => 'crash';
-
- @override
- Future<FlutterCommandResult> runCommand() async {
- void fn1() {
- throw StateError('Test bad state error');
- }
-
- void fn2() {
- fn1();
- }
-
- void fn3() {
- fn2();
- }
-
- fn3();
-
- return FlutterCommandResult.success();
- }
-}
-
-/// Throws StateError from async callback.
-class _CrashAsyncCommand extends FlutterCommand {
-
- @override
- String get description => 'Simulates a crash';
-
- @override
- String get name => 'crash';
-
- @override
- Future<FlutterCommandResult> runCommand() async {
- Timer.run(() {
- throw StateError('Test bad state error');
- });
- return Completer<FlutterCommandResult>().future; // expect StateError
- }
-}
-
-/// Generates multiple asynchronous unhandled exceptions.
-class _MultiCrashAsyncCommand extends FlutterCommand {
- _MultiCrashAsyncCommand({
- int crashes = 1,
- }) : _crashes = crashes;
-
- final int _crashes;
-
- @override
- String get description => 'Simulates a crash';
-
- @override
- String get name => 'crash';
-
- @override
- Future<FlutterCommandResult> runCommand() async {
- for (int i = 0; i < _crashes; i++) {
- Timer.run(() {
- throw StateError('Test bad state error');
- });
- }
- return Completer<FlutterCommandResult>().future; // expect StateError
- }
-}
-
/// A DoctorValidatorsProvider that overrides the default validators without
/// overriding the doctor.
class FakeDoctorValidatorsProvider implements DoctorValidatorsProvider {
@@ -399,49 +345,4 @@
List<Workflow> get workflows => <Workflow>[];
}
-class _NoStderr extends Stdio {
- _NoStderr();
-
- @override
- IOSink get stderr => const _NoopIOSink();
-}
-
-class _NoopIOSink implements IOSink {
- const _NoopIOSink();
-
- @override
- Encoding get encoding => utf8;
-
- @override
- set encoding(_) => throw UnsupportedError('');
-
- @override
- void add(_) { }
-
- @override
- void write(_) { }
-
- @override
- void writeAll(_, [ __ = '' ]) { }
-
- @override
- void writeln([ _ = '' ]) { }
-
- @override
- void writeCharCode(_) { }
-
- @override
- void addError(_, [ __ ]) { }
-
- @override
- Future<dynamic> addStream(_) async { }
-
- @override
- Future<dynamic> flush() async { }
-
- @override
- Future<dynamic> close() async { }
-
- @override
- Future<dynamic> get done async { }
-}
+class MockUsage extends Mock implements Usage {}
diff --git a/packages/flutter_tools/test/general.shard/runner/runner_test.dart b/packages/flutter_tools/test/general.shard/runner/runner_test.dart
index 38ff6a4..44d3d79 100644
--- a/packages/flutter_tools/test/general.shard/runner/runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/runner/runner_test.dart
@@ -24,7 +24,6 @@
MockGitHubTemplateCreator mockGitHubTemplateCreator;
setUp(() {
mockGitHubTemplateCreator = MockGitHubTemplateCreator();
- runner.crashFileSystem = MemoryFileSystem();
// Instead of exiting with dart:io exit(), this causes an exception to
// be thrown, which we catch with the onError callback in the zone below.
io.setExitFunctionForTests((int _) { throw 'test exit';});
@@ -32,7 +31,6 @@
});
tearDown(() {
- runner.crashFileSystem = const LocalFileSystem();
io.restoreExitFunction();
Cache.enableLocking();
});