mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
200 lines
5.8 KiB
Dart
200 lines
5.8 KiB
Dart
// Copyright 2014 The Flutter 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:async';
|
|
import 'dart:io' as io;
|
|
|
|
import 'package:flutter_tools/src/base/io.dart';
|
|
import 'package:flutter_tools/src/base/signals.dart';
|
|
import 'package:mockito/mockito.dart';
|
|
|
|
import '../../src/common.dart';
|
|
|
|
void main() {
|
|
group('Signals', () {
|
|
Signals signals;
|
|
MockIoProcessSignal mockSignal;
|
|
ProcessSignal signalUnderTest;
|
|
StreamController<io.ProcessSignal> controller;
|
|
|
|
setUp(() {
|
|
signals = Signals.test();
|
|
mockSignal = MockIoProcessSignal();
|
|
signalUnderTest = ProcessSignal(mockSignal);
|
|
controller = StreamController<io.ProcessSignal>();
|
|
when(mockSignal.watch()).thenAnswer((Invocation invocation) => controller.stream);
|
|
});
|
|
|
|
testWithoutContext('signal handler runs', () async {
|
|
final Completer<void> completer = Completer<void>();
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
expect(s, signalUnderTest);
|
|
completer.complete();
|
|
});
|
|
|
|
controller.add(mockSignal);
|
|
await completer.future;
|
|
});
|
|
|
|
testWithoutContext('signal handlers run in order', () async {
|
|
final Completer<void> completer = Completer<void>();
|
|
|
|
bool first = false;
|
|
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
expect(s, signalUnderTest);
|
|
first = true;
|
|
});
|
|
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
expect(s, signalUnderTest);
|
|
expect(first, isTrue);
|
|
completer.complete();
|
|
});
|
|
|
|
controller.add(mockSignal);
|
|
await completer.future;
|
|
});
|
|
|
|
testWithoutContext('signal handler error goes on error stream', () async {
|
|
final Exception exn = Exception('Error');
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
throw exn;
|
|
});
|
|
|
|
final Completer<void> completer = Completer<void>();
|
|
final List<Object> errList = <Object>[];
|
|
final StreamSubscription<Object> errSub = signals.errors.listen(
|
|
(Object err) {
|
|
errList.add(err);
|
|
completer.complete();
|
|
},
|
|
);
|
|
|
|
controller.add(mockSignal);
|
|
await completer.future;
|
|
await errSub.cancel();
|
|
expect(errList, contains(exn));
|
|
});
|
|
|
|
testWithoutContext('removed signal handler does not run', () async {
|
|
final Object token = signals.addHandler(
|
|
signalUnderTest,
|
|
(ProcessSignal s) {
|
|
fail('Signal handler should have been removed.');
|
|
},
|
|
);
|
|
|
|
await signals.removeHandler(signalUnderTest, token);
|
|
|
|
final List<Object> errList = <Object>[];
|
|
final StreamSubscription<Object> errSub = signals.errors.listen(
|
|
(Object err) {
|
|
errList.add(err);
|
|
},
|
|
);
|
|
|
|
controller.add(mockSignal);
|
|
|
|
await errSub.cancel();
|
|
expect(errList, isEmpty);
|
|
});
|
|
|
|
testWithoutContext('non-removed signal handler still runs', () async {
|
|
final Completer<void> completer = Completer<void>();
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
expect(s, signalUnderTest);
|
|
completer.complete();
|
|
});
|
|
|
|
final Object token = signals.addHandler(
|
|
signalUnderTest,
|
|
(ProcessSignal s) {
|
|
fail('Signal handler should have been removed.');
|
|
},
|
|
);
|
|
await signals.removeHandler(signalUnderTest, token);
|
|
|
|
final List<Object> errList = <Object>[];
|
|
final StreamSubscription<Object> errSub = signals.errors.listen(
|
|
(Object err) {
|
|
errList.add(err);
|
|
},
|
|
);
|
|
|
|
controller.add(mockSignal);
|
|
await completer.future;
|
|
await errSub.cancel();
|
|
expect(errList, isEmpty);
|
|
});
|
|
|
|
testWithoutContext('only handlers for the correct signal run', () async {
|
|
final MockIoProcessSignal mockSignal2 = MockIoProcessSignal();
|
|
final StreamController<io.ProcessSignal> controller2 = StreamController<io.ProcessSignal>();
|
|
final ProcessSignal otherSignal = ProcessSignal(mockSignal2);
|
|
|
|
when(mockSignal2.watch()).thenAnswer((Invocation invocation) => controller2.stream);
|
|
|
|
final Completer<void> completer = Completer<void>();
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
expect(s, signalUnderTest);
|
|
completer.complete();
|
|
});
|
|
|
|
signals.addHandler(otherSignal, (ProcessSignal s) {
|
|
fail('Wrong signal!.');
|
|
});
|
|
|
|
final List<Object> errList = <Object>[];
|
|
final StreamSubscription<Object> errSub = signals.errors.listen(
|
|
(Object err) {
|
|
errList.add(err);
|
|
},
|
|
);
|
|
|
|
controller.add(mockSignal);
|
|
await completer.future;
|
|
await errSub.cancel();
|
|
expect(errList, isEmpty);
|
|
});
|
|
|
|
testWithoutContext('all handlers for exiting signals are run before exit', () async {
|
|
final Signals signals = Signals.test(
|
|
exitSignals: <ProcessSignal>[signalUnderTest],
|
|
);
|
|
final Completer<void> completer = Completer<void>();
|
|
bool first = false;
|
|
bool second = false;
|
|
|
|
setExitFunctionForTests((int exitCode) {
|
|
// Both handlers have run before exit is called.
|
|
expect(first, isTrue);
|
|
expect(second, isTrue);
|
|
expect(exitCode, 0);
|
|
restoreExitFunction();
|
|
completer.complete();
|
|
});
|
|
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
expect(s, signalUnderTest);
|
|
expect(first, isFalse);
|
|
expect(second, isFalse);
|
|
first = true;
|
|
});
|
|
|
|
signals.addHandler(signalUnderTest, (ProcessSignal s) {
|
|
expect(s, signalUnderTest);
|
|
expect(first, isTrue);
|
|
expect(second, isFalse);
|
|
second = true;
|
|
});
|
|
|
|
controller.add(mockSignal);
|
|
await completer.future;
|
|
});
|
|
});
|
|
}
|
|
|
|
class MockIoProcessSignal extends Mock implements io.ProcessSignal {}
|