ffi-rzmq 1.0.3 → 2.0.4

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 (59) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +1 -1
  3. data/AUTHORS.txt +5 -1
  4. data/History.txt +45 -0
  5. data/README.rdoc +58 -28
  6. data/Rakefile +15 -0
  7. data/examples/README.rdoc +1 -3
  8. data/examples/{v3api/latency_measurement.rb → latency_measurement.rb} +1 -2
  9. data/examples/{v3api/local_lat.rb → local_lat.rb} +1 -1
  10. data/examples/{v3api/local_lat_poll.rb → local_lat_poll.rb} +4 -4
  11. data/examples/{v3api/local_throughput.rb → local_throughput.rb} +1 -1
  12. data/examples/{v3api/pub.rb → pub.rb} +1 -1
  13. data/examples/{v2api/publish_subscribe.rb → publish_subscribe.rb} +2 -2
  14. data/examples/{v2api/remote_lat.rb → remote_lat.rb} +1 -1
  15. data/examples/{v3api/remote_throughput.rb → remote_throughput.rb} +4 -3
  16. data/examples/repreq_over_curve.rb +60 -0
  17. data/examples/{v2api/reqrep_poll.rb → reqrep_poll.rb} +3 -4
  18. data/examples/{v2api/request_response.rb → request_response.rb} +1 -2
  19. data/examples/{v3api/sub.rb → sub.rb} +1 -2
  20. data/examples/{v3api/throughput_measurement.rb → throughput_measurement.rb} +1 -1
  21. data/examples/{v3api/xreqxrep_poll.rb → xreqxrep_poll.rb} +6 -7
  22. data/ffi-rzmq.gemspec +4 -4
  23. data/lib/ffi-rzmq.rb +2 -3
  24. data/lib/ffi-rzmq/context.rb +25 -53
  25. data/lib/ffi-rzmq/device.rb +8 -4
  26. data/lib/ffi-rzmq/exceptions.rb +3 -0
  27. data/lib/ffi-rzmq/message.rb +24 -30
  28. data/lib/ffi-rzmq/poll.rb +5 -16
  29. data/lib/ffi-rzmq/socket.rb +132 -282
  30. data/lib/ffi-rzmq/util.rb +28 -36
  31. data/lib/ffi-rzmq/version.rb +1 -1
  32. data/spec/context_spec.rb +18 -23
  33. data/spec/device_spec.rb +13 -12
  34. data/spec/message_spec.rb +13 -13
  35. data/spec/multipart_spec.rb +11 -11
  36. data/spec/nonblocking_recv_spec.rb +22 -22
  37. data/spec/poll_spec.rb +49 -49
  38. data/spec/pushpull_spec.rb +12 -11
  39. data/spec/reqrep_spec.rb +11 -11
  40. data/spec/socket_spec.rb +109 -196
  41. data/spec/spec_helper.rb +3 -11
  42. data/spec/util_spec.rb +29 -0
  43. metadata +80 -104
  44. data/examples/v2api/latency_measurement.rb +0 -139
  45. data/examples/v2api/local_lat.rb +0 -58
  46. data/examples/v2api/local_lat_poll.rb +0 -66
  47. data/examples/v2api/local_throughput.rb +0 -58
  48. data/examples/v2api/pub.rb +0 -46
  49. data/examples/v2api/remote_throughput.rb +0 -39
  50. data/examples/v2api/sub.rb +0 -74
  51. data/examples/v2api/throughput_measurement.rb +0 -138
  52. data/examples/v2api/xreqxrep_poll.rb +0 -93
  53. data/examples/v3api/publish_subscribe.rb +0 -82
  54. data/examples/v3api/remote_lat.rb +0 -71
  55. data/examples/v3api/reqrep_poll.rb +0 -62
  56. data/examples/v3api/request_response.rb +0 -40
  57. data/lib/ffi-rzmq/constants.rb +0 -187
  58. data/lib/ffi-rzmq/libc.rb +0 -19
  59. data/lib/ffi-rzmq/libzmq.rb +0 -283
