rx_ruby 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +22 -0
  3. data/.gitignore +173 -0
  4. data/.travis.yml +10 -0
  5. data/Gemfile +4 -0
  6. data/Rakefile +11 -0
  7. data/examples/aggregate.rb +39 -0
  8. data/examples/amb.rb +25 -0
  9. data/examples/ambproto.rb +24 -0
  10. data/examples/and.rb +26 -0
  11. data/examples/as_observable.rb +25 -0
  12. data/examples/average.rb +43 -0
  13. data/examples/buffer_with_count.rb +44 -0
  14. data/examples/buffer_with_time.rb +51 -0
  15. data/examples/case.rb +29 -0
  16. data/examples/catch.rb +20 -0
  17. data/examples/catchproto.rb +39 -0
  18. data/examples/combine_latest.rb +35 -0
  19. data/examples/combine_latestproto.rb +33 -0
  20. data/examples/concat.rb +22 -0
  21. data/examples/concat_all.rb +27 -0
  22. data/examples/concat_map.rb +61 -0
  23. data/examples/concat_map_observer.rb +29 -0
  24. data/examples/concatproto.rb +25 -0
  25. data/examples/connect.rb +41 -0
  26. data/examples/contains.rb +37 -0
  27. data/examples/count.rb +36 -0
  28. data/examples/create.rb +55 -0
  29. data/examples/debounce.rb +35 -0
  30. data/examples/default_if_empty.rb +35 -0
  31. data/examples/defer.rb +20 -0
  32. data/examples/delay.rb +49 -0
  33. data/examples/delay_with_selector.rb +63 -0
  34. data/examples/dematerialize.rb +22 -0
  35. data/examples/disposable.rb +12 -0
  36. data/examples/distinct.rb +43 -0
  37. data/examples/distinct_until_changed.rb +43 -0
  38. data/examples/do.rb +59 -0
  39. data/examples/empty.rb +16 -0
  40. data/examples/for.rb +26 -0
  41. data/examples/fork_join.rb +23 -0
  42. data/examples/from.rb +106 -0
  43. data/examples/from_array.rb +21 -0
  44. data/examples/from_callback.rb +21 -0
  45. data/examples/generate.rb +24 -0
  46. data/examples/group_join.rb +39 -0
  47. data/examples/if.rb +46 -0
  48. data/examples/intervals.rb +26 -0
  49. data/examples/merge.rb +36 -0
  50. data/examples/merge_all.rb +27 -0
  51. data/examples/multicast.rb +32 -0
  52. data/examples/never.rb +15 -0
  53. data/examples/of.rb +19 -0
  54. data/examples/on_error_resume_next.rb +21 -0
  55. data/examples/pairs.rb +26 -0
  56. data/examples/publish.rb +79 -0
  57. data/examples/range.rb +19 -0
  58. data/examples/reduce.rb +18 -0
  59. data/examples/repeat.rb +19 -0
  60. data/examples/return.rb +17 -0
  61. data/examples/scan.rb +41 -0
  62. data/examples/start.rb +29 -0
  63. data/examples/throw.rb +17 -0
  64. data/examples/time_intervals.rb +28 -0
  65. data/examples/timer.rb +26 -0
  66. data/examples/timestamp.rb +28 -0
  67. data/examples/to_a.rb +23 -0
  68. data/examples/to_async.rb +26 -0
  69. data/examples/using.rb +52 -0
  70. data/examples/when.rb +26 -0
  71. data/examples/while.rb +25 -0
  72. data/examples/window_with_time.rb +78 -0
  73. data/examples/zip.rb +27 -0
  74. data/examples/zip_array.rb +25 -0
  75. data/lib/core_ext/enumerable.rb +22 -0
  76. data/lib/rx_ruby.rb +27 -0
  77. data/lib/rx_ruby/concurrency/async_lock.rb +57 -0
  78. data/lib/rx_ruby/concurrency/current_thread_scheduler.rb +75 -0
  79. data/lib/rx_ruby/concurrency/default_scheduler.rb +51 -0
  80. data/lib/rx_ruby/concurrency/historical_scheduler.rb +16 -0
  81. data/lib/rx_ruby/concurrency/immediate_scheduler.rb +68 -0
  82. data/lib/rx_ruby/concurrency/local_scheduler.rb +39 -0
  83. data/lib/rx_ruby/concurrency/periodic_scheduler.rb +74 -0
  84. data/lib/rx_ruby/concurrency/scheduled_item.rb +42 -0
  85. data/lib/rx_ruby/concurrency/scheduler.rb +150 -0
  86. data/lib/rx_ruby/concurrency/virtual_time_scheduler.rb +170 -0
  87. data/lib/rx_ruby/core/async_lock_observer.rb +46 -0
  88. data/lib/rx_ruby/core/auto_detach_observer.rb +59 -0
  89. data/lib/rx_ruby/core/checked_observer.rb +66 -0
  90. data/lib/rx_ruby/core/notification.rb +161 -0
  91. data/lib/rx_ruby/core/observable.rb +104 -0
  92. data/lib/rx_ruby/core/observe_on_observer.rb +50 -0
  93. data/lib/rx_ruby/core/observer.rb +119 -0
  94. data/lib/rx_ruby/core/scheduled_observer.rb +83 -0
  95. data/lib/rx_ruby/core/synchronized_observer.rb +47 -0
  96. data/lib/rx_ruby/core/time_interval.rb +17 -0
  97. data/lib/rx_ruby/internal/priority_queue.rb +122 -0
  98. data/lib/rx_ruby/internal/util.rb +9 -0
  99. data/lib/rx_ruby/joins/active_plan.rb +45 -0
  100. data/lib/rx_ruby/joins/join_observer.rb +51 -0
  101. data/lib/rx_ruby/joins/pattern.rb +14 -0
  102. data/lib/rx_ruby/joins/plan.rb +44 -0
  103. data/lib/rx_ruby/linq/connectable_observable.rb +34 -0
  104. data/lib/rx_ruby/linq/observable/_observable_timer_date_and_period.rb +22 -0
  105. data/lib/rx_ruby/linq/observable/_observable_timer_time_span.rb +14 -0
  106. data/lib/rx_ruby/linq/observable/_observable_timer_time_span_and_period.rb +20 -0
  107. data/lib/rx_ruby/linq/observable/aggregate.rb +7 -0
  108. data/lib/rx_ruby/linq/observable/and.rb +7 -0
  109. data/lib/rx_ruby/linq/observable/case.rb +15 -0
  110. data/lib/rx_ruby/linq/observable/concat_all.rb +7 -0
  111. data/lib/rx_ruby/linq/observable/concat_map.rb +35 -0
  112. data/lib/rx_ruby/linq/observable/concat_map_observer.rb +43 -0
  113. data/lib/rx_ruby/linq/observable/contains.rb +28 -0
  114. data/lib/rx_ruby/linq/observable/debounce.rb +41 -0
  115. data/lib/rx_ruby/linq/observable/delay.rb +81 -0
  116. data/lib/rx_ruby/linq/observable/delay_with_selector.rb +64 -0
  117. data/lib/rx_ruby/linq/observable/do.rb +42 -0
  118. data/lib/rx_ruby/linq/observable/for.rb +13 -0
  119. data/lib/rx_ruby/linq/observable/fork_join.rb +55 -0
  120. data/lib/rx_ruby/linq/observable/from.rb +34 -0
  121. data/lib/rx_ruby/linq/observable/group_join.rb +108 -0
  122. data/lib/rx_ruby/linq/observable/if.rb +17 -0
  123. data/lib/rx_ruby/linq/observable/interval.rb +5 -0
  124. data/lib/rx_ruby/linq/observable/multicast.rb +14 -0
  125. data/lib/rx_ruby/linq/observable/of.rb +11 -0
  126. data/lib/rx_ruby/linq/observable/pairs.rb +7 -0
  127. data/lib/rx_ruby/linq/observable/pluck.rb +7 -0
  128. data/lib/rx_ruby/linq/observable/publish.rb +11 -0
  129. data/lib/rx_ruby/linq/observable/start.rb +7 -0
  130. data/lib/rx_ruby/linq/observable/time_interval.rb +15 -0
  131. data/lib/rx_ruby/linq/observable/timer.rb +26 -0
  132. data/lib/rx_ruby/linq/observable/timestamp.rb +9 -0
  133. data/lib/rx_ruby/linq/observable/to_async.rb +40 -0
  134. data/lib/rx_ruby/linq/observable/when.rb +36 -0
  135. data/lib/rx_ruby/linq/observable/while.rb +41 -0
  136. data/lib/rx_ruby/operators/aggregates.rb +611 -0
  137. data/lib/rx_ruby/operators/creation.rb +220 -0
  138. data/lib/rx_ruby/operators/multiple.rb +735 -0
  139. data/lib/rx_ruby/operators/single.rb +399 -0
  140. data/lib/rx_ruby/operators/standard_query_operators.rb +279 -0
  141. data/lib/rx_ruby/operators/synchronization.rb +47 -0
  142. data/lib/rx_ruby/operators/time.rb +120 -0
  143. data/lib/rx_ruby/subjects/async_subject.rb +161 -0
  144. data/lib/rx_ruby/subjects/behavior_subject.rb +149 -0
  145. data/lib/rx_ruby/subjects/replay_subject.rb +39 -0
  146. data/lib/rx_ruby/subjects/subject.rb +131 -0
  147. data/lib/rx_ruby/subjects/subject_extensions.rb +45 -0
  148. data/lib/rx_ruby/subscriptions/composite_subscription.rb +91 -0
  149. data/lib/rx_ruby/subscriptions/ref_count_subscription.rb +88 -0
  150. data/lib/rx_ruby/subscriptions/scheduled_subscription.rb +32 -0
  151. data/lib/rx_ruby/subscriptions/serial_subscription.rb +60 -0
  152. data/lib/rx_ruby/subscriptions/single_assignment_subscription.rb +64 -0
  153. data/lib/rx_ruby/subscriptions/subscription.rb +56 -0
  154. data/lib/rx_ruby/testing/cold_observable.rb +45 -0
  155. data/lib/rx_ruby/testing/hot_observable.rb +47 -0
  156. data/lib/rx_ruby/testing/mock_observer.rb +33 -0
  157. data/lib/rx_ruby/testing/reactive_test.rb +94 -0
  158. data/lib/rx_ruby/testing/recorded.rb +17 -0
  159. data/lib/rx_ruby/testing/test_scheduler.rb +96 -0
  160. data/lib/rx_ruby/testing/test_subscription.rb +22 -0
  161. data/lib/rx_ruby/version.rb +3 -0
  162. data/license.txt +13 -0
  163. data/readme.md +152 -0
  164. data/rx_ruby.gemspec +22 -0
  165. data/test/rx_ruby/concurrency/helpers/historical_virtual_scheduler_helper.rb +135 -0
  166. data/test/rx_ruby/concurrency/helpers/immediate_local_scheduler_helper.rb +51 -0
  167. data/test/rx_ruby/concurrency/test_async_lock.rb +56 -0
  168. data/test/rx_ruby/concurrency/test_current_thread_scheduler.rb +44 -0
  169. data/test/rx_ruby/concurrency/test_default_scheduler.rb +44 -0
  170. data/test/rx_ruby/concurrency/test_historical_scheduler.rb +18 -0
  171. data/test/rx_ruby/concurrency/test_immediate_scheduler.rb +53 -0
  172. data/test/rx_ruby/concurrency/test_local_scheduler.rb +12 -0
  173. data/test/rx_ruby/concurrency/test_periodic_scheduler.rb +53 -0
  174. data/test/rx_ruby/concurrency/test_scheduled_item.rb +50 -0
  175. data/test/rx_ruby/concurrency/test_scheduler.rb +128 -0
  176. data/test/rx_ruby/concurrency/test_virtual_time_scheduler.rb +14 -0
  177. data/test/rx_ruby/core/test_notification.rb +129 -0
  178. data/test/rx_ruby/core/test_observable_creation.rb +483 -0
  179. data/test/rx_ruby/core/test_observer.rb +634 -0
  180. data/test/rx_ruby/internal/test_priority_queue.rb +71 -0
  181. data/test/rx_ruby/subscriptions/test_composite_subscription.rb +116 -0
  182. data/test/rx_ruby/subscriptions/test_serial_subscription.rb +62 -0
  183. data/test/rx_ruby/subscriptions/test_singleassignment_subscription.rb +61 -0
  184. data/test/rx_ruby/subscriptions/test_subscription.rb +27 -0
  185. data/test/test_helper.rb +11 -0
  186. metadata +291 -0
