Index: tests/lib_strong/async/event_helper.dart |
diff --git a/tests/lib_strong/async/event_helper.dart b/tests/lib_strong/async/event_helper.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a13bac0a37ac5ffc67ba93a8076ffd8d0adc2ed6 |
--- /dev/null |
+++ b/tests/lib_strong/async/event_helper.dart |
@@ -0,0 +1,182 @@ |
+// Copyright (c) 2012, 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 event_helper; |
+ |
+import 'dart:async'; |
+ |
+abstract class Event { |
+ void replay(EventSink sink); |
+} |
+ |
+class DataEvent implements Event { |
+ final data; |
+ |
+ DataEvent(this.data); |
+ |
+ void replay(EventSink sink) { sink.add(data); } |
+ |
+ int get hashCode => data.hashCode; |
+ |
+ bool operator==(Object other) { |
+ if (other is! DataEvent) return false; |
+ DataEvent otherEvent = other; |
+ return data == otherEvent.data; |
+ } |
+ |
+ String toString() => "DataEvent: $data"; |
+} |
+ |
+class ErrorEvent implements Event { |
+ final error; |
+ |
+ ErrorEvent(this.error); |
+ |
+ void replay(EventSink sink) { sink.addError(error); } |
+ |
+ int get hashCode => error.error.hashCode; |
+ |
+ bool operator==(Object other) { |
+ if (other is! ErrorEvent) return false; |
+ ErrorEvent otherEvent = other; |
+ return error == otherEvent.error; |
+ } |
+ |
+ String toString() => "ErrorEvent: ${error}"; |
+} |
+ |
+class DoneEvent implements Event { |
+ const DoneEvent(); |
+ |
+ void replay(EventSink sink) { sink.close(); } |
+ |
+ int get hashCode => 42; |
+ |
+ bool operator==(Object other) => other is DoneEvent; |
+ |
+ String toString() => "DoneEvent"; |
+} |
+ |
+/** Collector of events. */ |
+class Events implements EventSink { |
+ final List<Event> events = []; |
+ bool trace = false; |
+ Completer onDoneSignal = new Completer(); |
+ |
+ Events(); |
+ |
+ Events.fromIterable(Iterable iterable) { |
+ for (var value in iterable) add(value); |
+ close(); |
+ } |
+ |
+ /** Capture events from a stream into a new [Events] object. */ |
+ factory Events.capture(Stream stream, |
+ { bool cancelOnError }) = CaptureEvents; |
+ |
+ // EventSink interface. |
+ void add(var value) { |
+ if (trace) print("Events#$hashCode: add($value)"); |
+ events.add(new DataEvent(value)); |
+ } |
+ |
+ void addError(error, [StackTrace stackTrace]) { |
+ if (trace) print("Events#$hashCode: addError($error)"); |
+ events.add(new ErrorEvent(error)); |
+ } |
+ |
+ void close() { |
+ if (trace) print("Events#$hashCode: close()"); |
+ events.add(const DoneEvent()); |
+ onDoneSignal.complete(); |
+ } |
+ |
+ /** |
+ * Error shorthand, for writing events manually. |
+ */ |
+ void error(var value, [StackTrace stackTrace]) { |
+ addError(value, stackTrace); |
+ } |
+ |
+ /** Replay the captured events on a sink. */ |
+ void replay(EventSink sink) { |
+ for (int i = 0; i < events.length; i++) { |
+ events[i].replay(sink); |
+ } |
+ } |
+ |
+ /** |
+ * Create a new [Events] with the same captured events. |
+ * |
+ * This does not copy a subscription. |
+ */ |
+ Events copy() { |
+ Events result = new Events(); |
+ replay(result); |
+ return result; |
+ } |
+ |
+ // Operations that only work when there is a subscription feeding the Events. |
+ |
+ /** |
+ * Pauses the subscription that feeds this [Events]. |
+ * |
+ * Should only be used when there is a subscription. That is, after a |
+ * call to [subscribeTo]. |
+ */ |
+ void pause([Future resumeSignal]) { |
+ throw new StateError("Not capturing events."); |
+ } |
+ |
+ /** Resumes after a call to [pause]. */ |
+ void resume() { |
+ throw new StateError("Not capturing events."); |
+ } |
+ |
+ /** |
+ * Sets an action to be called when this [Events] receives a 'done' event. |
+ * |
+ * The action will also be called if capturing events from a stream with |
+ * `cancelOnError` set to true and receiving an error. |
+ */ |
+ void onDone(void action()) { |
+ onDoneSignal.future.whenComplete(action); |
+ } |
+} |
+ |
+class CaptureEvents extends Events { |
+ StreamSubscription subscription; |
+ bool cancelOnError = false; |
+ |
+ CaptureEvents(Stream stream, |
+ { bool cancelOnError: false }) { |
+ this.cancelOnError = cancelOnError; |
+ subscription = stream.listen(add, |
+ onError: addError, |
+ onDone: close, |
+ cancelOnError: cancelOnError); |
+ } |
+ |
+ void addError(error, [stackTrace]) { |
+ super.addError(error, stackTrace); |
+ if (cancelOnError) { |
+ onDoneSignal.complete(); |
+ } |
+ } |
+ |
+ void pause([Future resumeSignal]) { |
+ if (trace) print("Events#$hashCode: pause"); |
+ subscription.pause(resumeSignal); |
+ } |
+ |
+ void resume() { |
+ if (trace) print("Events#$hashCode: resume"); |
+ subscription.resume(); |
+ } |
+ |
+ void onDone(void action()) { |
+ if (trace) print("Events#$hashCode: onDone"); |
+ super.onDone(action); |
+ } |
+} |