data/lib/ffi-rzmq/util.rb CHANGED
@@ -5,6 +5,23 @@ module ZMQ
5
5
  #
6
6
  class Util
7
7
 
8
+ # Generate and return a CURVE public/private keypair
9
+ #
10
+ # Raises an error if ZeroMQ is not configured for CURVE connections.
11
+ # Install libsodium if this is the case.
12
+ def self.curve_keypair
13
+ public_key = FFI::MemoryPointer.from_string(' ' * 41)
14
+ private_key = FFI::MemoryPointer.from_string(' ' * 41)
15
+ rc = LibZMQ.zmq_curve_keypair public_key, private_key
16
+
17
+ if rc < 0
18
+ raise NotSupportedError.new "zmq_curve_keypair" , rc, ZMQ::Util.errno,
19
+ "Rebuild zeromq with libsodium to enable CURVE security options."
20
+ end
21
+
22
+ [public_key.read_string, private_key.read_string]
23
+ end
24
+
8
25
  # Returns true when +rc+ is greater than or equal to 0, false otherwise.
9
26
  #
10
27
  # We use the >= test because zmq_poll() returns the number of sockets
@@ -28,19 +45,6 @@ module ZMQ
28
45
  LibZMQ.zmq_strerror(errno).read_string
29
46
  end
30
47
 
31
- # Returns an array of the form [major, minor, patch] to represent the
32
- # version of libzmq.
33
- #
34
- # Class method! Invoke as: ZMQ::Util.version
35
- #
36
- def self.version
37
- major = FFI::MemoryPointer.new :int
38
- minor = FFI::MemoryPointer.new :int
39
- patch = FFI::MemoryPointer.new :int
40
- LibZMQ.zmq_version major, minor, patch
41
- [major.read_int, minor.read_int, patch.read_int]
42
- end
43
-
44
48
  # Attempts to bind to a random tcp port on +host+ up to +max_tries+
45
49
  # times. Returns the port number upon success or nil upon failure.
46
50
  #
@@ -56,7 +60,7 @@ module ZMQ
56
60
 
57
61
  resultcode_ok?(rc) ? random : nil
58
62
  end
59
-
63
+
60
64
  # :doc:
61
65
  # Called to verify whether there were any errors during
62
66
  # operation. If any are found, raise the appropriate #ZeroMQError.
@@ -90,38 +94,26 @@ module ZMQ
90
94
 
91
95
  else
92
96
  raise ZeroMQError.new source, result_code, -1,
93
- "Source [#{source}] does not match any zmq_* strings, rc [#{result_code}], errno [#{ZMQ::Util.errno}], error_string [#{ZMQ::Util.error_string}]"
97
+ "Source [#{source}] does not match any zmq_* strings, rc [#{result_code}], errno [#{ZMQ::Util.errno}], error_string [#{ZMQ::Util.error_string}]"
94
98
  end
95
99
  end
96
100
 
97
101
  def self.eagain?
98
102
  EAGAIN == ZMQ::Util.errno
99
103
  end
100
-
101
- if LibZMQ.version2?
102
- def self.context_error?(source)
103
- 'zmq_init' == source ||
104
- 'zmq_socket' == source
105
- end
106
-
107
- def self.message_error?(source)
108
- ['zmq_msg_init', 'zmq_msg_init_data', 'zmq_msg_copy', 'zmq_msg_move'].include?(source)
109
- end
110
-
111
- elsif LibZMQ.version3?
112
- def self.context_error?(source)
113
- 'zmq_ctx_new' == source ||
104
+
105
+ def self.context_error?(source)
106
+ 'zmq_ctx_new' == source ||
114
107
  'zmq_ctx_set' == source ||
115
108
  'zmq_ctx_get' == source ||
116
109
  'zmq_ctx_destory' == source ||
117
110
  'zmq_ctx_set_monitor' == source
