| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:io' as dart_io; |
| |
| import 'package:file/file.dart'; |
| import 'package:file/memory.dart'; |
| import 'package:process/process.dart'; |
| import 'package:test/test.dart'; |
| import 'package:fxutils/fxutils.dart' as fxutils; |
| import 'package:codesize/crash_handling.dart'; |
| import 'package:codesize/io.dart'; |
| |
| const _mockProcessOutput = '❌ MOCK ❌'; |
| |
| class MockIo implements Io { |
| static Map<Object, Object> inject() => {#io: MockIo()}; |
| |
| final FileSystem _fs = MemoryFileSystem(); |
| |
| final recordedOut = StringBuffer(); |
| |
| @override |
| StringSink get out => recordedOut; |
| |
| final recordedErr = StringBuffer(); |
| |
| @override |
| StringSink get err => recordedErr; |
| |
| @override |
| void print(Object object) { |
| dart_io.stdout.writeln(object); |
| } |
| |
| @override |
| ProcessManager get processManager => throw UnimplementedError(); |
| |
| final fxutils.FxEnv _fxEnv = fxutils.FxEnv.env(_environment); |
| |
| @override |
| fxutils.FxEnv get fxEnv => _fxEnv; |
| |
| @override |
| fxutils.Fx get fx => fxutils.Fx.mock( |
| fxutils.MockProcess.raw(stdout: _mockProcessOutput), _fxEnv); |
| |
| @override |
| set exitCode(int code) => mockExitCode = code; |
| |
| @override |
| String get cwd => '/cwd'; |
| |
| static const Map<String, String> _environment = <String, String>{ |
| 'FUCHSIA_DIR': '/root/path/fuchsia', |
| 'FUCHSIA_BUILD_DIR': '/root/path/fuchsia/out/default', |
| }; |
| |
| @override |
| Map<String, String> get environment => _environment; |
| |
| @override |
| File createTempFile(String name) => |
| _fs.systemTempDirectory.createTempSync().childFile(name); |
| |
| int mockExitCode = 0; |
| } |
| |
| void main() { |
| group('CrashHandling', () { |
| test( |
| 'Catch known exception', |
| () => runWithIo<MockIo, void>(() async { |
| await withExceptionHandler( |
| () => throw KnownFailure('example failure')); |
| MockIo io = Io.get(); |
| |
| // The exit code of a known exception. |
| expect(io.mockExitCode, equals(2)); |
| |
| // No crash logs should be created. |
| expect(io._fs.systemTempDirectory.listSync().length, equals(0)); |
| |
| expect(io.out.toString(), equals('')); |
| expect(io.err.toString(), contains('example failure')); |
| expect(io.err.toString(), |
| isNot(contains('Oops, `fx codesize` has crashed.'))); |
| })); |
| |
| test( |
| 'Catch unexpected error', |
| () => runWithIo<MockIo, void>(() async { |
| await withExceptionHandler( |
| () => throw Exception('unexpected error')); |
| MockIo io = Io.get(); |
| |
| /// The exit code of an unexpected error. |
| /// From https://fuchsia.dev/fuchsia-src/concepts/api/cli#execution_success_and_failure, |
| /// exit code 1 is meant for general errors. |
| expect(io.mockExitCode, equals(1)); |
| |
| // Some crash logs should be created. |
| final tmpDirs = io._fs.systemTempDirectory.listSync(); |
| expect(tmpDirs.length, equals(1)); |
| |
| expect(io.err.toString(), |
| contains('Oops, `fx codesize` has crashed.')); |
| |
| expect( |
| io.err.toString(), |
| contains(r''' |
| Brief error description: |
| Exception: unexpected error |
| ''' |
| .trim())); |
| |
| final crashLogPattern = RegExp( |
| ''' |
| Exception: unexpected error |
| |
| ======== fx status ======== |
| $_mockProcessOutput |
| |
| ======== stack trace ======== |
| #0.*crash_handling_test\\.dart.* |
| #1.* |
| ''' |
| .trim(), |
| multiLine: true); |
| |
| expect( |
| io._fs |
| .directory(tmpDirs.first) |
| .childFile('crash_report.txt') |
| .readAsStringSync(), |
| matches(crashLogPattern)); |
| })); |
| }); |
| } |