@@ -0,0 +1,64 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'thread'
4
+
5
+ module RxRuby
6
+
7
+ # Represents a subscription resource which only allows a single assignment of its underlying subscription resource.
8
+ # If an underlying subscription resource has already been set, future attempts to set the underlying subscription resource will throw an error
9
+ class SingleAssignmentSubscription
10
+
11
+ def initialize
12
+ @gate = Mutex.new()
13
+ @current = nil
14
+ @unsubscribed = false
15
+ @set = false
16
+ end
17
+
18
+ # Gets a value that indicates whether the object is unsubscribed.
19
+ def unsubscribed?
20
+ @gate.synchronize do
21
+ return @unsubscribed
22
+ end
23
+ end
24
+
25
+ # Gets the underlying subscription. After unsubscribing, the result of getting this property is undefined.
26
+ def subscription
27
+ @current
28
+ end
29
+
30
+ # Sets the underlying disposable. If this has already been set, then an error is raised.
31
+ def subscription=(new_subscription)
32
+ raise 'Subscription already set' if @set
33
+
34
+ @set = true
35
+ should_unsubscribe = false
36
+ old = nil
37
+ @gate.synchronize do
38
+ should_unsubscribe = @unsubscribed
39
+ unless should_unsubscribe
40
+ old = @current
41
+ @current = new_subscription
42
+ end
43
+ end
44
+
45
+ old.unsubscribe if old
46
+ new_subscription.unsubscribe if should_unsubscribe && !new_subscription.nil?
47
+ end
48
+
49
+ # Unsubscribes the underlying subscription
50
+ def unsubscribe
51
+ old = nil
52
+ @gate.synchronize do
53
+ unless @unsubscribed
54
+ @unsubscribed = true
55
+ old = @current
56
+ @current = nil
57
+ end
58
+ end
59
+
60
+ old.unsubscribe if old
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,56 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'thread'
4
+ require 'singleton'
5
+
6
+ module RxRuby
7
+ module Subscription
8
+ def dispose
9
+ unsubscribe
10
+ end
11
+ end
12
+ Disposable = Subscription
13
+
14
+ class EmptySubscription
15
+
16
+ include Subscription
17
+ include Singleton
18
+
19
+ def unsubscribe
20
+
21
+ end
22
+ end
23
+
24
+ class AnonymousSubscription
25
+ include Subscription
26
+
27
+ def initialize(&unsubscribe_action)
28
+ @unsubscribe_action = unsubscribe_action
29
+ @gate = Mutex.new
30
+ @unsubscribed = false
31
+ end
32
+
33
+ def unsubscribe
34
+ should_unsubscribe = false
35
+ @gate.synchronize do
36
+ should_unsubscribe = !@unsubscribed
37
+ end
38
+
39
+ @unsubscribe_action.call if should_unsubscribe
40
+ end
41
+ end
42
+
43
+ # Provides a set of class methods for creating Disposables.
44
+ module Subscription
45
+
46
+ # Creates a subscription object that invokes the specified action when unsubscribed.
47
+ def self.create(&unsubscribe_action)
48
+ AnonymousSubscription.new(&unsubscribe_action)
49
+ end
50
+
51
+ # Gets the subscription that does nothing when unsubscribed.
52
+ def self.empty
53
+ EmptySubscription.instance
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,45 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'rx_ruby/subscriptions/subscription'
4
+ require 'rx_ruby/subscriptions/composite_subscription'
5
+ require 'rx_ruby/testing/test_subscription'
6
+
7
+ module RxRuby
8
+
9
+ class ColdObservable
10
+
11
+ attr_reader :messages, :subscriptions
12
+
13
+ def initialize(scheduler, *args)
14
+ raise 'scheduler cannot be nil' unless scheduler
15
+
16
+ @scheduler = scheduler
17
+ @messages = args
18
+ @subscriptions = []
19
+ end
20
+
21
+ def subscribe(observer)
22
+ raise 'observer cannot be nil' unless observer
23
+
24
+ subscriptions.push(TestSubscription.new @scheduler.clock)
25
+ index = subscriptions.length - 1
26
+
27
+ d = CompositeSubscription.new
28
+
29
+ messages.each do |message|
30
+ notification = message.value
31
+
32
+ d.push(@scheduler.schedule_at_relative_with_state(nil, message.time, lambda {|scheduler1, state1|
33
+ notification.accept observer
34
+ Subscription.empty
35
+ }))
36
+ end
37
+
38
+ return Subscription.create do
39
+ subscriptions[index] = TestSubscription.new(subscriptions[index].subscribe, @scheduler.clock)
40
+ d.unsubscribe
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'rx_ruby/core/observable'
4
+ require 'rx_ruby/subscriptions/subscription'
5
+ require 'rx_ruby/testing/test_subscription'
6
+
7
+ module RxRuby
8
+
9
+ class HotObservable
10
+ include Observable
11
+
12
+ attr_reader :messages, :subscriptions
13
+
14
+ def initialize(scheduler, *args)
15
+ raise 'scheduler cannot be nil' unless scheduler
16
+
17
+ @scheduler = scheduler
18
+ @messages = args
19
+ @subscriptions = []
20
+ @observers = []
21
+
22
+ @messages.each do |message|
23
+ notification = message.value
24
+ @scheduler.schedule_at_relative_with_state(nil, message.time, lambda {|scheduler1, state1|
25
+
26
+ @observers.clone.each {|observer| notification.accept observer }
27
+
28
+ Subscription.empty
29
+ })
30
+ end
31
+ end
32
+
33
+ def subscribe(observer)
34
+ raise 'observer cannot be nil' unless observer
35
+
36
+ @observers.push observer
37
+ subscriptions.push (TestSubscription.new @scheduler.clock)
38
+
39
+ index = subscriptions.length - 1
40
+
41
+ Subscription.create do
42
+ @observers.delete observer
43
+ subscriptions[index] = TestSubscription.new(subscriptions[index].subscribe, @scheduler.clock)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'rx_ruby/core/observer'
4
+ require 'rx_ruby/core/notification'
5
+ require 'rx_ruby/testing/recorded'
6
+
7
+ module RxRuby
8
+
9
+ class MockObserver
10
+ include Observer
11
+
12
+ attr_reader :messages
13
+
14
+ def initialize(scheduler)
15
+ raise 'scheduler cannot be nil' unless scheduler
16
+
17
+ @scheduler = scheduler
18
+ @messages = []
19
+ end
20
+
21
+ def on_next(value)
22
+ messages.push(Recorded.new(@scheduler.clock, Notification.create_on_next(value)))
23
+ end
24
+
25
+ def on_error(error)
26
+ messages.push(Recorded.new(@scheduler.clock, Notification.create_on_error(error)))
27
+ end
28
+
29
+ def on_completed
30
+ messages.push(Recorded.new(@scheduler.clock, Notification.create_on_completed))
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,94 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'rx_ruby/core/notification'
4
+ require 'rx_ruby/testing/recorded'
5
+
6
+ module RxRuby
7
+
8
+ # Module to write unit tests for applications and libraries built using Reactive Extensions.
9
+ module ReactiveTest
10
+
11
+ # Default virtual time used for creation of observable sequences in ReactiveTest-based unit tests.
12
+ CREATED = 100
13
+
14
+ # Default virtual time used to subscribe to observable sequences in ReactiveTest-based unit tests.
15
+ SUBSCRIBED = 200
16
+
17
+ # Default virtual time used to dispose subscriptions in ReactiveTest-based unit tests.
18
+ DISPOSED = 1000
19
+
20
+ # Factory method for an on_next notification record at a given time with a given value.
21
+ def on_next(ticks, value)
22
+ Recorded.new(ticks, Notification.create_on_next(value))
23
+ end
24
+
25
+ # Factory method for writing an assert that checks for an on_next notification record at a given time, using the specified predicate to check the value.
26
+ def on_next_predicate(ticks, &block)
27
+ n = OnNextPredicate.new(&block)
28
+ Recorded.new(ticks, n)
29
+ end
30
+
31
+ # Factory method for an on_error notification record at a given time with a given error.
32
+ def on_error(ticks, error)
33
+ Recorded.new(ticks, Notification.create_on_error(error))
34
+ end
35
+
36
+ # Factory method for writing an assert that checks for an on_error notification record at a given time, using the specified predicate to check the exception.
37
+ def on_error_predicate(ticks, &block)
38
+ n = OnErrorPredicate.new(&block)
39
+ Recorded.new(ticks, n)
40
+ end
41
+
42
+ # Factory method for an OnCompleted notification record at a given time.
43
+ def on_completed(ticks)
44
+ Recorded.new(ticks, Notification.create_on_completed)
45
+ end
46
+
47
+ # Factory method for a subscription record based on a given subscription and unsubscribe time.
48
+ def subscribe(subscribe, unsubscribe)
49
+ TestSubscription.new(subscribe, unsubscribe)
50
+ end
51
+
52
+ def assert_messages(expected, actual)
53
+ assert_equal expected.length, actual.length, "The size of messages differ"
54
+
55
+ for i in 0..expected.length - 1
56
+ assert_equal expected[i].time, actual[i].time, "The messages[#{i}].time differ"
57
+ assert_equal expected[i].value, actual[i].value, "The messages[#{i}].value differ"
58
+ end
59
+ end
60
+
61
+ def assert_subscriptions(expected, actual)
62
+ assert_equal expected.length, actual.length
63
+
64
+ for i in 0..expected.length - 1
65
+ assert (expected[i] == actual[i])
66
+ end
67
+ end
68
+
69
+ class OnNextPredicate
70
+
71
+ def initialize(&action)
72
+ @action = action
73
+ end
74
+
75
+ def ==(other)
76
+ other && other.on_next? && @action.call(other.value)
77
+ end
78
+ alias_method :eql?, :==
79
+ end
80
+
81
+ class OnErrorPredicate
82
+
83
+ def initialize(&action)
84
+ @action = action
85
+ end
86
+
87
+ def ==(other)
88
+ other && other.on_error? && @action.call(other.error)
89
+ end
90
+ alias_method :eql?, :==
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,17 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ module RxRuby
4
+
5
+ # Record of a value including the virtual time it was produced on.
6
+ class Recorded < Struct.new(:time, :value)
7
+
8
+ def initialize(time, value)
9
+ super
10
+ end
11
+
12
+ def to_s
13
+ "#{value} @ #{time}"
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,96 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'rx_ruby/concurrency/virtual_time_scheduler'
4
+ require 'rx_ruby/subscriptions/subscription'
5
+ require 'rx_ruby/testing/cold_observable'
6
+ require 'rx_ruby/testing/hot_observable'
7
+ require 'rx_ruby/testing/mock_observer'
8
+ require 'rx_ruby/testing/reactive_test'
9
+
10
+ module RxRuby
11
+
12
+ # Virtual time scheduler used for testing applications and libraries built using Reactive Extensions.
13
+ class TestScheduler < VirtualTimeScheduler
14
+
15
+ def initialize
16
+ super(0)
17
+ end
18
+
19
+ # Schedules an action to be executed at due_time.
20
+ def schedule_at_absolute_with_state(state, due_time, action)
21
+ raise 'action cannot be nil' unless action
22
+
23
+ due_time = clock + 1 if due_time <= clock
24
+
25
+ super(state, due_time, action)
26
+ end
27
+
28
+ # Adds a relative virtual time to an absolute virtual time value.
29
+ def add(absolute, relative)
30
+ absolute + relative
31
+ end
32
+
33
+ # Converts the absolute time value to a Time value.
34
+ def to_time(absolute)
35
+ Time.at absolute
36
+ end
37
+
38
+ # Converts the time span value to a relative time value.
39
+ def to_relative(time_span)
40
+ time_span
41
+ end
42
+
43
+ # Starts the test scheduler and uses the specified virtual times to invoke the factory function, subscribe to the resulting sequence, and unsubscribe the subscription.
44
+ def configure(options = {})
45
+ options.each {|key,_|
46
+ unless [:created, :subscribed, :disposed].include? key
47
+ raise ArgumentError, "Should be spcified whether :created, :subscribed or :disposed, but the #{key.inspect}"
48
+ end
49
+ }
50
+ o = {
51
+ :created => ReactiveTest::CREATED,
52
+ :subscribed => ReactiveTest::SUBSCRIBED,
53
+ :disposed => ReactiveTest::DISPOSED
54
+ }.merge(options)
55
+
56
+ source = nil
57
+ subscription = nil
58
+ observer = create_observer
59
+
60
+ schedule_at_absolute_with_state(nil, o[:created], lambda {|scheduler, state|
61
+ source = yield
62
+ Subscription.empty
63
+ })
64
+
65
+ schedule_at_absolute_with_state(nil, o[:subscribed], lambda {|scheduler, state|
66
+ subscription = source.subscribe observer
67
+ Subscription.empty
68
+ })
69
+
70
+ schedule_at_absolute_with_state(nil, o[:disposed], lambda {|scheduler, state|
71
+ subscription.unsubscribe
72
+ Subscription.empty
73
+ })
74
+
75
+ start
76
+
77
+ observer
78
+ end
79
+
80
+ # Creates a hot observable using the specified timestamped notification messages.
81
+ def create_hot_observable(*args)
82
+ HotObservable.new(self, *args)
83
+ end
84
+
85
+ # Creates a cold observable using the specified timestamped notification messages.
86
+ def create_cold_observable(*args)
87
+ ColdObservable.new(self, *args)
88
+ end
89
+
90
+ # Creates an observer that records received notification messages and timestamps those.
91
+ def create_observer
92
+ MockObserver.new self
93
+ end
94
+
95
+ end
96
+ end