118
- end
119
-
120
- def self.message_error?(source)
121
- ['zmq_msg_init', 'zmq_msg_init_data', 'zmq_msg_copy', 'zmq_msg_move', 'zmq_msg_close', 'zmq_msg_get',
122
- 'zmq_msg_more', 'zmq_msg_recv', 'zmq_msg_send', 'zmq_msg_set'].include?(source)
123
- end
124
- end # if LibZMQ.version...?
111
+ end
112
+
113
+ def self.message_error?(source)
114
+ ['zmq_msg_init', 'zmq_msg_init_data', 'zmq_msg_copy', 'zmq_msg_move', 'zmq_msg_close', 'zmq_msg_get',
115
+ 'zmq_msg_more', 'zmq_msg_recv', 'zmq_msg_send', 'zmq_msg_set'].include?(source)
116
+ end
125
117
 
126
118
  end # module Util
127
119
 
@@ -1,3 +1,3 @@
1
1
  module ZMQ
2
- VERSION = "1.0.3"
2
+ VERSION = "2.0.4"
3
3
  end
data/spec/context_spec.rb CHANGED
@@ -11,31 +11,31 @@ module ZMQ
11
11
  include APIHelper
12
12
 
13
13
  it "should return nil for negative io threads" do
14
- Context.create(-1).should be_nil
14
+ expect(Context.create(-1)).to eq(nil)
15
15
  end
16
16
 
17
17
  it "should default to requesting 1 i/o thread when no argument is passed" do
18
18
  ctx = Context.create
19
- ctx.io_threads.should == 1
19
+ expect(ctx.io_threads).to eq(1)
20
20
  end
21
21
 
22
22
  it "should set the :pointer accessor to non-nil" do
23
23
  ctx = Context.create
24
- ctx.pointer.should_not be_nil
24
+ expect(ctx.pointer).not_to be_nil
25
25
  end
26
26
 
27
27
  it "should set the :context accessor to non-nil" do
28
28
  ctx = Context.create
29
- ctx.context.should_not be_nil
29
+ expect(ctx.context).not_to be_nil
30
30
  end
31
31
 
32
32
  it "should set the :pointer and :context accessors to the same value" do
33
33
  ctx = Context.create
34
- ctx.pointer.should == ctx.context
34
+ expect(ctx.pointer).to eq(ctx.context)
35
35
  end
36
36
 
37
37
  it "should define a finalizer on this object" do
38
- ObjectSpace.should_receive(:define_finalizer)
38
+ expect(ObjectSpace).to receive(:define_finalizer)
39
39
  ctx = Context.create
40
40
  end
41
41
  end # context initializing
@@ -45,31 +45,31 @@ module ZMQ
45
45
  include APIHelper
46
46
 
47
47
  it "should raise a ContextError exception for negative io threads" do
48
- lambda { Context.new(-1) }.should raise_exception(ZMQ::ContextError)
48
+ expect { Context.new(-1) }.to raise_exception(ZMQ::ContextError)
49
49
  end
50
50
 
51
51
  it "should default to requesting 1 i/o thread when no argument is passed" do
52
52
  ctx = Context.new
53
- ctx.io_threads.should == 1
53
+ expect(ctx.io_threads).to eq(1)
54
54
  end
55
55
 
56
56
  it "should set the :pointer accessor to non-nil" do
57
57
  ctx = Context.new
58
- ctx.pointer.should_not be_nil
58
+ expect(ctx.pointer).not_to be_nil
59
59
  end
60
60
 
61
61
  it "should set the :context accessor to non-nil" do
62
62
  ctx = Context.new
63
- ctx.context.should_not be_nil
63
+ expect(ctx.context).not_to be_nil
64
64
  end
65
65
 
66
66
  it "should set the :pointer and :context accessors to the same value" do
67
67
  ctx = Context.new
68
- ctx.pointer.should == ctx.context
68
+ expect(ctx.pointer).to eq(ctx.context)
69
69
  end
70
70
 
71
71
  it "should define a finalizer on this object" do
72
- ObjectSpace.should_receive(:define_finalizer)
72
+ expect(ObjectSpace).to receive(:define_finalizer)
73
73
  Context.new 1
