mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* Update project.pbxproj files to say Flutter rather than Chromium Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright. * Update the copyright notice checker to require a standard notice on all files * Update copyrights on Dart files. (This was a mechanical commit.) * Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine. Some were already marked "The Flutter Authors", not clear why. Their dates have been normalized. Some were missing the blank line after the license. Some were randomly different in trivial ways for no apparent reason (e.g. missing the trailing period). * Clean up the copyrights in non-Dart files. (Manual edits.) Also, make sure templates don't have copyrights. * Fix some more ORGANIZATIONNAMEs
301 lines
7.8 KiB
Dart
301 lines
7.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 'package:flutter_tools/src/base/async_guard.dart';
|
|
import 'package:flutter_tools/src/base/common.dart';
|
|
import 'package:quiver/testing/async.dart';
|
|
|
|
import '../../src/common.dart';
|
|
|
|
Future<void> asyncError() {
|
|
final Completer<void> completer = Completer<void>();
|
|
final Completer<void> errorCompleter = Completer<void>();
|
|
errorCompleter.completeError('Async Doom', StackTrace.current);
|
|
return completer.future;
|
|
}
|
|
|
|
Future<void> syncError() {
|
|
throw 'Sync Doom';
|
|
}
|
|
|
|
Future<void> syncAndAsyncError() {
|
|
final Completer<void> errorCompleter = Completer<void>();
|
|
errorCompleter.completeError('Async Doom', StackTrace.current);
|
|
throw 'Sync Doom';
|
|
}
|
|
|
|
Future<void> delayedThrow(FakeAsync time) {
|
|
final Future<void> result =
|
|
Future<void>.delayed(const Duration(milliseconds: 10))
|
|
.then((_) {
|
|
throw 'Delayed Doom';
|
|
});
|
|
time.elapse(const Duration(seconds: 1));
|
|
time.flushMicrotasks();
|
|
return result;
|
|
}
|
|
|
|
void main() {
|
|
Completer<void> caughtInZone;
|
|
bool caughtByZone = false;
|
|
bool caughtByHandler = false;
|
|
Zone zone;
|
|
|
|
setUp(() {
|
|
caughtInZone = Completer<void>();
|
|
caughtByZone = false;
|
|
caughtByHandler = false;
|
|
zone = Zone.current.fork(specification: ZoneSpecification(
|
|
handleUncaughtError: (
|
|
Zone self,
|
|
ZoneDelegate parent,
|
|
Zone zone,
|
|
Object error,
|
|
StackTrace stackTrace,
|
|
) {
|
|
caughtByZone = true;
|
|
if (!caughtInZone.isCompleted) {
|
|
caughtInZone.complete();
|
|
}
|
|
},
|
|
));
|
|
});
|
|
|
|
test('asyncError percolates through zone', () async {
|
|
await zone.run(() async {
|
|
try {
|
|
// Completer is required or else we timeout.
|
|
await Future.any(<Future<void>>[asyncError(), caughtInZone.future]);
|
|
} on String {
|
|
caughtByHandler = true;
|
|
}
|
|
});
|
|
|
|
expect(caughtByZone, true);
|
|
expect(caughtByHandler, false);
|
|
});
|
|
|
|
test('syncAndAsyncError percolates through zone', () async {
|
|
await zone.run(() async {
|
|
try {
|
|
// Completer is required or else we timeout.
|
|
await Future.any(<Future<void>>[syncAndAsyncError(), caughtInZone.future]);
|
|
} on String {
|
|
caughtByHandler = true;
|
|
}
|
|
});
|
|
|
|
expect(caughtByZone, true);
|
|
expect(caughtByHandler, true);
|
|
});
|
|
|
|
test('syncError percolates through zone', () async {
|
|
await zone.run(() async {
|
|
try {
|
|
await syncError();
|
|
} on String {
|
|
caughtByHandler = true;
|
|
}
|
|
});
|
|
|
|
expect(caughtByZone, false);
|
|
expect(caughtByHandler, true);
|
|
});
|
|
|
|
test('syncError is caught by asyncGuard', () async {
|
|
await zone.run(() async {
|
|
try {
|
|
await asyncGuard(syncError);
|
|
} on String {
|
|
caughtByHandler = true;
|
|
}
|
|
});
|
|
|
|
expect(caughtByZone, false);
|
|
expect(caughtByHandler, true);
|
|
});
|
|
|
|
|
|
test('asyncError is caught by asyncGuard', () async {
|
|
await zone.run(() async {
|
|
try {
|
|
await asyncGuard(asyncError);
|
|
} on String {
|
|
caughtByHandler = true;
|
|
}
|
|
});
|
|
|
|
expect(caughtByZone, false);
|
|
expect(caughtByHandler, true);
|
|
});
|
|
|
|
test('asyncAndSyncError is caught by asyncGuard', () async {
|
|
await zone.run(() async {
|
|
try {
|
|
await asyncGuard(syncAndAsyncError);
|
|
} on String {
|
|
caughtByHandler = true;
|
|
}
|
|
});
|
|
|
|
expect(caughtByZone, false);
|
|
expect(caughtByHandler, true);
|
|
});
|
|
|
|
test('asyncError is missed when catchError is attached too late', () async {
|
|
bool caughtByZone = false;
|
|
bool caughtByHandler = false;
|
|
bool caughtByCatchError = false;
|
|
|
|
final Completer<void> completer = Completer<void>();
|
|
await FakeAsync().run((FakeAsync time) {
|
|
unawaited(runZoned(() async {
|
|
final Future<void> f = asyncGuard<void>(() => delayedThrow(time))
|
|
.catchError((Object e, StackTrace s) {
|
|
caughtByCatchError = true;
|
|
});
|
|
try {
|
|
await f;
|
|
} on String {
|
|
caughtByHandler = true;
|
|
}
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}, onError: (Object e, StackTrace s) {
|
|
caughtByZone = true;
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}));
|
|
time.elapse(const Duration(seconds: 1));
|
|
time.flushMicrotasks();
|
|
return completer.future;
|
|
});
|
|
|
|
expect(caughtByZone, true);
|
|
expect(caughtByHandler, false);
|
|
expect(caughtByCatchError, true);
|
|
});
|
|
|
|
test('asyncError is propagated with binary onError', () async {
|
|
bool caughtByZone = false;
|
|
bool caughtByHandler = false;
|
|
bool caughtByOnError = false;
|
|
|
|
final Completer<void> completer = Completer<void>();
|
|
await FakeAsync().run((FakeAsync time) {
|
|
unawaited(runZoned(() async {
|
|
final Future<void> f = asyncGuard<void>(
|
|
() => delayedThrow(time),
|
|
onError: (Object e, StackTrace s) {
|
|
caughtByOnError = true;
|
|
},
|
|
);
|
|
try {
|
|
await f;
|
|
} catch (e) {
|
|
caughtByHandler = true;
|
|
}
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}, onError: (Object e, StackTrace s) {
|
|
caughtByZone = true;
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}));
|
|
time.elapse(const Duration(seconds: 1));
|
|
time.flushMicrotasks();
|
|
return completer.future;
|
|
});
|
|
|
|
expect(caughtByZone, false);
|
|
expect(caughtByHandler, false);
|
|
expect(caughtByOnError, true);
|
|
});
|
|
|
|
test('asyncError is propagated with unary onError', () async {
|
|
bool caughtByZone = false;
|
|
bool caughtByHandler = false;
|
|
bool caughtByOnError = false;
|
|
|
|
final Completer<void> completer = Completer<void>();
|
|
await FakeAsync().run((FakeAsync time) {
|
|
unawaited(runZoned(() async {
|
|
final Future<void> f = asyncGuard<void>(
|
|
() => delayedThrow(time),
|
|
onError: (Object e) {
|
|
caughtByOnError = true;
|
|
},
|
|
);
|
|
try {
|
|
await f;
|
|
} catch (e) {
|
|
caughtByHandler = true;
|
|
}
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}, onError: (Object e, StackTrace s) {
|
|
caughtByZone = true;
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}));
|
|
time.elapse(const Duration(seconds: 1));
|
|
time.flushMicrotasks();
|
|
return completer.future;
|
|
});
|
|
|
|
expect(caughtByZone, false);
|
|
expect(caughtByHandler, false);
|
|
expect(caughtByOnError, true);
|
|
});
|
|
|
|
test('asyncError is propagated with optional stack trace', () async {
|
|
bool caughtByZone = false;
|
|
bool caughtByHandler = false;
|
|
bool caughtByOnError = false;
|
|
bool nonNullStackTrace = false;
|
|
|
|
final Completer<void> completer = Completer<void>();
|
|
await FakeAsync().run((FakeAsync time) {
|
|
unawaited(runZoned(() async {
|
|
final Future<void> f = asyncGuard<void>(
|
|
() => delayedThrow(time),
|
|
onError: (Object e, [StackTrace s]) {
|
|
caughtByOnError = true;
|
|
nonNullStackTrace = s != null;
|
|
},
|
|
);
|
|
try {
|
|
await f;
|
|
} catch (e) {
|
|
caughtByHandler = true;
|
|
}
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}, onError: (Object e, StackTrace s) {
|
|
caughtByZone = true;
|
|
if (!completer.isCompleted) {
|
|
completer.complete(null);
|
|
}
|
|
}));
|
|
time.elapse(const Duration(seconds: 1));
|
|
time.flushMicrotasks();
|
|
return completer.future;
|
|
});
|
|
|
|
expect(caughtByZone, false);
|
|
expect(caughtByHandler, false);
|
|
expect(caughtByOnError, true);
|
|
expect(nonNullStackTrace, true);
|
|
});
|
|
}
|