ffi-rzmq 0.8.2 → 0.9.0

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 (56) hide show
  1. data/AUTHORS.txt +1 -0
  2. data/History.txt +35 -0
  3. data/README.rdoc +48 -15
  4. data/Rakefile +7 -2
  5. data/examples/README.rdoc +21 -76
  6. data/examples/{local_lat.rb → v2api/local_lat.rb} +27 -12
  7. data/examples/v2api/local_lat_poll.rb +66 -0
  8. data/examples/{local_throughput.rb → v2api/local_throughput.rb} +24 -9
  9. data/examples/v2api/publish_subscribe.rb +82 -0
  10. data/examples/{remote_lat.rb → v2api/remote_lat.rb} +26 -8
  11. data/examples/v2api/remote_throughput.rb +39 -0
  12. data/examples/v2api/reqrep_poll.rb +62 -0
  13. data/examples/v2api/request_response.rb +40 -0
  14. data/examples/v2api/throughput_measurement.rb +138 -0
  15. data/examples/v3api/local_lat.rb +59 -0
  16. data/examples/v3api/local_lat_poll.rb +66 -0
  17. data/examples/v3api/local_throughput.rb +65 -0
  18. data/examples/v3api/publish_subscribe.rb +82 -0
  19. data/examples/v3api/remote_lat.rb +71 -0
  20. data/examples/v3api/remote_throughput.rb +47 -0
  21. data/examples/v3api/reqrep_poll.rb +62 -0
  22. data/examples/v3api/request_response.rb +40 -0
  23. data/examples/v3api/throughput_measurement.rb +166 -0
  24. data/ext/README +5 -0
  25. data/ffi-rzmq.gemspec +4 -4
  26. data/lib/ffi-rzmq.rb +4 -1
  27. data/lib/ffi-rzmq/constants.rb +178 -0
  28. data/lib/ffi-rzmq/context.rb +61 -45
  29. data/lib/ffi-rzmq/device.rb +22 -9
  30. data/lib/ffi-rzmq/exceptions.rb +0 -98
  31. data/lib/ffi-rzmq/libc.rb +19 -0
  32. data/lib/ffi-rzmq/libzmq.rb +188 -0
  33. data/lib/ffi-rzmq/message.rb +33 -40
  34. data/lib/ffi-rzmq/poll.rb +49 -52
  35. data/lib/ffi-rzmq/socket.rb +902 -392
  36. data/lib/ffi-rzmq/util.rb +101 -0
  37. data/spec/context_spec.rb +47 -21
  38. data/spec/device_spec.rb +78 -58
  39. data/spec/message_spec.rb +90 -12
  40. data/spec/multipart_spec.rb +162 -0
  41. data/spec/nonblocking_recv_spec.rb +325 -0
  42. data/spec/pushpull_spec.rb +95 -34
  43. data/spec/reqrep_spec.rb +55 -20
  44. data/spec/socket_spec.rb +353 -204
  45. data/spec/spec_helper.rb +46 -3
  46. data/version.txt +1 -1
  47. metadata +91 -66
  48. data/examples/local_lat_poll.rb +0 -54
  49. data/examples/local_lat_zerocopy.rb +0 -24
  50. data/examples/publish_subscribe.rb +0 -52
  51. data/examples/remote_lat_zerocopy.rb +0 -35
  52. data/examples/remote_throughput.rb +0 -27
  53. data/examples/reqrep_poll.rb +0 -49
  54. data/examples/request_response.rb +0 -23
  55. data/lib/ffi-rzmq/wrapper.rb +0 -121
  56. data/lib/ffi-rzmq/zmq.rb +0 -198