74
74
  end
75
75
  end # context initializing
@@ -79,19 +79,14 @@ module ZMQ
79
79
  it "should set the context to nil when terminating the library's context" do
80
80
  ctx = Context.new # can't use a shared context here because we are terminating it!
81
81
  ctx.terminate
82
- ctx.pointer.should be_nil
82
+ expect(ctx.pointer).to be_nil
83
83
  end
84
84
 
85
85
  it "should call the correct library function to terminate the context" do
86
86
  ctx = Context.new
87
-
88
- if LibZMQ.version2?
89
- LibZMQ.should_receive(:zmq_term).and_return(0)
90
- ctx.terminate
91
- else
92
- LibZMQ.should_receive(:zmq_ctx_destroy).with(ctx.pointer).and_return(0)
93
- ctx.terminate
94
- end
87
+
88
+ expect(LibZMQ).to receive(:zmq_ctx_destroy).with(ctx.pointer).and_return(0)
89
+ ctx.terminate
95
90
  end
96
91
  end # context terminate
97
92
 
@@ -99,8 +94,8 @@ module ZMQ
99
94
  context "when allocating a socket" do
100
95
  it "should return nil when allocation fails" do
101
96
  ctx = Context.new
102
- LibZMQ.stub(:zmq_socket => nil)
103
- ctx.socket(ZMQ::REQ).should be_nil
97
+ allow(LibZMQ).to receive(:zmq_socket).and_return(nil)
98
+ expect(ctx.socket(ZMQ::REQ)).to be_nil
104
99
  end
105
100
  end # context socket
106
101
 
data/spec/device_spec.rb CHANGED
@@ -5,7 +5,7 @@ module ZMQ
5
5
  describe Device do
6
6
  include APIHelper
7
7
 
8
- before(:all) do
8
+ before(:each) do
9
9
  @ctx = Context.new
10
10
  poller_setup
11
11
  @front_endpoint = "inproc://device_front_test"
@@ -13,7 +13,7 @@ module ZMQ
13
13
  @mutex = Mutex.new
14
14
  end
15
15
 
16
- after(:all) do
16
+ after(:each) do
17
17
  @ctx.terminate
18
18
  end
19
19
 
@@ -26,7 +26,9 @@ module ZMQ
26
26
  front = @ctx.socket(ZMQ::PUSH)
27
27
  front.bind(@front_endpoint)
28
28
  @mutex.synchronize { @device_thread = true }
29
- Device.new(ZMQ::STREAMER, back, front)
29
+ puts "create streamer device and running..."
30
+ Device.new(back, front)
31
+ puts "device exited"
30
32
  back.close
31
33
  front.close
32
34
  end
@@ -34,12 +36,11 @@ module ZMQ
34
36
 
35
37
  def wait_for_device
36
38
  loop do
37
- can_break = false
38
- @mutex.synchronize do
39
- can_break = true if @device_thread
40
- end
39
+ can_break = @mutex.synchronize { @device_thread }
40
+
41
41
  break if can_break
42
42
  end
43
+ puts "broke out of wait_for_device loop"
43
44
  end
44
45
 
45
46
  it "should create a device without error given valid opts" do
@@ -61,17 +62,17 @@ module ZMQ
61
62
  end
62
63
 
63
64
  res = ''
64
- rc = puller.recv_string(res, ZMQ::NonBlocking)
65
- res.should == "hello"
65
+ rc = puller.recv_string(res, ZMQ::DONTWAIT)
66
+ expect(res).to eq("hello")
66
67
 
67
68
  pusher.close
68
69
  puller.close
69
70
  end
70
71
 
71
72
  it "should raise an ArgumentError when trying to pass non-socket objects into the device" do
72
- lambda {
73
- Device.new(ZMQ::STREAMER, 1,2)
74
- }.should raise_exception(ArgumentError)
73
+ expect {
74
+ Device.new(1,2)
75
+ }.to raise_exception(ArgumentError)
75
76
  end
