d3904f5a54
Change-Id: I6ccbe1494165c2bda142ece13584c4738e3b43e6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425347 Commit-Queue: Lasse Nielsen <lrn@google.com> Reviewed-by: Lasse Nielsen <lrn@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com>
180 lines
4.9 KiB
Dart
180 lines
4.9 KiB
Dart
// Copyright (c) 2015, 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.
|
|
|
|
// Test empty stream.
|
|
import "package:expect/expect.dart";
|
|
import "dart:async";
|
|
import 'package:expect/async_helper.dart';
|
|
|
|
main() async {
|
|
await asyncTest(() async {
|
|
// Is a `const` constructor.
|
|
// Can be called with optional boolean to say whether broadcast or not.
|
|
await asyncTest(() => emptyTest(const Stream<int>.empty(), true));
|
|
await asyncTest(
|
|
() => emptyTest(const Stream<int>.empty(broadcast: true), true),
|
|
);
|
|
await asyncTest(
|
|
() => emptyTest(const Stream<int>.empty(broadcast: false), false),
|
|
);
|
|
|
|
// Check that the behavior is consistent with other empty multi-subscription
|
|
// streams.
|
|
await asyncTest(() => emptyTest(Stream<int>.fromIterable(<int>[]), false));
|
|
await asyncTest(
|
|
() =>
|
|
emptyTest((StreamController<int>.broadcast()..close()).stream, true),
|
|
);
|
|
await asyncTest(
|
|
() => emptyTest(Stream<int>.multi((c) => c.close()), false),
|
|
);
|
|
});
|
|
await flushMicrotasks();
|
|
}
|
|
|
|
// Function which fails the test if it gets called.
|
|
void unreachable([a, b]) {
|
|
Expect.fail("Unreachable");
|
|
}
|
|
|
|
/// Check that something happens once.
|
|
class Checker {
|
|
bool checked = false;
|
|
void check() {
|
|
if (checked) Expect.fail("Checked more than once");
|
|
checked = true;
|
|
}
|
|
}
|
|
|
|
Future<void> emptyTest(Stream<int> s, bool broadcast) async {
|
|
var checker = Checker();
|
|
// Respects type parameter (not a `Stream<Never>`)
|
|
Expect.notType<Stream<String>>(s);
|
|
|
|
// Has the expected `isBroadcast`.
|
|
Expect.equals(broadcast, s.isBroadcast);
|
|
|
|
StreamSubscription<int> sub = s.listen(
|
|
unreachable,
|
|
onError: unreachable,
|
|
onDone: checker.check,
|
|
);
|
|
// Type parameter of subscription respects stream.
|
|
// Not a `StreamSubscription<Never>`.
|
|
Expect.isFalse(sub is StreamSubscription<String>);
|
|
|
|
Expect.isFalse(sub.isPaused);
|
|
// Doesn't do callback immediately in response to listen.
|
|
Expect.isFalse(checker.checked);
|
|
await flushMicrotasks();
|
|
// Completes eventually, after a microtask.
|
|
Expect.isTrue(checker.checked);
|
|
Expect.isFalse(sub.isPaused);
|
|
|
|
// Can listen more than once, whether broadcast stream or not.
|
|
checker = Checker();
|
|
StreamSubscription<int> sub2 = s.listen(
|
|
unreachable,
|
|
onError: unreachable,
|
|
onDone: checker.check,
|
|
);
|
|
// Respects pauses.
|
|
sub2.pause();
|
|
Expect.isTrue(sub2.isPaused);
|
|
sub2.pause();
|
|
Expect.isTrue(sub2.isPaused);
|
|
sub2.pause(Future<int>.value(0));
|
|
Expect.isTrue(sub2.isPaused);
|
|
|
|
await flushMicrotasks();
|
|
Expect.isTrue(sub2.isPaused);
|
|
Expect.isFalse(checker.checked);
|
|
|
|
// Resumes when all pauses resumed.
|
|
sub2.resume();
|
|
Expect.isTrue(sub2.isPaused);
|
|
await flushMicrotasks();
|
|
Expect.isFalse(checker.checked);
|
|
Expect.isTrue(sub2.isPaused);
|
|
|
|
sub2.resume();
|
|
Expect.isFalse(sub2.isPaused);
|
|
await flushMicrotasks();
|
|
Expect.isTrue(checker.checked);
|
|
Expect.isFalse(sub2.isPaused);
|
|
|
|
// Can't pause after done.
|
|
sub2.pause(Future<int>.value(0));
|
|
Expect.isFalse(sub2.isPaused);
|
|
sub2.pause();
|
|
Expect.isFalse(sub2.isPaused);
|
|
|
|
// Respects cancel.
|
|
var sub3 = s.listen(unreachable, onError: unreachable, onDone: unreachable);
|
|
sub3.cancel();
|
|
sub3.onDone(unreachable);
|
|
Expect.isFalse(sub3.isPaused);
|
|
await flushMicrotasks();
|
|
Expect.isFalse(sub3.isPaused);
|
|
|
|
// Can't pause after cancel
|
|
sub3.pause();
|
|
Expect.isFalse(sub3.isPaused);
|
|
sub3.pause(Future<int>.value(0));
|
|
Expect.isFalse(sub3.isPaused);
|
|
// No errors.
|
|
|
|
// Respects cancel while paused.
|
|
var sub4 = s.listen(unreachable, onError: unreachable, onDone: unreachable);
|
|
sub4.pause();
|
|
sub4.cancel();
|
|
sub4.onDone(unreachable);
|
|
await flushMicrotasks();
|
|
sub4.resume();
|
|
await flushMicrotasks();
|
|
|
|
// Check that the stream is zone-aware.
|
|
// Registers onDone callback.
|
|
var log = [];
|
|
late final Zone zone;
|
|
|
|
void callback1() {
|
|
// Run in correct zone.
|
|
Expect.equals(zone, Zone.current);
|
|
log.add("don1");
|
|
}
|
|
|
|
void callback2() {
|
|
// Run in correct zone.
|
|
Expect.equals(zone, Zone.current);
|
|
log.add("don2");
|
|
}
|
|
|
|
zone = Zone.current.fork(
|
|
specification: ZoneSpecification(
|
|
registerCallback: <R>(s, p, z, f) {
|
|
if (f == callback1) log.add("reg1");
|
|
if (f == callback2) log.add("reg2");
|
|
return p.registerCallback<R>(z, f);
|
|
},
|
|
run: <R>(s, p, z, f) {
|
|
if (f == callback1) log.add("run1");
|
|
if (f == callback2) log.add("run2");
|
|
return p.run<R>(z, f);
|
|
},
|
|
),
|
|
);
|
|
|
|
await zone.run(() async {
|
|
var s = Stream<int>.empty();
|
|
|
|
var sub = s.listen(unreachable, onError: unreachable, onDone: callback1);
|
|
sub.onDone(callback2);
|
|
});
|
|
await flushMicrotasks();
|
|
Expect.listEquals(["reg1", "reg2", "run2", "don2"], log);
|
|
}
|
|
|
|
Future flushMicrotasks() => new Future.delayed(Duration.zero);
|