blob: 6778ee86f726fd6c97c5eb35f8424e50c4015d52 [file] [log] [blame]
// 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));
}));
});
}