Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(599)

Unified Diff: pkg/scheduled_test/test/scheduled_stream/scheduled_stream_test.dart

Issue 119673002: Add a ScheduledStream class and some stream matchers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/scheduled_test/test/scheduled_stream/scheduled_stream_test.dart
diff --git a/pkg/scheduled_test/test/scheduled_stream/scheduled_stream_test.dart b/pkg/scheduled_test/test/scheduled_stream/scheduled_stream_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..92dc027c84353e787501498ee6a22bb0b0ee7891
--- /dev/null
+++ b/pkg/scheduled_test/test/scheduled_stream/scheduled_stream_test.dart
@@ -0,0 +1,396 @@
+// Copyright (c) 2013, 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.
+
+library scheduled_test.scheduled_stream_test;
+
+import 'dart:async';
+
+import 'package:scheduled_test/scheduled_stream.dart';
+import 'package:unittest/unittest.dart';
+import 'package:scheduled_test/src/utils.dart';
+
+void main() {
+ group("a completed stream with no elements", () {
+ var stream;
+ setUp(() {
+ var controller = new StreamController()..close();
+ stream = new ScheduledStream(controller.stream);
+
+ // Wait for [stream] to register the wrapped stream's close event.
+ return pumpEventQueue();
+ });
+
+ test("throws an error for [next]", () {
+ expect(stream.next(), throwsStateError);
+ });
+
+ test("returns false for [hasNext]", () {
+ expect(stream.hasNext, completion(isFalse));
+ });
+
+ test("emittedValues is empty", () {
+ expect(stream.emittedValues, isEmpty);
+ });
+
+ test("allValues is empty", () {
+ expect(stream.allValues, isEmpty);
+ });
+
+ test("close() does nothing", () {
+ // This just shouldn't throw any exceptions.
+ stream.close();
+ });
+
+ test("fork() returns a closed stream", () {
+ var fork = stream.fork();
+ expect(fork.emittedValues, isEmpty);
+ expect(fork.allValues, isEmpty);
+ expect(fork.next(), throwsStateError);
+ expect(fork.hasNext, completion(isFalse));
+ });
+ });
+
+ group("a stream that completes later with no elements", () {
+ var controller;
+ var stream;
+ setUp(() {
+ controller = new StreamController();
+ stream = new ScheduledStream(controller.stream);
+ });
+
+ test("throws an error for [next]", () {
+ expect(stream.next(), throwsStateError);
+ return new Future(controller.close);
+ });
+
+ test("returns false for [hasNext]", () {
+ expect(stream.hasNext, completion(isFalse));
+ return new Future(controller.close);
+ });
+
+ test("emittedValues is empty", () {
+ expect(stream.emittedValues, isEmpty);
+ });
+
+ test("allValues is empty", () {
+ expect(stream.allValues, isEmpty);
+ });
+
+ test("fork() returns a stream that closes when the controller is closed",
+ () {
+ var fork = stream.fork();
+ expect(fork.emittedValues, isEmpty);
+ expect(fork.allValues, isEmpty);
+
+ var nextComplete = false;
+ expect(fork.next().whenComplete(() {
+ nextComplete = true;
+ }), throwsStateError);
+
+ var hasNextComplete = false;
+ expect(fork.hasNext.whenComplete(() {
+ hasNextComplete = true;
+ }), completion(isFalse));
+
+ // Pump the event queue to give [next] and [hasNext] a chance to
+ // (incorrectly) fire.
+ return pumpEventQueue().then((_) {
+ expect(nextComplete, isFalse);
+ expect(hasNextComplete, isFalse);
+
+ controller.close();
+ });
+ });
+ });
+
+ test("forking and then closing a stream closes the fork", () {
+ var stream = new ScheduledStream(new StreamController().stream);
+ var fork = stream.fork();
+ expect(fork.emittedValues, isEmpty);
+ expect(fork.allValues, isEmpty);
+
+ var nextComplete = false;
+ expect(fork.next().whenComplete(() {
+ nextComplete = true;
+ }), throwsStateError);
+
+ var hasNextComplete = false;
+ expect(fork.hasNext.whenComplete(() {
+ hasNextComplete = true;
+ }), completion(isFalse));
+
+ // Pump the event queue to give [next] and [hasNext] a chance to
+ // (incorrectly) fire.
+ return pumpEventQueue().then((_) {
+ expect(nextComplete, isFalse);
+ expect(hasNextComplete, isFalse);
+
+ stream.close();
+ });
+ });
+
+ group("a completed stream with several values", () {
+ var stream;
+ setUp(() {
+ var controller = new StreamController<int>()
+ ..add(1)..add(2)..add(3)..close();
+ stream = new ScheduledStream<int>(controller.stream);
+
+ return pumpEventQueue();
+ });
+
+ test("next() returns each value then throws an error", () {
+ return stream.next().then((value) {
+ expect(value, equals(1));
+ return stream.next();
+ }).then((value) {
+ expect(value, equals(2));
+ return stream.next();
+ }).then((value) {
+ expect(value, equals(3));
+ expect(stream.next(), throwsStateError);
+ });
+ });
+
+ test("parallel next() calls are disallowed", () {
+ expect(stream.next(), completion(equals(1)));
+ expect(stream.next(), throwsStateError);
+ });
+
+ test("parallel hasNext calls are allowed", () {
+ expect(stream.hasNext, completion(isTrue));
+ expect(stream.hasNext, completion(isTrue));
+ });
+
+ test("hasNext returns true until there are no more values", () {
+ return stream.hasNext.then((hasNext) {
+ expect(hasNext, isTrue);
+ return stream.next();
+ }).then((_) => stream.hasNext).then((hasNext) {
+ expect(hasNext, isTrue);
+ return stream.next();
+ }).then((_) => stream.hasNext).then((hasNext) {
+ expect(hasNext, isTrue);
+ return stream.next();
+ }).then((_) => expect(stream.hasNext, completion(isFalse)));
+ });
+
+ test("emittedValues returns the values that have been emitted", () {
+ expect(stream.emittedValues, isEmpty);
+
+ return stream.next().then((_) {
+ expect(stream.emittedValues, equals([1]));
+ return stream.next();
+ }).then((_) {
+ expect(stream.emittedValues, equals([1, 2]));
+ return stream.next();
+ }).then((_) {
+ expect(stream.emittedValues, equals([1, 2, 3]));
+ });
+ });
+
+ test("allValues returns all values that the inner stream emitted", () {
+ expect(stream.allValues, equals([1, 2, 3]));
+ });
+
+ test("closing the stream means it doesn't emit additional events", () {
+ return stream.next().then((_) {
+ stream.close();
+ expect(stream.next(), throwsStateError);
+ });
+ });
+
+ test("a fork created before any values are emitted emits all values", () {
+ var fork = stream.fork();
+ return fork.next().then((value) {
+ expect(value, equals(1));
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(2));
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(3));
+ expect(fork.next(), throwsStateError);
+ });
+ });
+
+ test("a fork created after some values are emitted emits remaining values",
+ () {
+ var fork;
+ return stream.next().then((_) {
+ fork = stream.fork();
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(2));
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(3));
+ expect(fork.next(), throwsStateError);
+ });
+ });
+
+ test("a fork doesn't push forward its parent stream", () {
+ var fork = stream.fork();
+ return fork.next().then((_) {
+ expect(stream.next(), completion(equals(1)));
+ });
+ });
+
+ test("closing a fork doesn't close its parent stream", () {
+ var fork = stream.fork();
+ fork.close();
+ expect(stream.next(), completion(equals(1)));
+ });
+
+ test("closing a stream closes its forks immediately", () {
+ var fork = stream.fork();
+ return stream.next().then((_) {
+ stream.close();
+ expect(fork.next(), throwsStateError);
+ });
+ });
+ });
+
+ group("a stream with several values added asynchronously", () {
+ var stream;
+ setUp(() {
+ var controller = new StreamController<int>();
+ stream = new ScheduledStream<int>(controller.stream);
+
+ pumpEventQueue().then((_) {
+ controller.add(1);
+ return pumpEventQueue();
+ }).then((_) {
+ controller.add(2);
+ return pumpEventQueue();
+ }).then((_) {
+ controller.add(3);
+ return pumpEventQueue();
+ }).then((_) {
+ controller.close();
+ });
+ });
+
+ test("next() returns each value then throws an error", () {
+ return stream.next().then((value) {
+ expect(value, equals(1));
+ return stream.next();
+ }).then((value) {
+ expect(value, equals(2));
+ return stream.next();
+ }).then((value) {
+ expect(value, equals(3));
+ expect(stream.next(), throwsStateError);
+ });
+ });
+
+ test("parallel next() calls are disallowed", () {
+ expect(stream.next(), completion(equals(1)));
+ expect(stream.next(), throwsStateError);
+ });
+
+ test("parallel hasNext calls are allowed", () {
+ expect(stream.hasNext, completion(isTrue));
+ expect(stream.hasNext, completion(isTrue));
+ });
+
+ test("hasNext returns true until there are no more values", () {
+ return stream.hasNext.then((hasNext) {
+ expect(hasNext, isTrue);
+ return stream.next();
+ }).then((_) => stream.hasNext).then((hasNext) {
+ expect(hasNext, isTrue);
+ return stream.next();
+ }).then((_) => stream.hasNext).then((hasNext) {
+ expect(hasNext, isTrue);
+ return stream.next();
+ }).then((_) => expect(stream.hasNext, completion(isFalse)));
+ });
+
+ test("emittedValues returns the values that have been emitted", () {
+ expect(stream.emittedValues, isEmpty);
+
+ return stream.next().then((_) {
+ expect(stream.emittedValues, equals([1]));
+ return stream.next();
+ }).then((_) {
+ expect(stream.emittedValues, equals([1, 2]));
+ return stream.next();
+ }).then((_) {
+ expect(stream.emittedValues, equals([1, 2, 3]));
+ });
+ });
+
+ test("allValues returns all values that the inner stream emitted", () {
+ expect(stream.allValues, isEmpty);
+
+ return stream.next().then((_) {
+ expect(stream.allValues, equals([1]));
+ return stream.next();
+ }).then((_) {
+ expect(stream.allValues, equals([1, 2]));
+ return stream.next();
+ }).then((_) {
+ expect(stream.allValues, equals([1, 2, 3]));
+ });
+ });
+
+ test("closing the stream means it doesn't emit additional events", () {
+ return stream.next().then((_) {
+ stream.close();
+ expect(stream.next(), throwsStateError);
+ });
+ });
+
+ test("a fork created before any values are emitted emits all values", () {
+ var fork = stream.fork();
+ return fork.next().then((value) {
+ expect(value, equals(1));
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(2));
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(3));
+ expect(fork.next(), throwsStateError);
+ });
+ });
+
+ test("a fork created after some values are emitted emits remaining values",
+ () {
+ var fork;
+ return stream.next().then((_) {
+ fork = stream.fork();
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(2));
+ return fork.next();
+ }).then((value) {
+ expect(value, equals(3));
+ expect(fork.next(), throwsStateError);
+ });
+ });
+
+ test("a fork doesn't push forward its parent stream", () {
+ var fork = stream.fork();
+ return fork.next().then((_) {
+ expect(stream.next(), completion(equals(1)));
+ });
+ });
+
+ test("closing a fork doesn't close its parent stream", () {
+ var fork = stream.fork();
+ fork.close();
+ expect(stream.next(), completion(equals(1)));
+ });
+
+ test("closing a stream closes its forks immediately", () {
+ var fork = stream.fork();
+ return stream.next().then((_) {
+ stream.close();
+ expect(fork.next(), throwsStateError);
+ });
+ });
+ });
+}

Powered by Google App Engine
This is Rietveld 408576698