em-zmq-tp10 0.1.7

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.
data/tests/test_req.rb ADDED
@@ -0,0 +1,229 @@
1
+ require 'eventmachine'
2
+ require 'minitest/autorun'
3
+ require File.expand_path('../helper.rb', __FILE__)
4
+
5
+ require 'em/protocols/zmq2/req'
6
+
7
+ describe 'Req' do
8
+ let(:connected) do
9
+ EM::DefaultDeferrable.new
10
+ end
11
+
12
+ describe EM::Protocols::Zmq2::PreReq do
13
+ class MyPreReq < EM::Protocols::Zmq2::PreReq
14
+ attr :incoming_queue
15
+ def initialize(opts={})
16
+ super
17
+ @connected = opts[:connected]
18
+ @incoming_queue = []
19
+ end
20
+ def peer_free(peer_identity, connection)
21
+ super
22
+ @connected.succeed
23
+ end
24
+ def receive_reply(message, data, request_id)
25
+ message.first.must_equal 'world'
26
+ message.last.must_equal data.to_s
27
+ @incoming_queue << ['hello', message.last]
28
+ end
29
+ end
30
+
31
+ attr :req
32
+ before do
33
+ @req = MyPreReq.new(identity: 'REQ', connected: connected)
34
+ @req.connect(Native::ZBIND_ADDR)
35
+ end
36
+
37
+ let(:messages){
38
+ 300.times.map{|i| ['hello', i.to_s]} << ['hello', 'xxx']
39
+ }
40
+
41
+ it 'should send requests' do
42
+ Native.with_socket('REP') do |zrep|
43
+ thrd = Thread.new do
44
+ messages.size.times do
45
+ ar = []
46
+ zrep.recv_strings ar
47
+ ar[0] = 'world'
48
+ zrep.send_strings ar
49
+ end
50
+ end
51
+ EM.run {
52
+ connected.callback {
53
+ dup = messages.dup
54
+ cb = lambda {
55
+ if dup.empty?
56
+ EM.add_timer(0.3){
57
+ EM.next_tick{ EM.stop }
58
+ }
59
+ else
60
+ message = dup.first
61
+ if String === req.send_request(message, message.last)
62
+ dup.shift
63
+ EM.next_tick cb
64
+ else
65
+ EM.add_timer 0.1, cb
66
+ end
67
+ end
68
+ }
69
+ cb.call
70
+ }
71
+ }
72
+ thrd.join
73
+ end
74
+ (req.incoming_queue - messages).must_be_empty
75
+ (messages - req.incoming_queue).must_be_empty
76
+ end
77
+ end
78
+
79
+ describe EM::Protocols::Zmq2::Req do
80
+ class MyReq < EM::Protocols::Zmq2::Req
81
+ attr :incoming_queue, :canceled_requests
82
+ def initialize(opts={}, defered_conn, defered_mess)
83
+ super opts
84
+ @defered_conn = defered_conn
85
+ @defered_mess = defered_mess
86
+ @incoming_queue = []
87
+ @canceled_requests = []
88
+ end
89
+ def peer_free(peer_identity, connection)
90
+ super
91
+ @defered_conn.succeed
92
+ end
93
+ def receive_reply(message, data, request_id)
94
+ message.first.must_equal 'world'
95
+ message.last.must_equal data.to_s
96
+ @incoming_queue << ['hello', message.last]
97
+ @defered_mess.succeed if message.last == 'xxx'
98
+ end
99
+ def cancel_request(request_id)
100
+ @canceled_requests << request_id
101
+ end
102
+ end
103
+
104
+ let(:finished){ EM::DefaultDeferrable.new }
105
+ attr :req
106
+ before do
107
+ @req = MyReq.new({identity: 'REQ'}, connected, finished)
108
+ @req.connect(Native::ZBIND_ADDR)
109
+ end
110
+ let(:messages){
111
+ 5000.times.map{|i| ['hello', i.to_s]} << ['hello', 'xxx']
112
+ }
113
+
114
+ it 'should send a lot of requests' do
115
+ Native.with_socket('REP') do |zrep|
116
+ thrd = Thread.new do
117
+ messages.size.times do
118
+ ar = []
119
+ zrep.recv_strings ar
120
+ ar[0] = 'world'
121
+ zrep.send_strings ar
122
+ end
123
+ end
124
+ EM.run {
125
+ connected.callback {
126
+ messages.each{|message|
127
+ req.send_request(message, message.last)
128
+ }
129
+ }
130
+ finished.callback {
131
+ EM.next_tick{ EM.stop }
132
+ }
133
+ }
134
+ thrd.join
135
+ end
136
+ (req.incoming_queue - messages).must_be_empty
137
+ (messages - req.incoming_queue).must_be_empty
138
+ end
139
+
140
+ it "should not accept message on low hwm with strategy :drop_last" do
141
+ req.hwm = 2
142
+ req.hwm_strategy = :drop_last
143
+ EM.run {
144
+ req.send_request(['hi', 'ho1'], nil).must_be_kind_of String
145
+ req.send_request(['hi', 'ho2'], nil).must_be_kind_of String
146
+ req.send_request(['hi', 'ho3'], nil).wont_be_kind_of String
147
+ EM.stop
148
+ }
149
+ end
150
+
151
+ it "should cancel earlier message on low hwm with strategy :drop_first" do
152
+ req.hwm = 2
153
+ req.hwm_strategy = :drop_first
154
+ first_req = nil
155
+ EM.run {
156
+ first_req = req.send_request(['hi', 'ho1'], nil)
157
+ first_req.must_be_kind_of String
158
+ req.send_request(['hi', 'ho2'], nil).must_be_kind_of String
159
+ req.send_request(['hi', 'ho3'], nil).must_be_kind_of String
160
+ EM.stop
161
+ }
162
+ req.canceled_requests.must_equal [first_req]
163
+ end
164
+ end
165
+
166
+ describe EM::Protocols::Zmq2::ReqDefer do
167
+ class TSTRep < EM::Protocols::Zmq2::Rep
168
+ include DeferredMixin
169
+ def receive_request(message, environment)
170
+ send_reply([message.first, 'yeah'], environment)
171
+ end
172
+ def peer_free(peer, conn)
173
+ super
174
+ @connected.succeed
175
+ end
176
+ end
177
+ it "should correctly setup and call deferrable" do
178
+ req = EM::Protocols::Zmq2::ReqDefer.new
179
+ def req.send_message(message, even = false)
180
+ res = super
181
+ res
182
+ end
183
+ rep = TSTRep.new(connected: connected)
184
+ rep.bind('inproc://tst')
185
+ first_success, first_error = nil, nil
186
+ second_success, second_error = nil, nil
187
+ require 'pp'
188
+ EM.run {
189
+ uniq = Object.new.freeze
190
+ first = nil
191
+ follow = proc do |null, data|
192
+ data.must_equal uniq
193
+ null.must_be_nil
194
+ req.connect('inproc://tst')
195
+ connected.callback do
196
+ stop = proc{ EM.next_tick{ EM.stop } }
197
+ second = req.send_request(['hi', 'ho'], uniq) do |reply, data|
198
+ second_success = true
199
+ reply.must_equal ['hi', 'yeah']
200
+ data.must_equal uniq
201
+ end
202
+ second.must_be_kind_of EM::Deferrable
203
+ second.errback do
204
+ second_error = true
205
+ end
206
+ second.callback &stop
207
+ second.errback &stop
208
+ end
209
+ end
210
+ first = req.send_request(['hi', 'ho'], uniq) do |reply, data|
211
+ first_success = true
212
+ reply.must_equal ['hi', 'yeah']
213
+ data.must_equal uniq
214
+ end
215
+ first.must_be_kind_of EM::Deferrable
216
+ first.timeout(0.3, 1, uniq)
217
+ first.errback do
218
+ first_error = true
219
+ end
220
+ first.callback &follow
221
+ first.errback &follow
222
+ }
223
+ first_success.must_equal nil
224
+ first_error.must_equal true
225
+ second_success.must_equal true
226
+ second_error.must_equal nil
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,221 @@
1
+ require 'eventmachine'
2
+ require 'minitest/autorun'
3
+ require File.expand_path('../helper.rb', __FILE__)
4
+
5
+ require 'em/protocols/zmq2/router'
6
+
7
+ describe 'Router' do
8
+
9
+ let(:connected) do
10
+ EM::DefaultDeferrable.new
11
+ end
12
+
13
+ let(:finished) do
14
+ EM::DefaultDeferrable.new
15
+ end
16
+
17
+ class DealerCollector
18
+ attr :res_a, :res_b
19
+ def initialize(till)
20
+ @till = till
21
+ @res_a, @res_b = [], []
22
+ end
23
+ def full?
24
+ @res_a.size + @res_b.size >= @till
25
+ end
26
+ def full_res
27
+ @res_a + @res_b
28
+ end
29
+ def set_sockets(zbind, zconnect)
30
+ @zbind = zbind
31
+ @zconnect = zconnect
32
+ end
33
+ def thread
34
+ Thread.new do
35
+ begin
36
+ result = []
37
+ until full?
38
+ while @zbind.recv_strings(result, ZMQ::NOBLOCK) != -1
39
+ result.first.must_equal 'hello'
40
+ @res_a << result
41
+ result = []
42
+ end
43
+ while @zconnect.recv_strings(result, ZMQ::NOBLOCK) != -1
44
+ result.first.must_equal 'hello'
45
+ @res_b << result
46
+ result = []
47
+ end
48
+ sleep(0.01)
49
+ end
50
+ rescue
51
+ puts $!
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe EM::Protocols::Zmq2::PreRouter do
58
+ class MyPreRouter < EM::Protocols::Zmq2::PreRouter
59
+ attr :incoming_queue
60
+ def initialize(connected, finished, opts={})
61
+ super opts
62
+ @connected = connected
63
+ @finished = finished
64
+ @incoming_queue = {}
65
+ end
66
+ def peer_free(peer_ident, connection)
67
+ super
68
+ @connected.succeed if @free_peers.size == 2
69
+ end
70
+ def receive_message(message)
71
+ (@incoming_queue[message.first] ||= []) << message[1..-1]
72
+ @finished.succeed if message.last == 'xxx'
73
+ end
74
+ end
75
+
76
+ attr :router
77
+ before do
78
+ @router = MyPreRouter.new(connected, finished, identity: 'MyRouter')
79
+ @router.bind(Native::ZCONNECT_ADDR)
80
+ @router.connect(Native::ZBIND_ADDR)
81
+ end
82
+
83
+ let(:messages) do
84
+ 62.times.map{|n| ['hello', n.to_s] } << ['hello', 'xxx']
85
+ end
86
+
87
+ it "should be able to receive messages" do
88
+ halves = messages[0...(messages.size/2)], messages[(messages.size/2)..-1]
89
+ Native.with_socket_pair('DEALER') do |zbind, zconnect|
90
+ EM.run {
91
+ connected.callback do
92
+ halves[0].each do |message|
93
+ zbind.send_strings(message)
94
+ end
95
+ halves[1].each do |message|
96
+ zconnect.send_strings(message)
97
+ end
98
+ end
99
+ finished.callback do
100
+ EM.next_tick{ EM.stop }
101
+ end
102
+ }
103
+ end
104
+ router.incoming_queue['BIND_DEALER'].must_equal halves[0]
105
+ router.incoming_queue['CONNECT_DEALER'].must_equal halves[1]
106
+ end
107
+
108
+ it "should be able to route messages" do
109
+ collector = DealerCollector.new(messages.size)
110
+ halves = messages[0...(messages.size/2)], messages[(messages.size/2)..-1]
111
+ Native.with_socket_pair('DEALER') do |zbind, zconnect|
112
+ collector.set_sockets zbind, zconnect
113
+ thrd = collector.thread
114
+ EM.run {
115
+ dup_halves = halves.map(&:dup)
116
+ connected.callback do
117
+ dup_halves[0].each do |message|
118
+ router.send_message(['BIND_DEALER', *message]).must_equal true
119
+ end
120
+ dup_halves[1].each do |message|
121
+ router.send_message(['CONNECT_DEALER', *message]).must_equal true
122
+ end
123
+ EM.defer(proc do thrd.join end, proc do
124
+ EM.next_tick{ EM.stop }
125
+ end)
126
+ end
127
+ }
128
+ end
129
+ collector.res_a.must_equal halves[0]
130
+ collector.res_b.must_equal halves[1]
131
+ end
132
+ end
133
+
134
+ describe EM::Protocols::Zmq2::Router do
135
+ class MyRouter < EM::Protocols::Zmq2::Router
136
+ attr :incoming_queue, :canceled_messages
137
+ def initialize(connected, finished, opts={})
138
+ super opts
139
+ @connected = connected
140
+ @finished = finished
141
+ @incoming_queue = {}
142
+ @canceled_messages = []
143
+ end
144
+ def peer_free(peer_ident, connection)
145
+ super
146
+ @connected.succeed if @free_peers.size == 2
147
+ end
148
+ def receive_message(message)
149
+ (@incoming_queue[message.first] ||= []) << message[1..-1]
150
+ @finished.succeed if message.last == 'xxx'
151
+ end
152
+ def cancel_message(message)
153
+ @canceled_messages << message
154
+ end
155
+ end
156
+
157
+ attr :router
158
+ before do
159
+ @router = MyRouter.new(connected, finished, identity: 'MyRouter')
160
+ @router.bind(Native::ZCONNECT_ADDR)
161
+ @router.connect(Native::ZBIND_ADDR)
162
+ end
163
+
164
+ let(:messages) do
165
+ 10000.times.map{|n| ['hello', n.to_s] } << ['hello', 'xxx']
166
+ end
167
+
168
+ it "should be able to route a lot of messages" do
169
+ collector = DealerCollector.new(messages.size)
170
+ halves = messages[0...(messages.size/2)], messages[(messages.size/2)..-1]
171
+ Native.with_socket_pair('DEALER') do |zbind, zconnect|
172
+ collector.set_sockets zbind, zconnect
173
+ thrd = collector.thread
174
+ EM.run {
175
+ dup_halves = halves.map(&:dup)
176
+ connected.callback do
177
+ dup_halves[0].each do |message|
178
+ router.send_message(['BIND_DEALER', *message])
179
+ end
180
+ dup_halves[1].each do |message|
181
+ router.send_message(['CONNECT_DEALER', *message])
182
+ end
183
+ EM.defer(proc do thrd.join end, proc do
184
+ EM.next_tick{ EM.stop }
185
+ end)
186
+ end
187
+ }
188
+ thrd.join
189
+ end
190
+ collector.res_a.must_equal halves[0]
191
+ collector.res_b.must_equal halves[1]
192
+ end
193
+
194
+ it "should not accept message on low hwm with strategy :drop_last" do
195
+ router.hwm = 1
196
+ router.hwm_strategy = :drop_last
197
+ EM.run {
198
+ router.send_message(['FIRST_PEER', 'hi', 'ho1']).must_equal true
199
+ router.send_message(['FIRST_PEER', 'hi', 'ho2']).wont_equal true
200
+ router.send_message(['SECOND_PEER', 'hi', 'ho1']).must_equal true
201
+ router.send_message(['SECOND_PEER', 'hi', 'ho2']).wont_equal true
202
+ EM.stop
203
+ }
204
+ end
205
+
206
+ it "should cancel earlier message on low hwm with strategy :drop_first" do
207
+ router.hwm = 1
208
+ router.hwm_strategy = :drop_first
209
+ EM.run {
210
+ router.send_message(['FIRST_PEER', 'hi', 'ho1']).must_equal true
211
+ router.send_message(['FIRST_PEER', 'hi', 'ho2']).must_equal true
212
+ router.send_message(['SECOND_PEER', 'hi', 'ho1']).must_equal true
213
+ router.send_message(['SECOND_PEER', 'hi', 'ho2']).must_equal true
214
+ EM.stop
215
+ }
216
+ router.canceled_messages.count.must_equal 2
217
+ router.canceled_messages.must_include ['FIRST_PEER', 'hi', 'ho1']
218
+ router.canceled_messages.must_include ['SECOND_PEER', 'hi', 'ho1']
219
+ end
220
+ end
221
+ end