76
77
  end
77
78
  end
data/spec/message_spec.rb CHANGED
@@ -9,12 +9,12 @@ module ZMQ
9
9
  context "when initializing with an argument" do
10
10
 
11
11
  it "calls zmq_msg_init_data()" do
12
- LibZMQ.should_receive(:zmq_msg_init_data)
12
+ expect(LibZMQ).to receive(:zmq_msg_init_data)
13
13
  message = Message.new "text"
14
14
  end
15
15
 
16
16
  it "should *not* define a finalizer on this object" do
17
- ObjectSpace.should_not_receive(:define_finalizer)
17
+ expect(ObjectSpace).not_to receive(:define_finalizer)
18
18
  Message.new "text"
19
19
  end
20
20
  end # context initializing with arg
@@ -22,12 +22,12 @@ module ZMQ
22
22
  context "when initializing *without* an argument" do
23
23
 
24
24
  it "calls zmq_msg_init()" do
25
- LibZMQ.should_receive(:zmq_msg_init).and_return(0)
25
+ expect(LibZMQ).to receive(:zmq_msg_init).and_return(0)
26
26
  message = Message.new
27
27
  end
28
28
 
29
29
  it "should *not* define a finalizer on this object" do
30
- ObjectSpace.should_not_receive(:define_finalizer)
30
+ expect(ObjectSpace).not_to receive(:define_finalizer)
31
31
  Message.new "text"
32
32
  end
33
33
  end # context initializing with arg
@@ -37,14 +37,14 @@ module ZMQ
37
37
  it "calls zmq_msg_init_data()" do
38
38
  message = Message.new "text"
39
39
 
40
- LibZMQ.should_receive(:zmq_msg_init_data)
40
+ expect(LibZMQ).to receive(:zmq_msg_init_data)
41
41
  message.copy_in_string("new text")
42
42
  end
43
43
 
44
44
  it "correctly finds the length of binary data by ignoring encoding" do
45
45
  message = Message.new
46
46
  message.copy_in_string("\x83\x6e\x04\x00\x00\x44\xd1\x81")
47
- message.size.should == 8
47
+ expect(message.size).to eq(8)
48
48
  end
49
49
  end
50
50
 
@@ -54,7 +54,7 @@ module ZMQ
54
54
  message = Message.new "text"
55
55
  copy = Message.new
56
56
 
57
- LibZMQ.should_receive(:zmq_msg_copy)
57
+ expect(LibZMQ).to receive(:zmq_msg_copy)
58
58
  copy.copy(message)
59
59
  end
60
60
  end # context copy
@@ -65,7 +65,7 @@ module ZMQ
65
65
  message = Message.new "text"
66
66
  copy = Message.new
67
67
 
68
- LibZMQ.should_receive(:zmq_msg_move)
68
+ expect(LibZMQ).to receive(:zmq_msg_move)
69
69
  copy.move(message)
70
70
  end
71
71
  end # context move
@@ -75,7 +75,7 @@ module ZMQ
75
75
  it "calls zmq_msg_size()" do
76
76
  message = Message.new "text"
77
77
 
78
- LibZMQ.should_receive(:zmq_msg_size)
78
+ expect(LibZMQ).to receive(:zmq_msg_size)
79
79
  message.size
80
80
  end
81
81
  end # context size
@@ -85,7 +85,7 @@ module ZMQ
85
85
  it "calls zmq_msg_data()" do
86
86
  message = Message.new "text"
87
87
 
88
- LibZMQ.should_receive(:zmq_msg_data)
88
+ expect(LibZMQ).to receive(:zmq_msg_data)
89
89
  message.data
90
90
  end
91
91
  end # context data
@@ -95,7 +95,7 @@ module ZMQ
95
95
  it "calls zmq_msg_close() the first time" do
96
96
  message = Message.new "text"
97
97
 
98
- LibZMQ.should_receive(:zmq_msg_close)
98
+ expect(LibZMQ).to receive(:zmq_msg_close)
99
99
  message.close
