em-zmq-tp10 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,271 @@
1
+ require 'eventmachine'
2
+ require 'minitest/autorun'
3
+ require File.expand_path('../helper.rb', __FILE__)
4
+
5
+ require 'em/protocols/zmq2/pub_sub'
6
+
7
+ describe 'Sub' do
8
+ let(:connected) do
9
+ EM::DefaultDeferrable.new
10
+ end
11
+
12
+ let(:finished) do
13
+ EM::DefaultDeferrable.new
14
+ end
15
+
16
+ describe EM::Protocols::Zmq2::Sub do
17
+ class MySub < EM::Protocols::Zmq2::Sub
18
+ attr :incoming_queue
19
+ def initialize(connected, finished, opts={})
20
+ super opts
21
+ @connected = connected
22
+ @finished = finished
23
+ @incoming_queue = []
24
+ @to_catch = 2
25
+ end
26
+ def peer_free(peer, connection)
27
+ super
28
+ @connected.succeed if @peers.size == 2
29
+ end
30
+ def receive_message(message)
31
+ @incoming_queue << message
32
+ if message.last == 'xxx'
33
+ @to_catch -= 1
34
+ @finished.succeed if @to_catch == 0
35
+ end
36
+ end
37
+ end
38
+
39
+ attr :sub
40
+ before do
41
+ @sub = MySub.new(connected, finished, subscribe: 'mess')
42
+ @sub.connect(Native::ZBIND_ADDR)
43
+ @sub.bind(Native::ZCONNECT_ADDR)
44
+ end
45
+
46
+ let(:messages_a) do
47
+ 1000.times.map{|n| ['mess_a', n.to_s]} << ['mess_a', 'xxx']
48
+ end
49
+
50
+ let(:messages_b) do
51
+ 1000.times.map{|n| ['mess_b', n.to_s]} << ['mess_b', 'xxx']
52
+ end
53
+
54
+ it "should accept messages" do
55
+ Native.with_socket_pair('PUB') do |zbind, zconnect|
56
+ thrd1, thrd2 = nil
57
+ EM.run do
58
+ connected.callback do
59
+ thrd1 = Thread.new do
60
+ messages_a.each do |message|
61
+ zbind.send_strings(message)
62
+ end
63
+ end
64
+ thrd2 = Thread.new do
65
+ messages_b.each do |message|
66
+ zconnect.send_strings(message)
67
+ end
68
+ end
69
+ end
70
+ finished.callback do
71
+ EM.next_tick{ EM.stop }
72
+ end
73
+ end
74
+ thrd1.join
75
+ thrd2.join
76
+ end
77
+ (sub.incoming_queue - messages_a - messages_b).must_be_empty
78
+ (messages_a - sub.incoming_queue).must_be_empty
79
+ (messages_b - sub.incoming_queue).must_be_empty
80
+ end
81
+ end
82
+
83
+ describe EM::Protocols::Zmq2::PrePub do
84
+ class MyPrePub < EM::Protocols::Zmq2::PrePub
85
+ def initialize(connected, opts={})
86
+ super opts
87
+ @connected = connected
88
+ end
89
+ def peer_free(peer, connection)
90
+ super
91
+ @connected.succeed if @peers.size == 2
92
+ end
93
+ end
94
+
95
+ attr :pub
96
+ before do
97
+ @pub = MyPrePub.new(connected)
98
+ @pub.connect(Native::ZBIND_ADDR)
99
+ @pub.bind(Native::ZCONNECT_ADDR)
100
+ end
101
+
102
+ let(:messages) {
103
+ 100.times.map{|n| ['mess_a', n.to_s]} << ['mess_a', 'xxx']
104
+ }
105
+
106
+ it "should send messages" do
107
+ results = []
108
+ Native.with_socket_pair('SUB') do |zbind, zconnect|
109
+ zbind.setsockopt(ZMQ::SUBSCRIBE, 'mess')
110
+ zconnect.setsockopt(ZMQ::SUBSCRIBE, 'mess')
111
+ thrds = [zbind, zconnect].map{|z| Thread.new do
112
+ res = []
113
+ while true
114
+ recv = []
115
+ z.recv_strings recv
116
+ res << recv
117
+ break if recv.last == 'xxx'
118
+ end
119
+ res
120
+ end}
121
+ EM.run do
122
+ connected.callback do
123
+ messages.each do |message|
124
+ pub.send_message message
125
+ end
126
+ pub.close do
127
+ EM.next_tick do EM.stop end
128
+ end
129
+ end
130
+ end
131
+ results = thrds.map(&:value)
132
+ end
133
+ results[0].must_equal messages
134
+ results[1].must_equal messages
135
+ end
136
+ end
137
+
138
+ describe EM::Protocols::Zmq2::Pub do
139
+ class MyPub < EM::Protocols::Zmq2::Pub
140
+ def initialize(connected, opts={})
141
+ super opts
142
+ @connected = connected
143
+ end
144
+ def peer_free(peer, connection)
145
+ super
146
+ @connected.succeed if @peers.size == 2
147
+ end
148
+ end
149
+
150
+ attr :pub
151
+ before do
152
+ @pub = MyPub.new(connected)
153
+ @pub.connect(Native::ZBIND_ADDR)
154
+ @pub.bind(Native::ZCONNECT_ADDR)
155
+ end
156
+
157
+ let(:messages) {
158
+ 500.times.map{|n| ['mess_a', n.to_s]} << ['mess_a', 'xxx']
159
+ }
160
+
161
+ it "should send a lot of messages" do
162
+ results = []
163
+ Native.with_socket_pair('SUB') do |zbind, zconnect|
164
+ zbind.setsockopt(ZMQ::SUBSCRIBE, 'mess')
165
+ zconnect.setsockopt(ZMQ::SUBSCRIBE, 'mess')
166
+ thrds = [zbind, zconnect].map{|z| Thread.new do
167
+ res = []
168
+ while true
169
+ recv = []
170
+ z.recv_strings recv
171
+ res << recv
172
+ #p [z.object_id, *recv]
173
+ break if recv.last == 'xxx'
174
+ end
175
+ res
176
+ end}
177
+ EM.run do
178
+ connected.callback do
179
+ messages.each do |message|
180
+ pub.send_message message
181
+ end
182
+ pub.close do
183
+ EM.next_tick do EM.stop end
184
+ end
185
+ end
186
+ end
187
+ results = thrds.map(&:value)
188
+ end
189
+ results[0].must_equal messages
190
+ results[1].must_equal messages
191
+ end
192
+
193
+ it "should not accept message when hwm is low and strategy is :drop_last" do
194
+ pub.hwm = 1
195
+ pub.hwm_strategy = :drop_last
196
+ results = nil
197
+ EM.run do
198
+ EM.defer proc{
199
+ Native.with_socket_pair('SUB') do |zbind, zconnect|
200
+ sleep 0.2
201
+ end
202
+ }, proc {
203
+ pub.send_message(messages[0]).must_equal true
204
+ pub.send_message(messages[1]).must_equal false
205
+ connected.instance_variable_set(:@deferred_status, nil)
206
+ connected.callback do
207
+ pub.send_message(messages.last).must_equal true
208
+ end
209
+ EM.defer proc{
210
+ Native.with_socket_pair('SUB') do |zbind, zconnect|
211
+ zbind.setsockopt(ZMQ::SUBSCRIBE, 'mess')
212
+ zconnect.setsockopt(ZMQ::SUBSCRIBE, 'mess')
213
+ results = [zbind, zconnect].map{|z| Thread.new do
214
+ res = []
215
+ 2.times do
216
+ recv = []
217
+ z.recv_strings recv
218
+ res << recv
219
+ end
220
+ res
221
+ end}.map(&:value)
222
+ end
223
+ }, proc{
224
+ EM.next_tick{ EM.stop }
225
+ }
226
+ }
227
+ end
228
+ results[0].must_equal [messages.first, messages.last]
229
+ results[1].must_equal [messages.first, messages.last]
230
+ end
231
+
232
+ it "should drop first message when hwm is low and strategy is :drop_first" do
233
+ pub.hwm = 1
234
+ pub.hwm_strategy = :drop_first
235
+ results = nil
236
+ EM.run do
237
+ EM.defer proc{
238
+ Native.with_socket_pair('SUB') do |zbind, zconnect|
239
+ sleep 0.2
240
+ end
241
+ }, proc {
242
+ pub.send_message(messages[0]).must_equal true
243
+ pub.send_message(messages[1]).must_equal true
244
+ connected.instance_variable_set(:@deferred_status, nil)
245
+ connected.callback do
246
+ pub.send_message(messages.last).must_equal true
247
+ end
248
+ EM.defer proc{
249
+ Native.with_socket_pair('SUB') do |zbind, zconnect|
250
+ zbind.setsockopt(ZMQ::SUBSCRIBE, 'mess')
251
+ zconnect.setsockopt(ZMQ::SUBSCRIBE, 'mess')
252
+ results = [zbind, zconnect].map{|z| Thread.new do
253
+ res = []
254
+ 2.times do
255
+ recv = []
256
+ z.recv_strings recv
257
+ res << recv
258
+ end
259
+ res
260
+ end}.map(&:value)
261
+ end
262
+ }, proc{
263
+ EM.next_tick{ EM.stop }
264
+ }
265
+ }
266
+ end
267
+ results[0].must_equal [messages[1], messages.last]
268
+ results[1].must_equal [messages[1], messages.last]
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,64 @@
1
+ require 'eventmachine'
2
+ require 'minitest/autorun'
3
+ require File.expand_path('../helper.rb', __FILE__)
4
+
5
+ require 'em/protocols/zmq2/socket'
6
+
7
+ describe EM::Protocols::Zmq2::Socket do
8
+ class MSocket < EM::Protocols::Zmq2::Socket
9
+ include DeferredMixin
10
+ end
11
+ let(:connected){ EM::DefaultDeferrable.new }
12
+ let(:fan) { MSocket.new(connected: connected) }
13
+ let(:sink) { MSocket.new() }
14
+
15
+ it 'should connect after timeout to tcp' do
16
+ were_connected = false
17
+ EM.run {
18
+ connected.callback {
19
+ were_connected = true
20
+ EM.next_tick { EM.stop }
21
+ }
22
+ fan.connect(Native::ZBIND_ADDR)
23
+ fan.connect(Native::ZCONNECT_ADDR)
24
+ EM.add_timer(0.1) do
25
+ sink.bind(Native::ZBIND_ADDR)
26
+ sink.bind(Native::ZCONNECT_ADDR)
27
+ EM.add_timer(0.1) do
28
+ EM.next_tick { EM.stop }
29
+ end
30
+ end
31
+ }
32
+ were_connected.must_equal true
33
+ end
34
+
35
+ unless RUBY_PLATFORM =~ /windows|mingw|mswin/
36
+ it 'should connect after timeout to ipc' do
37
+ socket1 = File.expand_path("../test1.sock", __FILE__)
38
+ socket2 = File.expand_path("../test2.sock", __FILE__)
39
+ File.unlink(socket1) rescue nil
40
+ File.unlink(socket2) rescue nil
41
+
42
+ were_connected = false
43
+ EM.run {
44
+ connected.callback {
45
+ were_connected = true
46
+ EM.next_tick { EM.stop }
47
+ }
48
+ fan.connect('ipc://'+socket1)
49
+ fan.connect('ipc://'+socket2)
50
+ EM.add_timer(0.1) do
51
+ sink.bind('ipc://'+socket1)
52
+ sink.bind('ipc://'+socket2)
53
+ EM.add_timer(0.1) do
54
+ EM.next_tick { EM.stop }
55
+ end
56
+ end
57
+ }
58
+ were_connected.must_equal true
59
+
60
+ File.unlink(socket1) rescue nil
61
+ File.unlink(socket2) rescue nil
62
+ end
63
+ end
64
+ end
data/tests/test_rep.rb ADDED
@@ -0,0 +1,117 @@
1
+ require 'eventmachine'
2
+ require 'minitest/autorun'
3
+ require File.expand_path('../helper.rb', __FILE__)
4
+
5
+ require 'em/protocols/zmq2/rep'
6
+
7
+ describe 'Rep' do
8
+ let(:connected) do
9
+ EM::DefaultDeferrable.new
10
+ end
11
+
12
+ let(:finished) do
13
+ EM::DefaultDeferrable.new
14
+ end
15
+
16
+ module MyRepMixin
17
+ attr :incoming_queue
18
+ def initialize(connected, finished, opts={})
19
+ super opts
20
+ @connected = connected
21
+ @finished = finished
22
+ @incoming_queue = []
23
+ end
24
+ def peer_free(peer_identity, connection)
25
+ super
26
+ @connected.succeed
27
+ end
28
+ def receive_request(message, envelope)
29
+ message.first.must_equal 'hello'
30
+ envelope.first.must_be :start_with?, 'BIND_'
31
+ send_reply(['world', *message[1..-1]], envelope)
32
+ @finished.succeed if message.last == 'xxx'
33
+ end
34
+ end
35
+
36
+ describe EM::Protocols::Zmq2::PreRep do
37
+ class MyPreRep < EM::Protocols::Zmq2::PreRep
38
+ include MyRepMixin
39
+ end
40
+
41
+ attr :req
42
+ before do
43
+ @req = MyPreRep.new(connected, finished, identity: 'REP')
44
+ @req.connect(Native::ZBIND_ADDR)
45
+ end
46
+
47
+ let(:messages){
48
+ 300.times.map{|i| ['hello', i.to_s]} << ['hello', 'xxx']
49
+ }
50
+
51
+ it 'should make replies' do
52
+ replies = []
53
+ Native.with_socket('REQ') do |zreq|
54
+ thrd = Thread.new do
55
+ messages.each do |message|
56
+ zreq.send_strings message
57
+ reply = []
58
+ zreq.recv_strings reply
59
+ replies << reply
60
+ end
61
+ end
62
+ EM.run {
63
+ finished.callback {
64
+ req.close do
65
+ EM.next_tick{ EM.stop }
66
+ end
67
+ }
68
+ }
69
+ thrd.join
70
+ end
71
+ replies.all?{|reply| reply.first == 'world'}.must_equal true
72
+ replies.map{|reply| ['hello', *reply[1..-1]]}.must_equal messages
73
+ end
74
+ end
75
+
76
+ describe EM::Protocols::Zmq2::Rep do
77
+ class MyRep < EM::Protocols::Zmq2::Rep
78
+ include MyRepMixin
79
+ end
80
+
81
+ attr :req
82
+ before do
83
+ @req = MyRep.new(connected, finished, identity: 'REP')
84
+ @req.connect(Native::ZBIND_ADDR)
85
+ end
86
+
87
+ let(:messages){
88
+ 5000.times.map{|i| ['hello', i.to_s]} << ['hello', 'xxx']
89
+ }
90
+
91
+ it 'should make a lot of replies' do
92
+ replies = []
93
+ Native.with_socket('DEALER') do |zreq|
94
+ thrd = Thread.new do
95
+ messages.each do |message|
96
+ zreq.send_strings ['', *message]
97
+ end
98
+ messages.size.times do
99
+ reply = []
100
+ zreq.recv_strings reply
101
+ replies << reply[1..-1]
102
+ end
103
+ end
104
+ EM.run {
105
+ finished.callback {
106
+ req.close do
107
+ EM.next_tick{ EM.stop }
108
+ end
109
+ }
110
+ }
111
+ thrd.join
112
+ end
113
+ replies.all?{|reply| reply.first == 'world'}.must_equal true
114
+ replies.map{|reply| ['hello', *reply[1..-1]]}.must_equal messages
115
+ end
116
+ end
117
+ end