a2c7cd6c3f
(There are so many subdirectories under language/ that I figure going a letter at a time is easier to review than going a subdirectory at a time and sending out a huge flurry of tiny CLs.) Change-Id: Ie899b93c5a5f502ca67953b722cecb68c5c6d233 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400146 Auto-Submit: Bob Nystrom <rnystrom@google.com> Reviewed-by: Lasse Nielsen <lrn@google.com> Commit-Queue: Lasse Nielsen <lrn@google.com>
160 lines
3.0 KiB
Dart
160 lines
3.0 KiB
Dart
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
|
// for details. 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:expect/legacy/async_minitest.dart'; // ignore: deprecated_member_use
|
|
|
|
import 'utils.dart';
|
|
|
|
class NotAStream {
|
|
listen(oData, {onError, onDone, cancelOnError}) {
|
|
fail('Not implementing Stream.');
|
|
}
|
|
}
|
|
|
|
StreamTransformer getErrors = StreamTransformer.fromHandlers(
|
|
handleData: (data, sink) {
|
|
fail('Unexpected value');
|
|
},
|
|
handleError: (e, s, sink) {
|
|
sink.add(e);
|
|
},
|
|
handleDone: (sink) {
|
|
sink.close();
|
|
},
|
|
);
|
|
|
|
// Obscuring identity function.
|
|
id(x) {
|
|
try {
|
|
if (x != null) throw x;
|
|
} catch (e) {
|
|
return e;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
main() {
|
|
test('empty', () {
|
|
f() async* {}
|
|
return f().toList().then((v) {
|
|
expect(v, equals([]));
|
|
});
|
|
});
|
|
|
|
test('single', () {
|
|
f() async* {
|
|
yield 42;
|
|
}
|
|
|
|
return f().toList().then((v) {
|
|
expect(v, equals([42]));
|
|
});
|
|
});
|
|
|
|
test('call delays', () {
|
|
var list = [];
|
|
f() async* {
|
|
list.add(1);
|
|
yield 2;
|
|
}
|
|
|
|
var res = f().forEach(list.add);
|
|
list.add(0);
|
|
return res.whenComplete(() {
|
|
expect(list, equals([0, 1, 2]));
|
|
});
|
|
});
|
|
|
|
test('throws', () {
|
|
f() async* {
|
|
yield 1;
|
|
throw 2;
|
|
}
|
|
|
|
var completer = Completer();
|
|
var list = [];
|
|
f().listen(
|
|
list.add,
|
|
onError: (v) => list.add('$v'),
|
|
onDone: completer.complete,
|
|
);
|
|
return completer.future.whenComplete(() {
|
|
expect(list, equals([1, '2']));
|
|
});
|
|
});
|
|
|
|
test('multiple', () {
|
|
f() async* {
|
|
for (int i = 0; i < 10; i++) {
|
|
yield i;
|
|
}
|
|
}
|
|
|
|
return expectList(f(), List.generate(10, id));
|
|
});
|
|
|
|
test('allows await', () {
|
|
f() async* {
|
|
var x = await Future.value(42);
|
|
yield x;
|
|
x = await Future.value(42);
|
|
}
|
|
|
|
return expectList(f(), [42]);
|
|
});
|
|
|
|
test('allows await in loop', () {
|
|
f() async* {
|
|
for (int i = 0; i < 10; i++) {
|
|
yield await i;
|
|
}
|
|
}
|
|
|
|
return expectList(f(), List.generate(10, id));
|
|
});
|
|
|
|
test('allows yield*', () {
|
|
f() async* {
|
|
yield* Stream.fromIterable([1, 2, 3]);
|
|
}
|
|
|
|
return expectList(f(), [1, 2, 3]);
|
|
});
|
|
|
|
test('allows yield* of async*', () {
|
|
f(n) async* {
|
|
yield n;
|
|
if (n == 0) return;
|
|
yield* f(n - 1);
|
|
yield n;
|
|
}
|
|
|
|
return expectList(f(3), [3, 2, 1, 0, 1, 2, 3]);
|
|
});
|
|
|
|
test('Cannot yield* non-stream', () {
|
|
f(dynamic s) async* {
|
|
yield* s;
|
|
}
|
|
|
|
return f(42).transform(getErrors).single.then((v) {
|
|
// Not implementing Stream.
|
|
expect(v is Error, isTrue);
|
|
});
|
|
});
|
|
|
|
test('Cannot yield* non-stream 2', () {
|
|
f(dynamic s) async* {
|
|
yield* s;
|
|
}
|
|
|
|
return f(NotAStream()).transform(getErrors).single.then((v) {
|
|
// Not implementing Stream.
|
|
expect(v is Error, isTrue);
|
|
});
|
|
});
|
|
}
|