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.
@@ -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