ffi-rzmq 1.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
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