100
100
  end
101
101
 
@@ -103,7 +103,7 @@ module ZMQ
103
103
  message = Message.new "text"
104
104
  message.close
105
105
 
106
- LibZMQ.should_not_receive(:zmq_msg_close)
106
+ expect(LibZMQ).not_to receive(:zmq_msg_close)
107
107
  message.close
108
108
  end
109
109
  end # context close
@@ -116,7 +116,7 @@ module ZMQ
116
116
  context "when initializing with an argument" do
117
117
 
118
118
  it "should define a finalizer on this object" do
119
- ObjectSpace.should_receive(:define_finalizer)
119
+ expect(ObjectSpace).to receive(:define_finalizer)
120
120
  ManagedMessage.new "text"
121
121
  end
122
122
  end # context initializing
@@ -29,7 +29,7 @@ module ZMQ
29
29
  sleep 1
30
30
  strings = []
31
31
  rc = @receiver.recv_strings(strings)
32
- strings.should == data
32
+ expect(strings).to eq(data)
33
33
  end
34
34
  end
35
35
 
@@ -56,12 +56,12 @@ module ZMQ
56
56
  @req.send_strings(req_data)
57
57
  strings = []
58
58
  rc = @rep.recv_strings(strings)
59
- strings.should == req_data
59
+ expect(strings).to eq(req_data)
60
60
 
61
61
  @rep.send_strings(rep_data)
62
62
  strings = []
63
63
  rc = @req.recv_strings(strings)
64
- strings.should == rep_data
64
+ expect(strings).to eq(rep_data)
65
65
  end
66
66
 
67
67
  it "should be delivered between REQ and REP returning an array of messages" do
@@ -71,14 +71,14 @@ module ZMQ
71
71
  messages = []
72
72
  rc = @rep.recvmsgs(messages)
73
73
  messages.each_with_index do |message, index|
74
- message.copy_out_string.should == req_data[index]
74
+ expect(message.copy_out_string).to eq(req_data[index])
75
75
  end
76
76
 
77
77
  @rep.send_strings(rep_data)
78
78
  messages = []
79
79
  rc = @req.recvmsgs(messages)
80
80
  messages.each_with_index do |message, index|
81
- message.copy_out_string.should == rep_data[index]
81
+ expect(message.copy_out_string).to eq(rep_data[index])
82
82
  end
83
83
  end
84
84
  end
@@ -106,12 +106,12 @@ module ZMQ
106
106
  @req.send_string(req_data)
107
107
  strings = []
108
108
  rc = @rep.recv_strings(strings)
109
- strings.should == [ @req.identity, "", "hello" ]
109
+ expect(strings).to eq([ @req.identity, "", "hello" ])
110
110
 
111
111
  @rep.send_strings(rep_data)
112
112
  string = ''
113
113
  rc = @req.recv_string(string)
114
- string.should == rep_data.last
114
+ expect(string).to eq(rep_data.last)
115
115
  end
116
116
 
117
117
  it "should be delivered between REQ and REP returning an array of messages with an empty string as the envelope delimiter" do
@@ -120,14 +120,14 @@ module ZMQ
120
120
  @req.send_string(req_data)
121
121
  msgs = []
122
122
  rc = @rep.recvmsgs(msgs)
123
- msgs[0].copy_out_string.should == @req.identity
124
- msgs[1].copy_out_string.should == ""
125
- msgs[2].copy_out_string.should == "hello"
123
+ expect(msgs[0].copy_out_string).to eq(@req.identity)
124
+ expect(msgs[1].copy_out_string).to eq("")
125
+ expect(msgs[2].copy_out_string).to eq("hello")
126
126
 
127
127
  @rep.send_strings(rep_data)
128
128
  msgs = []
129
129
  rc = @req.recvmsgs(msgs)
130
- msgs[0].copy_out_string.should == rep_data.last
130
+ expect(msgs[0].copy_out_string).to eq(rep_data.last)
131
131
  end
132
132
  end
133
133