1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-03 00:08:46 +00:00

Add more information to ParalleWaitError.toString.

Gives the constructor optional parameters for providing
more information that can be used in the `toString` message,
and the `stackTrace` getter.
Makes the `iterable.wait` and `record.wait` extension methods
provide such information, so that the `toString` will always
contain the text of *one* of the errors.

(No issue, problem with logging was brought up in chat.)

Change-Id: I5f9a20ad0af0c64a2e7ff3cdb56f187a5cf5a3ca
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/353080
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Lasse Nielsen <lrn@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2024-02-28 20:36:58 +00:00 committed by Commit Queue
parent 4642c73347
commit 1436635d27
4 changed files with 322 additions and 122 deletions

View File

@ -42,6 +42,13 @@
### Libraries
#### `dart:async`
- Added option for `ParallelWaitError` to get some meta-information that
it can expose in its `toString`, and the `Iterable<Future>.wait` and
`(Future,...,Future).wait` extension methods now provide that information.
Should make a `ParallelWaitError` easier to log.
#### `dart:ffi`
- Added `Struct.create` and `Union.create` to create struct and union views

View File

@ -36,16 +36,18 @@ extension FutureIterable<T> on Iterable<Future<T>> {
if (errors == 0) {
c.complete([for (var r in results) r.value]);
} else {
var errorList = [for (var r in results) r.errorOrNull];
c.completeError(ParallelWaitError<List<T?>, List<AsyncError?>>(
[for (var r in results) r.valueOrNull],
[for (var r in results) r.errorOrNull],
));
[for (var r in results) r.valueOrNull], errorList,
errorCount: errors, defaultError: errorList.firstWhere(_notNull)));
}
});
return c.future;
}
}
bool _notNull(Object? object) => object != null;
/// Parallel operations on a record of futures.
///
/// {@template record-parallel-wait}
@ -81,6 +83,8 @@ extension FutureRecord2<T1, T2> on (Future<T1>, Future<T2>) {
c.completeError(ParallelWaitError(
(v1.valueOrNull, v2.valueOrNull),
(v1.errorOrNull, v2.errorOrNull),
errorCount: errors,
defaultError: v1.errorOrNull ?? v2.errorOrNull
));
}
});
@ -105,6 +109,8 @@ extension FutureRecord3<T1, T2, T3> on (Future<T1>, Future<T2>, Future<T3>) {
c.completeError(ParallelWaitError(
(v1.valueOrNull, v2.valueOrNull, v3.valueOrNull),
(v1.errorOrNull, v2.errorOrNull, v3.errorOrNull),
errorCount: errors,
defaultError: v1.errorOrNull ?? v2.errorOrNull ?? v3.errorOrNull,
));
}
});
@ -135,6 +141,11 @@ extension FutureRecord4<T1, T2, T3, T4> on (
c.completeError(ParallelWaitError(
(v1.valueOrNull, v2.valueOrNull, v3.valueOrNull, v4.valueOrNull),
(v1.errorOrNull, v2.errorOrNull, v3.errorOrNull, v4.errorOrNull),
errorCount: errors,
defaultError: v1.errorOrNull ??
v2.errorOrNull ??
v3.errorOrNull ??
v4.errorOrNull,
));
}
});
@ -179,6 +190,12 @@ extension FutureRecord5<T1, T2, T3, T4, T5> on (
v4.errorOrNull,
v5.errorOrNull
),
errorCount: errors,
defaultError: v1.errorOrNull ??
v2.errorOrNull ??
v3.errorOrNull ??
v4.errorOrNull ??
v5.errorOrNull
));
}
});
@ -227,7 +244,14 @@ extension FutureRecord6<T1, T2, T3, T4, T5, T6> on (
v4.errorOrNull,
v5.errorOrNull,
v6.errorOrNull
),
),
errorCount: errors,
defaultError: v1.errorOrNull ??
v2.errorOrNull ??
v3.errorOrNull ??
v4.errorOrNull ??
v5.errorOrNull ??
v6.errorOrNull
));
}
});
@ -259,16 +283,15 @@ extension FutureRecord7<T1, T2, T3, T4, T5, T6, T7> on (
_FutureResult._waitAll([v1, v2, v3, v4, v5, v6, v7], (int errors) {
if (errors == 0) {
c.complete(
(
v1.value,
v2.value,
v3.value,
v4.value,
v5.value,
v6.value,
v7.value
));
c.complete((
v1.value,
v2.value,
v3.value,
v4.value,
v5.value,
v6.value,
v7.value
));
} else {
c.completeError(ParallelWaitError(
(
@ -289,6 +312,14 @@ extension FutureRecord7<T1, T2, T3, T4, T5, T6, T7> on (
v6.errorOrNull,
v7.errorOrNull
),
errorCount: errors,
defaultError: v1.errorOrNull ??
v2.errorOrNull ??
v3.errorOrNull ??
v4.errorOrNull ??
v5.errorOrNull ??
v6.errorOrNull ??
v7.errorOrNull
));
}
});
@ -322,17 +353,16 @@ extension FutureRecord8<T1, T2, T3, T4, T5, T6, T7, T8> on (
_FutureResult._waitAll([v1, v2, v3, v4, v5, v6, v7, v8], (int errors) {
if (errors == 0) {
c.complete(
(
v1.value,
v2.value,
v3.value,
v4.value,
v5.value,
v6.value,
v7.value,
v8.value
));
c.complete((
v1.value,
v2.value,
v3.value,
v4.value,
v5.value,
v6.value,
v7.value,
v8.value
));
} else {
c.completeError(ParallelWaitError(
(
@ -355,6 +385,15 @@ extension FutureRecord8<T1, T2, T3, T4, T5, T6, T7, T8> on (
v7.errorOrNull,
v8.errorOrNull
),
errorCount: errors,
defaultError: v1.errorOrNull ??
v2.errorOrNull ??
v3.errorOrNull ??
v4.errorOrNull ??
v5.errorOrNull ??
v6.errorOrNull ??
v7.errorOrNull ??
v8.errorOrNull
));
}
});
@ -390,18 +429,17 @@ extension FutureRecord9<T1, T2, T3, T4, T5, T6, T7, T8, T9> on (
_FutureResult._waitAll([v1, v2, v3, v4, v5, v6, v7, v8, v9], (int errors) {
if (errors == 0) {
c.complete(
(
v1.value,
v2.value,
v3.value,
v4.value,
v5.value,
v6.value,
v7.value,
v8.value,
v9.value
));
c.complete((
v1.value,
v2.value,
v3.value,
v4.value,
v5.value,
v6.value,
v7.value,
v8.value,
v9.value
));
} else {
c.completeError(ParallelWaitError(
(
@ -426,6 +464,16 @@ extension FutureRecord9<T1, T2, T3, T4, T5, T6, T7, T8, T9> on (
v8.errorOrNull,
v9.errorOrNull
),
errorCount: errors,
defaultError: v1.errorOrNull ??
v2.errorOrNull ??
v3.errorOrNull ??
v4.errorOrNull ??
v5.errorOrNull ??
v6.errorOrNull ??
v7.errorOrNull ??
v8.errorOrNull ??
v9.errorOrNull
));
}
});
@ -464,10 +512,40 @@ class ParallelWaitError<V, E> extends Error {
/// future and `null` values for each successful future.
final E errors;
/// Creates error with the provided [values] and [errors].
ParallelWaitError(this.values, this.errors);
/// An error which, if present, is included in the [toString] output.
///
/// If the default error has a stack trace, it's also reported by the
/// [stackTrace] getter, instead of where this [ParallelWaitError] was thrown.
final AsyncError? _defaultError;
String toString() => "ParallelWaitError";
/// Number of errors, if available.
final int? _errorCount;
/// Creates error with the provided [values] and [errors].
///
/// If [defaultError] is provided, its [AsyncError.error] is used in
/// the [toString] of this parallel error, and its [AsyncError.stackTrace]
/// is returned by [stackTrace].
///
/// If [errorCount] is provided, and it's greater than one,
/// the number is reported in the [toString].
ParallelWaitError(this.values, this.errors,
{int? errorCount, AsyncError? defaultError})
: _defaultError = defaultError,
_errorCount = errorCount;
String toString() {
if (_defaultError == null) {
if (_errorCount == null || _errorCount <= 1) {
return "ParallelWaitError";
}
return "ParallelWaitError($_errorCount errors)";
}
return "ParallelWaitError${_errorCount != null && _errorCount > 1 //
? "($_errorCount errors)" : ""}: ${_defaultError.error}";
}
StackTrace? get stackTrace => _defaultError?.stackTrace ?? super.stackTrace;
}
/// The result of a future, when it has completed.

View File

@ -6,12 +6,14 @@ import "dart:async";
import 'package:async_helper/async_helper.dart';
import "package:expect/expect.dart";
import '../../language/static_type_helper.dart';
void main() async {
asyncStart();
var futures = [for (var i = 0; i < 5; i++) Future<int>.value(i)];
var errors = [for (var i = 0; i < 5; i++) Future<int>.error("e$i")..ignore()];
var errors = [
for (var i = 0; i < 5; i++)
Future<int>.error("error $i", StackTrace.fromString("stack $i"))..ignore()
];
// Empty list.
Expect.listEquals([], await <Future<int>>[].wait);
@ -35,9 +37,14 @@ void main() async {
Expect.isNull(e.errors[0]);
Expect.isNull(e.errors[1]);
Expect.equals("e2", e.errors[2]?.error);
Expect.equals("error 2", e.errors[2]?.error);
Expect.isNull(e.errors[3]);
Expect.isNull(e.errors[4]);
var toString = e.toString();
Expect.contains("ParallelWaitError:", toString);
Expect.contains("error 2", toString);
Expect.equals("stack 2", e.stackTrace.toString());
}
// Multiple errors.
@ -52,10 +59,15 @@ void main() async {
Expect.equals(4, e.values[4]);
Expect.isNull(e.errors[0]);
Expect.equals("e1", e.errors[1]?.error);
Expect.equals("error 1", e.errors[1]?.error);
Expect.isNull(e.errors[2]);
Expect.equals("e3", e.errors[3]?.error);
Expect.equals("error 3", e.errors[3]?.error);
Expect.isNull(e.errors[4]);
var toString = e.toString();
Expect.contains("ParallelWaitError(2 errors):", toString);
Expect.containsOneOf(["error 1", "error 3"], toString);
Expect.containsOneOf(["stack 1", "stack 3"], e.stackTrace.toString());
}
// All errors.
@ -69,11 +81,73 @@ void main() async {
Expect.isNull(e.values[3]);
Expect.isNull(e.values[4]);
Expect.equals("e0", e.errors[0]?.error);
Expect.equals("e1", e.errors[1]?.error);
Expect.equals("e2", e.errors[2]?.error);
Expect.equals("e3", e.errors[3]?.error);
Expect.equals("e4", e.errors[4]?.error);
Expect.equals("error 0", e.errors[0]?.error);
Expect.equals("error 1", e.errors[1]?.error);
Expect.equals("error 2", e.errors[2]?.error);
Expect.equals("error 3", e.errors[3]?.error);
Expect.equals("error 4", e.errors[4]?.error);
var toString = e.toString();
Expect.contains("ParallelWaitError(5 errors):", toString);
Expect.containsOneOf(
["error 0", "error 1", "error 2", "error 3", "error 4"], toString);
Expect.containsOneOf(
["stack 0", "stack 1", "stack 2", "stack 3", "stack 4"],
e.stackTrace.toString());
}
// Direct tests of `ParallelWaitError`.
Expect.equals("ParallelWaitError",
ParallelWaitError<Null, Null>(null, null, errorCount: null).toString());
Expect.equals("ParallelWaitError",
ParallelWaitError<Null, Null>(null, null, errorCount: 0).toString());
Expect.equals("ParallelWaitError",
ParallelWaitError<Null, Null>(null, null, errorCount: 1).toString());
Expect.equals("ParallelWaitError(2 errors)",
ParallelWaitError<Null, Null>(null, null, errorCount: 2).toString());
Expect.equals("ParallelWaitError(9999 errors)",
ParallelWaitError<Null, Null>(null, null, errorCount: 9999).toString());
var defaultError = AsyncError(
StateError("default error"), StackTrace.fromString("default stack"));
final ParallelWaitError unthrownWithoutDefault =
ParallelWaitError<Null, Null>(null, null);
final ParallelWaitError unthrownWithDefault =
ParallelWaitError<Null, Null>(null, null, defaultError: defaultError);
final ParallelWaitError thrownWithoutDefault;
final StackTrace thrownWithoutDefaultStack;
try {
throw ParallelWaitError<Null, Null>(null, null);
} catch (e, s) {
thrownWithoutDefault = e as ParallelWaitError;
thrownWithoutDefaultStack = s;
}
final ParallelWaitError thrownWithDefault;
try {
throw ParallelWaitError<Null, Null>(null, null, defaultError: defaultError);
} catch (e) {
thrownWithDefault = e as ParallelWaitError;
}
Expect.equals("ParallelWaitError", thrownWithoutDefault.toString());
Expect.equals("ParallelWaitError", unthrownWithoutDefault.toString());
Expect.equals(
"ParallelWaitError: ${defaultError.error}", thrownWithDefault.toString());
Expect.equals("ParallelWaitError: ${defaultError.error}",
unthrownWithDefault.toString());
Expect.identical(unthrownWithDefault.stackTrace, defaultError.stackTrace);
Expect.identical(thrownWithDefault.stackTrace, defaultError.stackTrace);
Expect.equals(thrownWithoutDefault.stackTrace.toString(),
thrownWithoutDefaultStack.toString());
Expect.isNull(unthrownWithoutDefault.stackTrace);
// Both default and count.
Expect.equals(
"ParallelWaitError(25 errors): ${defaultError.error}",
ParallelWaitError<Null, Null>(null, null,
errorCount: 25, defaultError: defaultError)
.toString());
asyncEnd();
}

View File

@ -6,17 +6,24 @@ import "dart:async";
import 'package:async_helper/async_helper.dart';
import "package:expect/expect.dart";
import '../../language/static_type_helper.dart';
final fi = Future<int>.value(2);
final fb = Future<bool>.value(true);
final fs = Future<String>.value("s");
final ie = StateError("ie error");
final be = StateError("be error");
final se = StateError("se error");
final stie = StackTrace.fromString("ie stack");
final stbe = StackTrace.fromString("be stack");
final stse = StackTrace.fromString("se stack");
final fie = Future<int>.error(ie, stie)..ignore();
final fbe = Future<bool>.error(be, stbe)..ignore();
final fse = Future<String>.error(se, stse)..ignore();
final fsn = Completer<String>().future; // Never completes.
final errorStackMapping = {ie: stie, be: stbe, se: stse};
void main() async {
asyncStart();
var fi = Future<int>.value(2);
var fb = Future<bool>.value(true);
var fs = Future<String>.value("s");
var fie = Future<int>.error("ie", StackTrace.empty)..ignore();
var fbe = Future<bool>.error("be", StackTrace.empty)..ignore();
var fse = Future<String>.error("se", StackTrace.empty)..ignore();
var fsn = Completer<String>().future; // Never completes.
{
// 2-tuple `wait` getter.
@ -33,7 +40,8 @@ void main() async {
(AsyncError?, AsyncError?)> catch (e, s) {
Expect.equals((2, null), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("be", e.errors.$2?.error);
Expect.equals(be, e.errors.$2?.error);
checkDefaultError(e, 1, [be]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -45,8 +53,9 @@ void main() async {
} on ParallelWaitError<(int?, bool?),
(AsyncError?, AsyncError?)> catch (e, s) {
Expect.equals((null, null), e.values);
Expect.equals("ie", e.errors.$1?.error);
Expect.equals("be", e.errors.$2?.error);
Expect.equals(ie, e.errors.$1?.error);
Expect.equals(be, e.errors.$2?.error);
checkDefaultError(e, 2, [ie, be]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -67,8 +76,9 @@ void main() async {
(AsyncError?, AsyncError?, AsyncError?)> catch (e, s) {
Expect.equals((true, null, 2), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("se", e.errors.$2?.error);
Expect.equals(se, e.errors.$2?.error);
Expect.isNull(e.errors.$3);
checkDefaultError(e, 1, [se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -80,9 +90,10 @@ void main() async {
} on ParallelWaitError<(bool?, String?, int?),
(AsyncError?, AsyncError?, AsyncError?)> catch (e, s) {
Expect.equals((null, null, null), e.values);
Expect.equals("be", e.errors.$1?.error);
Expect.equals("se", e.errors.$2?.error);
Expect.equals("ie", e.errors.$3?.error);
Expect.equals(be, e.errors.$1?.error);
Expect.equals(se, e.errors.$2?.error);
Expect.equals(ie, e.errors.$3?.error);
checkDefaultError(e, 3, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -103,9 +114,10 @@ void main() async {
(AsyncError?, AsyncError?, AsyncError?, AsyncError?)> catch (e, s) {
Expect.equals(("s", null, true, null), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("ie", e.errors.$2?.error);
Expect.equals(ie, e.errors.$2?.error);
Expect.isNull(e.errors.$3);
Expect.equals("se", e.errors.$4?.error);
Expect.equals(se, e.errors.$4?.error);
checkDefaultError(e, 2, [ie, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -117,10 +129,11 @@ void main() async {
} on ParallelWaitError<(String?, int?, bool?, String?),
(AsyncError?, AsyncError?, AsyncError?, AsyncError?)> catch (e, s) {
Expect.equals((null, null, null, null), e.values);
Expect.equals("se", e.errors.$1?.error);
Expect.equals("ie", e.errors.$2?.error);
Expect.equals("be", e.errors.$3?.error);
Expect.equals("se", e.errors.$4?.error);
Expect.equals(se, e.errors.$1?.error);
Expect.equals(ie, e.errors.$2?.error);
Expect.equals(be, e.errors.$3?.error);
Expect.equals(se, e.errors.$4?.error);
checkDefaultError(e, 4, [se, ie, be]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -148,10 +161,11 @@ void main() async {
)> catch (e, s) {
Expect.equals((2, null, "s", null, true), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("be", e.errors.$2?.error);
Expect.equals(be, e.errors.$2?.error);
Expect.isNull(e.errors.$3);
Expect.equals("ie", e.errors.$4?.error);
Expect.equals(ie, e.errors.$4?.error);
Expect.isNull(e.errors.$5);
checkDefaultError(e, 2, [ie, be]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -170,11 +184,12 @@ void main() async {
AsyncError?
)> catch (e, s) {
Expect.equals((null, null, null, null, null), e.values);
Expect.equals("ie", e.errors.$1?.error);
Expect.equals("be", e.errors.$2?.error);
Expect.equals("se", e.errors.$3?.error);
Expect.equals("ie", e.errors.$4?.error);
Expect.equals("be", e.errors.$5?.error);
Expect.equals(ie, e.errors.$1?.error);
Expect.equals(be, e.errors.$2?.error);
Expect.equals(se, e.errors.$3?.error);
Expect.equals(ie, e.errors.$4?.error);
Expect.equals(be, e.errors.$5?.error);
checkDefaultError(e, 5, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -203,11 +218,12 @@ void main() async {
)> catch (e, s) {
Expect.equals((true, null, 2, null, "s", null), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("se", e.errors.$2?.error);
Expect.equals(se, e.errors.$2?.error);
Expect.isNull(e.errors.$3);
Expect.equals("be", e.errors.$4?.error);
Expect.equals(be, e.errors.$4?.error);
Expect.isNull(e.errors.$5);
Expect.equals("ie", e.errors.$6?.error);
Expect.equals(ie, e.errors.$6?.error);
checkDefaultError(e, 3, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -227,12 +243,13 @@ void main() async {
AsyncError?
)> catch (e, s) {
Expect.equals((null, null, null, null, null, null), e.values);
Expect.equals("be", e.errors.$1?.error);
Expect.equals("se", e.errors.$2?.error);
Expect.equals("ie", e.errors.$3?.error);
Expect.equals("be", e.errors.$4?.error);
Expect.equals("se", e.errors.$5?.error);
Expect.equals("ie", e.errors.$6?.error);
Expect.equals(be, e.errors.$1?.error);
Expect.equals(se, e.errors.$2?.error);
Expect.equals(ie, e.errors.$3?.error);
Expect.equals(be, e.errors.$4?.error);
Expect.equals(se, e.errors.$5?.error);
Expect.equals(ie, e.errors.$6?.error);
checkDefaultError(e, 6, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -262,12 +279,13 @@ void main() async {
)> catch (e, s) {
Expect.equals(("s", null, true, null, 2, null, "s"), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("ie", e.errors.$2?.error);
Expect.equals(ie, e.errors.$2?.error);
Expect.isNull(e.errors.$3);
Expect.equals("se", e.errors.$4?.error);
Expect.equals(se, e.errors.$4?.error);
Expect.isNull(e.errors.$5);
Expect.equals("be", e.errors.$6?.error);
Expect.equals(be, e.errors.$6?.error);
Expect.isNull(e.errors.$7);
checkDefaultError(e, 3, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -288,13 +306,14 @@ void main() async {
AsyncError?
)> catch (e, s) {
Expect.equals((null, null, null, null, null, null, null), e.values);
Expect.equals("se", e.errors.$1?.error);
Expect.equals("ie", e.errors.$2?.error);
Expect.equals("be", e.errors.$3?.error);
Expect.equals("se", e.errors.$4?.error);
Expect.equals("ie", e.errors.$5?.error);
Expect.equals("be", e.errors.$6?.error);
Expect.equals("se", e.errors.$7?.error);
Expect.equals(se, e.errors.$1?.error);
Expect.equals(ie, e.errors.$2?.error);
Expect.equals(be, e.errors.$3?.error);
Expect.equals(se, e.errors.$4?.error);
Expect.equals(ie, e.errors.$5?.error);
Expect.equals(be, e.errors.$6?.error);
Expect.equals(se, e.errors.$7?.error);
checkDefaultError(e, 7, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -325,13 +344,14 @@ void main() async {
)> catch (e, s) {
Expect.equals((2, null, "s", null, true, null, 2, null), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("be", e.errors.$2?.error);
Expect.equals(be, e.errors.$2?.error);
Expect.isNull(e.errors.$3);
Expect.equals("ie", e.errors.$4?.error);
Expect.equals(ie, e.errors.$4?.error);
Expect.isNull(e.errors.$5);
Expect.equals("se", e.errors.$6?.error);
Expect.equals(se, e.errors.$6?.error);
Expect.isNull(e.errors.$7);
Expect.equals("be", e.errors.$8?.error);
Expect.equals(be, e.errors.$8?.error);
checkDefaultError(e, 4, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -353,14 +373,15 @@ void main() async {
AsyncError?
)> catch (e, s) {
Expect.equals((null, null, null, null, null, null, null, null), e.values);
Expect.equals("ie", e.errors.$1?.error);
Expect.equals("be", e.errors.$2?.error);
Expect.equals("se", e.errors.$3?.error);
Expect.equals("ie", e.errors.$4?.error);
Expect.equals("be", e.errors.$5?.error);
Expect.equals("se", e.errors.$6?.error);
Expect.equals("ie", e.errors.$7?.error);
Expect.equals("be", e.errors.$8?.error);
Expect.equals(ie, e.errors.$1?.error);
Expect.equals(be, e.errors.$2?.error);
Expect.equals(se, e.errors.$3?.error);
Expect.equals(ie, e.errors.$4?.error);
Expect.equals(be, e.errors.$5?.error);
Expect.equals(se, e.errors.$6?.error);
Expect.equals(ie, e.errors.$7?.error);
Expect.equals(be, e.errors.$8?.error);
checkDefaultError(e, 8, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -392,14 +413,15 @@ void main() async {
)> catch (e, s) {
Expect.equals((true, null, 2, null, "s", null, true, null, 2), e.values);
Expect.isNull(e.errors.$1);
Expect.equals("se", e.errors.$2?.error);
Expect.equals(se, e.errors.$2?.error);
Expect.isNull(e.errors.$3);
Expect.equals("be", e.errors.$4?.error);
Expect.equals(be, e.errors.$4?.error);
Expect.isNull(e.errors.$5);
Expect.equals("ie", e.errors.$6?.error);
Expect.equals(ie, e.errors.$6?.error);
Expect.isNull(e.errors.$7);
Expect.equals("se", e.errors.$8?.error);
Expect.equals(se, e.errors.$8?.error);
Expect.isNull(e.errors.$9);
checkDefaultError(e, 4, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -423,15 +445,16 @@ void main() async {
)> catch (e, s) {
Expect.equals(
(null, null, null, null, null, null, null, null, null), e.values);
Expect.equals("be", e.errors.$1?.error);
Expect.equals("se", e.errors.$2?.error);
Expect.equals("ie", e.errors.$3?.error);
Expect.equals("be", e.errors.$4?.error);
Expect.equals("se", e.errors.$5?.error);
Expect.equals("ie", e.errors.$6?.error);
Expect.equals("be", e.errors.$7?.error);
Expect.equals("se", e.errors.$8?.error);
Expect.equals("ie", e.errors.$9?.error);
Expect.equals(be, e.errors.$1?.error);
Expect.equals(se, e.errors.$2?.error);
Expect.equals(ie, e.errors.$3?.error);
Expect.equals(be, e.errors.$4?.error);
Expect.equals(se, e.errors.$5?.error);
Expect.equals(ie, e.errors.$6?.error);
Expect.equals(be, e.errors.$7?.error);
Expect.equals(se, e.errors.$8?.error);
Expect.equals(ie, e.errors.$9?.error);
checkDefaultError(e, 9, [ie, be, se]);
} on Object catch (e) {
Expect.fail("Did not throw expected error: ${e.runtimeType}");
}
@ -439,3 +462,21 @@ void main() async {
asyncEnd();
}
void checkDefaultError(
ParallelWaitError error, int errorCount, List<Object> expectedErrors) {
var toString = error.toString();
if (errorCount > 1) {
Expect.contains("ParallelWaitError($errorCount errors):", toString);
} else {
Expect.contains("ParallelWaitError:", toString);
}
for (var expectedError in expectedErrors) {
if (toString.contains(expectedError.toString())) {
var expectedStack = errorStackMapping[expectedError]!;
Expect.equals(error.stackTrace.toString(), expectedStack.toString());
return;
}
}
Expect.fail("Error toString did not contain one of the expected errors");
}