root/trunk/tests/test_futures.rb

Revision 668, 5.2 kB (checked in by blackhedd, 1 year ago)

migrated version_0 to trunk

  • Property svn:keywords set to Id
Line 
1 # $Id$
2 #
3 # Author:: Francis Cianfrocca (gmail: blackhedd)
4 # Homepage::  http://rubyeventmachine.com
5 # Date:: 8 April 2006
6 #
7 # See EventMachine and EventMachine::Connection for documentation and
8 # usage examples.
9 #
10 #----------------------------------------------------------------------------
11 #
12 # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13 # Gmail: blackhedd
14 #
15 # This program is free software; you can redistribute it and/or modify
16 # it under the terms of either: 1) the GNU General Public License
17 # as published by the Free Software Foundation; either version 2 of the
18 # License, or (at your option) any later version; or 2) Ruby's License.
19 #
20 # See the file COPYING for complete licensing information.
21 #
22 #---------------------------------------------------------------------------
23 #
24 #
25 #
26
27 $:.unshift "../lib"
28 require 'eventmachine'
29 require 'test/unit'
30
31
32
33 class TestFutures < Test::Unit::TestCase
34
35   def setup
36   end
37
38   def teardown
39   end
40
41   def test_future
42       assert_equal(100, EventMachine::Deferrable.future(100) )
43
44       p1 = proc { 100 + 1 }
45       assert_equal(101, EventMachine::Deferrable.future(p1) )
46   end
47
48
49
50   class MyFuture
51       include EventMachine::Deferrable
52       def initialize *args
53           super
54           set_deferred_status :succeeded, 40
55       end
56   end
57
58   class MyErrorFuture
59       include EventMachine::Deferrable
60       def initialize *args
61           super
62           set_deferred_status :failed, 41
63       end
64   end
65
66
67   def test_future_1
68       # Call future with one additional argument and it will be treated as a callback.
69       def my_future
70           MyFuture.new
71       end
72
73       value = nil
74       EventMachine::Deferrable.future my_future, proc {|v| value=v}
75       assert_equal( 40, value )
76   end
77
78
79   def test_future_2
80       # Call future with two additional arguments and they will be treated as a callback
81       # and an errback.
82       value = nil
83       EventMachine::Deferrable.future MyErrorFuture.new, nil, proc {|v| value=v}
84       assert_equal( 41, value )
85   end
86
87
88   def test_future_3
89       # Call future with no additional arguments but with a block, and the block will be
90       # treated as a callback.
91       value = nil
92       EventMachine::Deferrable.future MyFuture.new do |v|
93           value=v
94       end
95       assert_equal( 40, value )
96   end
97
98
99   class RecursiveCallback
100       include EventMachine::Deferrable
101   end
102
103   # A Deferrable callback can call #set_deferred_status to change the values
104   # passed to subsequent callbacks.
105   #
106   def test_recursive_callbacks
107       n = 0 # counter assures that all the tests actually run.
108       rc = RecursiveCallback.new
109       rc.callback {|a|
110           assert_equal(100, a)
111           n += 1
112           rc.set_deferred_status :succeeded, 101, 101
113       }
114       rc.callback {|a,b|
115           assert_equal(101, a)
116           assert_equal(101, b)
117           n += 1
118           rc.set_deferred_status :succeeded, 102, 102, 102
119       }
120       rc.callback {|a,b,c|
121           assert_equal(102, a)
122           assert_equal(102, b)
123           assert_equal(102, c)
124           n += 1
125       }
126       rc.set_deferred_status :succeeded, 100
127       assert_equal(3, n)
128   end
129
130
131
132         def test_syntactic_sugar
133                 rc = RecursiveCallback.new
134                 rc.set_deferred_success 100
135                 rc.set_deferred_failure 200
136         end
137
138
139
140         # It doesn't raise an error to set deferred status more than once.
141         # In fact, this is a desired and useful idiom when it happens INSIDE
142         # a callback or errback.
143         # However, it's less useful otherwise, and in fact would generally be
144         # indicative of a programming error. However, we would like to be resistant
145         # to such errors. So whenever we set deferred status, we also clear BOTH
146         # stacks of handlers.
147         #
148         def test_double_calls
149                 s = 0
150                 e = 0
151
152                 d = EM::DefaultDeferrable.new
153                 d.callback {s += 1}
154                 d.errback {e += 1}
155
156                 d.succeed       # We expect the callback to be called, and the errback to be DISCARDED.
157                 d.fail  # Presumably an error. We expect the errback NOT to be called.
158                 d.succeed       # We expect the callback to have been discarded and NOT to be called again.
159
160                 assert_equal(1, s)
161                 assert_equal(0, e)
162         end
163
164
165         # Adding a callback to a Deferrable that is already in a success state executes the callback
166         # immediately. The same applies to a an errback added to an already-failed Deferrable.
167         # HOWEVER, we expect NOT to be able to add errbacks to succeeded Deferrables, or callbacks
168         # to failed ones.
169         #
170         # We illustrate this with a rather contrived test. The test calls #fail after #succeed,
171         # which ordinarily would not happen in a real program.
172         #
173         # What we're NOT attempting to specify is what happens if a Deferrable is succeeded and then
174         # failed (or vice-versa). Should we then be able to add callbacks/errbacks of the appropriate
175         # type for immediate execution? For now at least, the official answer is "don't do that."
176         #
177         def test_delayed_callbacks
178                 s1 = 0
179                 s2 = 0
180                 e = 0
181
182                 d = EM::DefaultDeferrable.new
183                 d.callback {s1 += 1}
184
185                 d.succeed       # Triggers and discards the callback.
186
187                 d.callback {s2 += 1}    # This callback is executed immediately and discarded.
188
189                 d.errback {e += 1}      # This errback should be DISCARDED and never execute.
190                 d.fail          # To prove it, let's
191
192                 assert_equal( [1,1], [s1,s2] )
193                 assert_equal( 0, e )
194         end
195
196
197
198
199         #
200         #
201         #
202         def test_timeout
203                 n = 0
204                 EM.run {
205                         d = EM::DefaultDeferrable.new
206                         d.callback {n = 1; EM.stop}
207                         d.errback {n = 2; EM.stop}
208                         d.timeout(1)
209                 }
210                 assert_equal( 2, n )
211         end
212
213 end
214
Note: See TracBrowser for help on using the browser.