@@ -0,0 +1,162 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ module ZMQ
4
+ describe Socket do
5
+ context "multipart messages" do
6
+ before(:all) { @ctx = Context.new }
7
+ after(:all) { @ctx.terminate }
8
+
9
+ context "without identity" do
10
+ include APIHelper
11
+
12
+ before(:all) do
13
+ @rep = Socket.new(@ctx.pointer, ZMQ::REP)
14
+ port = bind_to_random_tcp_port(@rep)
15
+
16
+ @req = Socket.new(@ctx.pointer, ZMQ::REQ)
17
+ @req.connect("tcp://127.0.0.1:#{port}")
18
+ end
19
+
20
+ after(:all) do
21
+ @req.close
22
+ @rep.close
23
+ end
24
+
25
+ it "should be delivered between REQ and REP returning an array of strings" do
26
+ req_data, rep_data = [ "1", "2" ], [ "2", "3" ]
27
+
28
+ @req.send_strings(req_data)
29
+ strings = []
30
+ rc = @rep.recv_strings(strings)
31
+ strings.should == req_data
32
+
33
+ @rep.send_strings(rep_data)
34
+ strings = []
35
+ rc = @req.recv_strings(strings)
36
+ strings.should == rep_data
37
+ end
38
+
39
+ it "should be delivered between REQ and REP returning an array of messages" do
40
+ req_data, rep_data = [ "1", "2" ], [ "2", "3" ]
41
+
42
+ @req.send_strings(req_data)
43
+ messages = []
44
+ rc = @rep.recvmsgs(messages)
45
+ messages.each_with_index do |message, index|
46
+ message.copy_out_string.should == req_data[index]
47
+ end
48
+
49
+ @rep.send_strings(rep_data)
50
+ messages = []
51
+ rc = @req.recvmsgs(messages)
52
+ messages.each_with_index do |message, index|
53
+ message.copy_out_string.should == rep_data[index]
54
+ end
55
+ end
56
+ end
57
+
58
+ if version2?
59
+ context "with identity" do
60
+ include APIHelper
61
+
62
+ before(:each) do # was :all
63
+ @rep = Socket.new(@ctx.pointer, ZMQ::XREP)
64
+ port = bind_to_random_tcp_port(@rep)
65
+
66
+ @req = Socket.new(@ctx.pointer, ZMQ::REQ)
67
+ @req.identity = 'foo'
68
+ @req.connect("tcp://127.0.0.1:#{port}")
69
+ end
70
+
71
+ after(:each) do # was :all
72
+ @req.close
73
+ @rep.close
74
+ end
75
+
76
+ it "should be delivered between REQ and REP returning an array of strings with an empty string as the envelope delimiter" do
77
+ req_data, rep_data = "hello", [ @req.identity, "", "ok" ]
78
+
79
+ @req.send_string(req_data)
80
+ strings = []
81
+ rc = @rep.recv_strings(strings)
82
+ strings.should == [ @req.identity, "", "hello" ]
83
+
84
+ @rep.send_strings(rep_data)
85
+ string = ''
86
+ rc = @req.recv_string(string)
87
+ string.should == rep_data.last
88
+ end
89
+
90
+ it "should be delivered between REQ and REP returning an array of messages with an empty string as the envelope delimiter" do
91
+ req_data, rep_data = "hello", [ @req.identity, "", "ok" ]
92
+
93
+ @req.send_string(req_data)
94
+ msgs = []
95
+ rc = @rep.recvmsgs(msgs)
96
+ msgs[0].copy_out_string.should == @req.identity
97
+ msgs[1].copy_out_string.should == ""
98
+ msgs[2].copy_out_string.should == "hello"
99
+
100
+ @rep.send_strings(rep_data)
101
+ msgs = []
102
+ rc = @req.recvmsgs(msgs)
103
+ msgs[0].copy_out_string.should == rep_data.last
104
+ end
105
+ end
106
+
107
+ elsif LibZMQ.version3? # version3
108
+
109
+ context "with identity" do
110
+ include APIHelper
111
+
112
+ before(:each) do # was :all
113
+ @rep = Socket.new(@ctx.pointer, ZMQ::ROUTER)
114
+ port = bind_to_random_tcp_port(@rep)
115
+
116
+ @req = Socket.new(@ctx.pointer, ZMQ::DEALER)
117
+ @req.identity = 'foo'
118
+ @req.connect("tcp://127.0.0.1:#{port}")
119
+ end
120
+
121
+ after(:each) do # was :all
122
+ @req.close
123
+ @rep.close
124
+ end
125
+
126
+ it "should be delivered between ROUTER and DEALER returning an array of strings" do
127
+ req_data, rep_data = "hello", [ @req.identity, "ok" ]
128
+
129
+ @req.send_string(req_data)
130
+ strings = []
131
+ rc = @rep.recv_strings(strings)
132
+ strings.should == [ @req.identity, "hello" ]
133
+
134
+ @rep.send_strings(rep_data)
135
+ string = ''
136
+ rc = @req.recv_string(string)
137
+ string.should == rep_data.last
138
+ end
139
+
140
+ it "should be delivered between ROUTER and DEALER returning an array of messages" do
141
+ req_data, rep_data = "hello", [ @req.identity, "ok" ]
142
+
143
+ @req.send_string(req_data)
144
+ msgs = []
145
+ rc = @rep.recvmsgs(msgs)
146
+ msgs[0].copy_out_string.should == @req.identity
147
+ msgs[1].copy_out_string.should == "hello"
148
+
149
+ @rep.send_strings(rep_data)
150
+ msgs = []
151
+ rc = @req.recvmsgs(msgs)
152
+ msgs[0].copy_out_string.should == rep_data.last
153
+ end
154
+
155
+ end
156
+
157
+ end # if version...
158
+
159
+
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,325 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ module ZMQ
5
+
6
+
7
+ describe Socket do
8
+ before(:all) do
9
+ @ctx = Context.new
10
+ end
11
+
12
+ after(:all) do
13
+ @ctx.terminate
14
+ end
15
+
16
+
17
+ shared_examples_for "any socket" do
18
+
19
+ it "returns -1 and gets EAGAIN when there are no messages to read" do
20
+ array = []
21
+ rc = @receiver.recvmsgs(array, NonBlockingFlag)
22
+ Util.resultcode_ok?(rc).should be_false
23
+ array.size.should == 0
24
+ ZMQ::Util.errno.should == ZMQ::EAGAIN
25
+ end
26
+
27
+ end
28
+
29
+ shared_examples_for "sockets without exposed envelopes" do
30
+
31
+ it "read the single message and returns a successful result code" do
32
+ rc = @sender.send_string('test')
33
+ Util.resultcode_ok?(rc).should be_true
34
+ sleep 0.1 # give it time to deliver to the receiver
35
+
36
+ array = []
37
+ rc = @receiver.recvmsgs(array, NonBlockingFlag)
38
+ Util.resultcode_ok?(rc).should be_true
39
+ array.size.should == 1
40
+ end
41
+
42
+ it "read all message parts transmitted and returns a successful result code" do
43
+ strings = Array.new(10, 'test')
44
+ rc = @sender.send_strings(strings)
45
+ Util.resultcode_ok?(rc).should be_true
46
+ sleep 0.1 # give it time to deliver to the sub socket
47
+
48
+ array = []
49
+ rc = @receiver.recvmsgs(array, NonBlockingFlag)
50
+ Util.resultcode_ok?(rc).should be_true
51
+ array.size.should == 10
52
+ end
53
+
54
+ end
55
+
56
+ shared_examples_for "sockets with exposed envelopes" do
57
+
58
+ it "read the single message and returns a successful result code" do
59
+ rc = @sender.send_string('test')
60
+ Util.resultcode_ok?(rc).should be_true
61
+ sleep 0.1 # give it time to deliver to the receiver
62
+
63
+ array = []
64
+ rc = @receiver.recvmsgs(array, NonBlockingFlag)
65
+ Util.resultcode_ok?(rc).should be_true
66
+ array.size.should == 1 + 1 # extra 1 for envelope
67
+ end
68
+
69
+ it "read all message parts transmitted and returns a successful result code" do
70
+ strings = Array.new(10, 'test')
71
+ rc = @sender.send_strings(strings)
72
+ Util.resultcode_ok?(rc).should be_true
73
+ sleep 0.1 # give it time to deliver to the sub socket
74
+
75
+ array = []
76
+ rc = @receiver.recvmsgs(array, NonBlockingFlag)
77
+ Util.resultcode_ok?(rc).should be_true
78
+ array.size.should == 10 + 1 # add 1 for the envelope
79
+ end
80
+
81
+ end
82
+
83
+ context "PUB" do
84
+
85
+ describe "non-blocking #recvmsgs where sender connects & receiver binds" do
86
+ include APIHelper
87
+
88
+ before(:each) do
89
+ @receiver = @ctx.socket ZMQ::SUB
90
+ port = bind_to_random_tcp_port(@receiver)
91
+ assert_ok(@receiver.setsockopt(ZMQ::SUBSCRIBE, ''))
92
+ @sender = @ctx.socket ZMQ::PUB
93
+ assert_ok(@sender.connect("tcp://127.0.0.1:#{port}"))
94
+ sleep 0.3
95
+ end
96
+
97
+ after(:each) do
98
+ @receiver.close
99
+ @sender.close
100
+ end
101
+
102
+ it_behaves_like "any socket"
103
+ it_behaves_like "sockets without exposed envelopes"
104
+
105
+ end # describe 'non-blocking recvmsgs'
106
+
107
+ describe "non-blocking #recvmsgs where sender binds & receiver connects" do
108
+ include APIHelper
109
+
110
+ before(:each) do
111
+ @receiver = @ctx.socket ZMQ::SUB
112
+ port = connect_to_random_tcp_port(@receiver)
113
+ assert_ok(@receiver.setsockopt(ZMQ::SUBSCRIBE, ''))
114
+ @sender = @ctx.socket ZMQ::PUB
115
+ assert_ok(@sender.bind("tcp://127.0.0.1:#{port}"))
116
+ sleep 0.3
117
+ end
118
+
119
+ after(:each) do
120
+ @receiver.close
121
+ @sender.close
122
+ end
123
+
124
+ it_behaves_like "any socket"
125
+ it_behaves_like "sockets without exposed envelopes"
126
+
127
+ end # describe 'non-blocking recvmsgs'
128
+
129
+ end # Pub
130
+
131
+ context "REQ" do
132
+
133
+ describe "non-blocking #recvmsgs where sender connects & receiver binds" do
134
+ include APIHelper
135
+
136
+ before(:each) do
137
+ @receiver = @ctx.socket ZMQ::REP
138
+ port = bind_to_random_tcp_port(@receiver)
139
+ @sender = @ctx.socket ZMQ::REQ
140
+ assert_ok(@sender.connect("tcp://127.0.0.1:#{port}"))
141
+ sleep 0.1
142
+ end
143
+
144
+ after(:each) do
145
+ @receiver.close
146
+ @sender.close
147
+ end
148
+
149
+ it_behaves_like "any socket"
150
+ it_behaves_like "sockets without exposed envelopes"
151
+
152
+ end # describe 'non-blocking recvmsgs'
153
+
154
+ describe "non-blocking #recvmsgs where sender binds & receiver connects" do
155
+ include APIHelper
156
+
157
+ before(:each) do
158
+ @receiver = @ctx.socket ZMQ::REP
159
+ port = connect_to_random_tcp_port(@receiver)
160
+ @sender = @ctx.socket ZMQ::REQ
161
+ assert_ok(@sender.bind("tcp://127.0.0.1:#{port}"))
162
+ sleep 0.1
163
+ end
164
+
165
+ after(:each) do
166
+ @receiver.close
167
+ @sender.close
168
+ end
169
+
170
+ it_behaves_like "any socket"
171
+ it_behaves_like "sockets without exposed envelopes"
172
+
173
+ end # describe 'non-blocking recvmsgs'
174
+
175
+ end # REQ
176
+
177
+
178
+ context "PUSH" do
179
+
180
+ describe "non-blocking #recvmsgs where sender connects & receiver binds" do
181
+ include APIHelper
182
+
183
+ before(:each) do
184
+ @receiver = @ctx.socket ZMQ::PULL
185
+ port = bind_to_random_tcp_port(@receiver)
186
+ @sender = @ctx.socket ZMQ::PUSH
187
+ assert_ok(@sender.connect("tcp://127.0.0.1:#{port}"))
188
+ sleep 0.1
189
+ end
190
+
191
+ after(:each) do
192
+ @receiver.close
193
+ @sender.close
194
+ end
195
+
196
+ it_behaves_like "any socket"
197
+ it_behaves_like "sockets without exposed envelopes"
198
+
199
+ end # describe 'non-blocking recvmsgs'
200
+
201
+ describe "non-blocking #recvmsgs where sender binds & receiver connects" do
202
+ include APIHelper
203
+
204
+ before(:each) do
205
+ @receiver = @ctx.socket ZMQ::PULL
206
+ port = connect_to_random_tcp_port(@receiver)
207
+ @sender = @ctx.socket ZMQ::PUSH
208
+ assert_ok(@sender.bind("tcp://127.0.0.1:#{port}"))
209
+ sleep 0.1
210
+ end
211
+
212
+ after(:each) do
213
+ @receiver.close
214
+ @sender.close
215
+ end
216
+
217
+ it_behaves_like "any socket"
218
+ it_behaves_like "sockets without exposed envelopes"
219
+
220
+ end # describe 'non-blocking recvmsgs'
221
+
222
+ end # PUSH
223
+
224
+
225
+ unless LibZMQ.version4?
226
+
227
+ context "DEALER" do
228
+
229
+ describe "non-blocking #recvmsgs where sender connects & receiver binds" do
230
+ include APIHelper
231
+
232
+ before(:each) do
233
+ @receiver = @ctx.socket ZMQ::ROUTER
234
+ port = bind_to_random_tcp_port(@receiver)
235
+ @sender = @ctx.socket ZMQ::DEALER
236
+ assert_ok(@sender.connect("tcp://127.0.0.1:#{port}"))
237
+ sleep 0.1
238
+ end
239
+
240
+ after(:each) do
241
+ @receiver.close
242
+ @sender.close
243
+ end
244
+
245
+ it_behaves_like "any socket"
246
+ it_behaves_like "sockets with exposed envelopes"
247
+
248
+ end # describe 'non-blocking recvmsgs'
249
+
250
+ describe "non-blocking #recvmsgs where sender binds & receiver connects" do
251
+ include APIHelper
252
+
253
+ before(:each) do
254
+ @receiver = @ctx.socket ZMQ::ROUTER
255
+ port = connect_to_random_tcp_port(@receiver)
256
+ @sender = @ctx.socket ZMQ::DEALER
257
+ assert_ok(@sender.bind("tcp://127.0.0.1:#{port}"))
258
+ sleep 0.1
259
+ end
260
+
261
+ after(:each) do
262
+ @receiver.close
263
+ @sender.close
264
+ end
265
+
266
+ it_behaves_like "any socket"
267
+ it_behaves_like "sockets with exposed envelopes"
268
+
269
+ end # describe 'non-blocking recvmsgs'
270
+
271
+ end # DEALER
272
+
273
+ end # unless version4?
274
+
275
+
276
+ context "XREQ" do
277
+
278
+ describe "non-blocking #recvmsgs where sender connects & receiver binds" do
279
+ include APIHelper
280
+
281
+ before(:each) do
282
+ @receiver = @ctx.socket ZMQ::XREP
283
+ port = bind_to_random_tcp_port(@receiver)
284
+ @sender = @ctx.socket ZMQ::XREQ
285
+ assert_ok(@sender.connect("tcp://127.0.0.1:#{port}"))
286
+ sleep 0.1
287
+ end
288
+
289
+ after(:each) do
290
+ @receiver.close
291
+ @sender.close
292
+ end
293
+
294
+ it_behaves_like "any socket"
295
+ it_behaves_like "sockets with exposed envelopes"
296
+
297
+ end # describe 'non-blocking recvmsgs'
298
+
299
+ describe "non-blocking #recvmsgs where sender binds & receiver connects" do
300
+ include APIHelper
301
+
302
+ before(:each) do
303
+ @receiver = @ctx.socket ZMQ::XREP
304
+ port = connect_to_random_tcp_port(@receiver)
305
+ @sender = @ctx.socket ZMQ::XREQ
306
+ assert_ok(@sender.bind("tcp://127.0.0.1:#{port}"))
307
+ sleep 0.1
308
+ end
309
+
310
+ after(:each) do
311
+ @receiver.close
312
+ @sender.close
313
+ end
314
+
315
+ it_behaves_like "any socket"
316
+ it_behaves_like "sockets with exposed envelopes"
317
+
318
+ end # describe 'non-blocking recvmsgs'
319
+
320
+ end # XREQ
321
+
322
+ end # describe Socket
323
+
324
+
325
+ end # module ZMQ