rbczmq 0.1
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.
- data/.gitignore +23 -0
- data/.travis.yml +19 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +19 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +247 -0
- data/Rakefile +67 -0
- data/examples/loop.rb +109 -0
- data/examples/poller.rb +37 -0
- data/examples/pub_sub.rb +101 -0
- data/examples/push_pull.rb +104 -0
- data/examples/req_rep.rb +100 -0
- data/ext/czmq.tar.gz +0 -0
- data/ext/rbczmq/context.c +280 -0
- data/ext/rbczmq/context.h +26 -0
- data/ext/rbczmq/extconf.rb +138 -0
- data/ext/rbczmq/frame.c +401 -0
- data/ext/rbczmq/frame.h +24 -0
- data/ext/rbczmq/jruby.h +22 -0
- data/ext/rbczmq/loop.c +413 -0
- data/ext/rbczmq/loop.h +24 -0
- data/ext/rbczmq/message.c +620 -0
- data/ext/rbczmq/message.h +24 -0
- data/ext/rbczmq/poller.c +308 -0
- data/ext/rbczmq/poller.h +29 -0
- data/ext/rbczmq/pollitem.c +251 -0
- data/ext/rbczmq/pollitem.h +25 -0
- data/ext/rbczmq/rbczmq_ext.c +198 -0
- data/ext/rbczmq/rbczmq_ext.h +94 -0
- data/ext/rbczmq/rbczmq_prelude.h +22 -0
- data/ext/rbczmq/rubinius.h +24 -0
- data/ext/rbczmq/ruby18.h +43 -0
- data/ext/rbczmq/ruby19.h +15 -0
- data/ext/rbczmq/socket.c +1570 -0
- data/ext/rbczmq/socket.h +136 -0
- data/ext/rbczmq/timer.c +110 -0
- data/ext/rbczmq/timer.h +23 -0
- data/ext/zeromq.tar.gz +0 -0
- data/lib/rbczmq.rb +3 -0
- data/lib/zmq.rb +77 -0
- data/lib/zmq/context.rb +50 -0
- data/lib/zmq/default_handler.rb +16 -0
- data/lib/zmq/frame.rb +11 -0
- data/lib/zmq/handler.rb +76 -0
- data/lib/zmq/loop.rb +131 -0
- data/lib/zmq/message.rb +9 -0
- data/lib/zmq/poller.rb +22 -0
- data/lib/zmq/pollitem.rb +31 -0
- data/lib/zmq/socket.rb +125 -0
- data/lib/zmq/socket/dealer.rb +33 -0
- data/lib/zmq/socket/pair.rb +39 -0
- data/lib/zmq/socket/pub.rb +30 -0
- data/lib/zmq/socket/pull.rb +29 -0
- data/lib/zmq/socket/push.rb +32 -0
- data/lib/zmq/socket/rep.rb +37 -0
- data/lib/zmq/socket/req.rb +37 -0
- data/lib/zmq/socket/router.rb +38 -0
- data/lib/zmq/socket/sub.rb +27 -0
- data/lib/zmq/timer.rb +12 -0
- data/lib/zmq/version.rb +5 -0
- data/perf/pair.rb +7 -0
- data/perf/pair/local.rb +22 -0
- data/perf/pair/remote.rb +25 -0
- data/perf/pub_sub.rb +7 -0
- data/perf/pub_sub/local.rb +22 -0
- data/perf/pub_sub/remote.rb +25 -0
- data/perf/push_pull.rb +7 -0
- data/perf/push_pull/local.rb +21 -0
- data/perf/push_pull/remote.rb +25 -0
- data/perf/req_rep.rb +7 -0
- data/perf/req_rep/local.rb +35 -0
- data/perf/req_rep/remote.rb +28 -0
- data/perf/runner.rb +142 -0
- data/rbczmq.gemspec +22 -0
- data/test/helper.rb +21 -0
- data/test/socket/test_dealer_socket.rb +14 -0
- data/test/socket/test_pair_socket.rb +24 -0
- data/test/socket/test_pair_sockets.rb +74 -0
- data/test/socket/test_pub_socket.rb +17 -0
- data/test/socket/test_pub_sub_sockets.rb +87 -0
- data/test/socket/test_pull_socket.rb +17 -0
- data/test/socket/test_push_pull_sockets.rb +81 -0
- data/test/socket/test_push_socket.rb +17 -0
- data/test/socket/test_rep_socket.rb +25 -0
- data/test/socket/test_req_rep_sockets.rb +42 -0
- data/test/socket/test_req_socket.rb +27 -0
- data/test/socket/test_router_socket.rb +14 -0
- data/test/socket/test_routing.rb +66 -0
- data/test/socket/test_sub_socket.rb +17 -0
- data/test/test_context.rb +86 -0
- data/test/test_frame.rb +78 -0
- data/test/test_handler.rb +28 -0
- data/test/test_loop.rb +252 -0
- data/test/test_message.rb +201 -0
- data/test/test_poller.rb +154 -0
- data/test/test_pollitem.rb +78 -0
- data/test/test_socket.rb +403 -0
- data/test/test_threading.rb +34 -0
- data/test/test_timer.rb +37 -0
- data/test/test_zmq.rb +62 -0
- metadata +208 -0
data/perf/runner.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.expand_path('lib')
|
4
|
+
require 'zmq'
|
5
|
+
|
6
|
+
class Runner
|
7
|
+
DEFAULT_MSG_COUNT = 100_000
|
8
|
+
DEFAULT_MSG_SIZE = 100
|
9
|
+
DEFAULT_ENCODING = :string
|
10
|
+
|
11
|
+
attr_reader :msg_count, :msg_size, :encoding, :workers_count, :stats_buf
|
12
|
+
|
13
|
+
def initialize(msg_count, msg_size, encoding, workers_count = 1)
|
14
|
+
@msg_count = (msg_count || DEFAULT_MSG_COUNT).to_i
|
15
|
+
@msg_size = (msg_size || DEFAULT_MSG_SIZE).to_i
|
16
|
+
@encoding = (encoding || DEFAULT_ENCODING).to_sym
|
17
|
+
@workers_count = (workers_count || 1).to_i
|
18
|
+
@stats_buf, @workers = [], []
|
19
|
+
register_signal_handlers
|
20
|
+
end
|
21
|
+
|
22
|
+
def start(test)
|
23
|
+
@workers_count.times{ fork_local(test) }
|
24
|
+
fork_remote(test)
|
25
|
+
puts "Workers: #{@workers.join(', ')}"
|
26
|
+
puts "Producer: #{@producer}"
|
27
|
+
after_start
|
28
|
+
ensure
|
29
|
+
stop
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_msg_count
|
33
|
+
msg_count / workers_count
|
34
|
+
end
|
35
|
+
|
36
|
+
def endpoint
|
37
|
+
self.class.const_get(:ENDPOINT)
|
38
|
+
end
|
39
|
+
|
40
|
+
def payload
|
41
|
+
@payload ||= "#{'0'*msg_size}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def stats(start_time)
|
45
|
+
end_time = Time.now
|
46
|
+
elapsed = (end_time.to_f - start_time.to_f) * 1000000
|
47
|
+
elapsed = 1 if elapsed == 0
|
48
|
+
|
49
|
+
throughput = process_msg_count * 1000000 / elapsed
|
50
|
+
megabits = throughput * msg_size * 8 / 1000000
|
51
|
+
stats_buf << "====== [#{Process.pid}] transfer stats ======"
|
52
|
+
stats_buf << "message encoding: %s" % encoding
|
53
|
+
stats_buf << "message size: %i [B]" % msg_size
|
54
|
+
stats_buf << "message count: %i" % process_msg_count
|
55
|
+
stats_buf << "mean throughput: %i [msg/s]" % throughput
|
56
|
+
stats_buf << "mean throughput: %.3f [Mb/s]" % megabits
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def register_signal_handlers
|
61
|
+
%w(INT TERM QUIT).each do |sig|
|
62
|
+
trap(sig){ stop }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def before_fork
|
67
|
+
sample_mem(:before)
|
68
|
+
end
|
69
|
+
|
70
|
+
def after_fork
|
71
|
+
sample_mem(:after)
|
72
|
+
stats_buf.each{|s| puts(s) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def sample_mem(w)
|
76
|
+
stats_buf << "[#{$$}] Memory used #{w}: %dkb" % `ps -o rss= -p #{$$}`.to_i
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class ProcessRunner < Runner
|
81
|
+
ENDPOINT = "tcp://127.0.0.1:5221"
|
82
|
+
|
83
|
+
def stop
|
84
|
+
Process.kill(:INT, @producer) rescue nil
|
85
|
+
@workers.each{|p| Process.kill(:INT, p) rescue nil }
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
def after_start
|
90
|
+
Process.waitpid(@producer, Process::WNOHANG)
|
91
|
+
@workers.each{|p| Process.waitpid(p) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def fork_local(test)
|
95
|
+
@workers << fork do
|
96
|
+
before_fork
|
97
|
+
require File.join(File.dirname(__FILE__), test.to_s, 'local')
|
98
|
+
after_fork
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def fork_remote(test)
|
103
|
+
@producer = fork do
|
104
|
+
before_fork
|
105
|
+
sleep 1
|
106
|
+
require File.join(File.dirname(__FILE__), test.to_s, 'remote')
|
107
|
+
after_fork
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class ThreadRunner < Runner
|
113
|
+
ENDPOINT = "inproc://perf"
|
114
|
+
|
115
|
+
def stop
|
116
|
+
@producer.kill rescue nil
|
117
|
+
@workers.each{|t| t.kill rescue nil }
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
def after_start
|
122
|
+
@producer.join
|
123
|
+
@workers.each{|t| t.join }
|
124
|
+
end
|
125
|
+
|
126
|
+
def fork_local(test)
|
127
|
+
@workers << Thread.new do
|
128
|
+
before_fork
|
129
|
+
require File.join(File.dirname(__FILE__), test.to_s, 'local')
|
130
|
+
after_fork
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def fork_remote(test)
|
135
|
+
@producer = Thread.new do
|
136
|
+
before_fork
|
137
|
+
sleep 1
|
138
|
+
require File.join(File.dirname(__FILE__), test.to_s, 'remote')
|
139
|
+
after_fork
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/rbczmq.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path('../lib/zmq/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rbczmq"
|
7
|
+
s.version = ZMQ::VERSION
|
8
|
+
s.summary = "Ruby extension for CZMQ - High-level C Binding for ØMQ (http://czmq.zeromq.org)"
|
9
|
+
s.description = "Ruby extension for CZMQ - High-level C Binding for ØMQ (http://czmq.zeromq.org)"
|
10
|
+
s.authors = ["Lourens Naudé", "James Tucker"]
|
11
|
+
s.email = ["lourens@methodmissing.com", "jftucker@gmail.com"]
|
12
|
+
s.homepage = "http://github.com/methodmissing/rbczmq"
|
13
|
+
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
14
|
+
s.platform = Gem::Platform::RUBY
|
15
|
+
s.extensions = "ext/rbczmq/extconf.rb"
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files test`.split("\n")
|
19
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.add_development_dependency('rake-compiler', '~> 0.8.0')
|
22
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'zmq'
|
5
|
+
require 'stringio'
|
6
|
+
|
7
|
+
Thread.abort_on_exception = true
|
8
|
+
|
9
|
+
class ZmqTestCase < Test::Unit::TestCase
|
10
|
+
undef_method :default_test if method_defined? :default_test
|
11
|
+
|
12
|
+
if ENV['STRESS_GC']
|
13
|
+
def setup
|
14
|
+
GC.stress = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
GC.stress = false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'helper')
|
4
|
+
|
5
|
+
class TestDealerSocket < ZmqTestCase
|
6
|
+
def test_behavior
|
7
|
+
ctx = ZMQ::Context.new
|
8
|
+
sock = ctx.socket(:DEALER)
|
9
|
+
assert_equal ZMQ::DEALER, sock.type
|
10
|
+
assert_equal "DEALER socket", sock.to_s
|
11
|
+
ensure
|
12
|
+
ctx.destroy
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'helper')
|
4
|
+
|
5
|
+
class TestPairSocket < ZmqTestCase
|
6
|
+
def test_behavior
|
7
|
+
ctx = ZMQ::Context.new
|
8
|
+
sock = ctx.socket(:PAIR)
|
9
|
+
assert_equal ZMQ::PAIR, sock.type
|
10
|
+
assert_equal "PAIR socket", sock.to_s
|
11
|
+
ensure
|
12
|
+
ctx.destroy
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_inproc_only_transport
|
16
|
+
ctx = ZMQ::Context.new
|
17
|
+
sock = ctx.socket(:PAIR)
|
18
|
+
assert_raises ZMQ::Error do
|
19
|
+
sock.bind("tcp://127.0.0.1:*")
|
20
|
+
end
|
21
|
+
ensure
|
22
|
+
ctx.destroy
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'helper')
|
4
|
+
|
5
|
+
class TestPairSockets < ZmqTestCase
|
6
|
+
def test_flow
|
7
|
+
ctx = ZMQ::Context.new
|
8
|
+
a = ctx.bind(:PAIR, "inproc://test.pair-flow")
|
9
|
+
b = ctx.connect(:PAIR, "inproc://test.pair-flow")
|
10
|
+
a.send("a")
|
11
|
+
b.send("b")
|
12
|
+
assert_equal "b", a.recv
|
13
|
+
assert_equal "a", b.recv
|
14
|
+
ensure
|
15
|
+
ctx.destroy
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_transfer
|
19
|
+
ctx = ZMQ::Context.new
|
20
|
+
a = ctx.bind(:PAIR, "inproc://test.pair-transfer")
|
21
|
+
b = ctx.connect(:PAIR, "inproc://test.pair-transfer")
|
22
|
+
a.send("message")
|
23
|
+
assert_equal "message", b.recv
|
24
|
+
|
25
|
+
a.sendm("me")
|
26
|
+
a.sendm("ss")
|
27
|
+
a.send("age")
|
28
|
+
assert_equal "me", b.recv
|
29
|
+
assert_equal "ss", b.recv
|
30
|
+
assert_equal "age", b.recv
|
31
|
+
|
32
|
+
a.send_frame ZMQ::Frame("frame")
|
33
|
+
assert_equal ZMQ::Frame("frame"), b.recv_frame
|
34
|
+
|
35
|
+
5.times do |i|
|
36
|
+
frame = ZMQ::Frame("m#{i}")
|
37
|
+
a.send_frame(frame, ZMQ::Frame::MORE)
|
38
|
+
end
|
39
|
+
a.send_frame(ZMQ::Frame("m5"))
|
40
|
+
expected, frames = %w(m0 m1 m2 m3 m4 m5), []
|
41
|
+
5.times do
|
42
|
+
frames << b.recv_frame.data
|
43
|
+
end
|
44
|
+
frames << b.recv_frame.data
|
45
|
+
assert_equal expected, frames
|
46
|
+
|
47
|
+
msg = ZMQ::Message.new
|
48
|
+
msg.push ZMQ::Frame("header")
|
49
|
+
|
50
|
+
assert_nil a.send_message(msg)
|
51
|
+
|
52
|
+
recvd_msg = b.recv_message
|
53
|
+
assert_instance_of ZMQ::Message, recvd_msg
|
54
|
+
assert_equal ZMQ::Frame("header"), recvd_msg.pop
|
55
|
+
ensure
|
56
|
+
ctx.destroy
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_distribution
|
60
|
+
ctx = ZMQ::Context.new
|
61
|
+
a = ctx.bind(:PAIR, "inproc://test.pair-distribution")
|
62
|
+
thread = Thread.new do
|
63
|
+
b = ctx.connect(:PAIR, "inproc://test.pair-distribution")
|
64
|
+
frame = b.recv_frame
|
65
|
+
b.close
|
66
|
+
frame
|
67
|
+
end
|
68
|
+
|
69
|
+
a.send_frame ZMQ::Frame("message")
|
70
|
+
assert_equal ZMQ::Frame("message"), thread.value
|
71
|
+
ensure
|
72
|
+
ctx.destroy
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'helper')
|
4
|
+
|
5
|
+
class TestPubSocket < ZmqTestCase
|
6
|
+
def test_behavior
|
7
|
+
ctx = ZMQ::Context.new
|
8
|
+
sock = ctx.socket(:PUB)
|
9
|
+
assert_equal ZMQ::PUB, sock.type
|
10
|
+
assert_equal "PUB socket", sock.to_s
|
11
|
+
assert_raises ZMQ::Error do
|
12
|
+
sock.recv
|
13
|
+
end
|
14
|
+
ensure
|
15
|
+
ctx.destroy
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'helper')
|
4
|
+
|
5
|
+
class TestPubSubSockets < ZmqTestCase
|
6
|
+
def test_flow
|
7
|
+
ctx = ZMQ::Context.new
|
8
|
+
pub = ctx.bind(:PUB, "inproc://test.pub-sub-flow")
|
9
|
+
sub = ctx.connect(:SUB, "inproc://test.pub-sub-flow")
|
10
|
+
sub.subscribe("")
|
11
|
+
pub.send("a")
|
12
|
+
assert_equal "a", sub.recv
|
13
|
+
ensure
|
14
|
+
ctx.destroy
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_transfer
|
18
|
+
ctx = ZMQ::Context.new
|
19
|
+
pub = ctx.bind(:PUB, "inproc://test.pub-sub-transfer")
|
20
|
+
sub = ctx.connect(:SUB, "inproc://test.pub-sub-transfer")
|
21
|
+
sub.subscribe("")
|
22
|
+
pub.send("message")
|
23
|
+
assert_equal "message", sub.recv
|
24
|
+
|
25
|
+
pub.sendm("me")
|
26
|
+
pub.sendm("ss")
|
27
|
+
pub.send("age")
|
28
|
+
assert_equal "me", sub.recv
|
29
|
+
assert_equal "ss", sub.recv
|
30
|
+
assert_equal "age", sub.recv
|
31
|
+
|
32
|
+
pub.send_frame ZMQ::Frame("frame")
|
33
|
+
assert_equal ZMQ::Frame("frame"), sub.recv_frame
|
34
|
+
|
35
|
+
5.times do |i|
|
36
|
+
frame = ZMQ::Frame("m#{i}")
|
37
|
+
pub.send_frame(frame, ZMQ::Frame::MORE)
|
38
|
+
end
|
39
|
+
pub.send_frame(ZMQ::Frame("m5"))
|
40
|
+
expected, frames = %w(m0 m1 m2 m3 m4 m5), []
|
41
|
+
5.times do
|
42
|
+
frames << sub.recv_frame.data
|
43
|
+
end
|
44
|
+
frames << sub.recv_frame.data
|
45
|
+
assert_equal expected, frames
|
46
|
+
|
47
|
+
msg = ZMQ::Message.new
|
48
|
+
msg.push ZMQ::Frame("header")
|
49
|
+
|
50
|
+
assert_nil pub.send_message(msg)
|
51
|
+
|
52
|
+
recvd_msg = sub.recv_message
|
53
|
+
assert_instance_of ZMQ::Message, recvd_msg
|
54
|
+
assert_equal ZMQ::Frame("header"), recvd_msg.pop
|
55
|
+
ensure
|
56
|
+
ctx.destroy
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_distribution
|
60
|
+
ctx = ZMQ::Context.new
|
61
|
+
pub = ctx.bind(:PUB, "inproc://test.pub-sub-distribution")
|
62
|
+
threads = []
|
63
|
+
5.times do |i|
|
64
|
+
threads << Thread.new do
|
65
|
+
sub = ctx.connect(:SUB, "inproc://test.pub-sub-distribution")
|
66
|
+
sub.subscribe("")
|
67
|
+
messages = []
|
68
|
+
5.times do
|
69
|
+
messages << sub.recv
|
70
|
+
end
|
71
|
+
sub.close
|
72
|
+
messages
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
sleep 0.5 # "slow joiner" syndrome
|
77
|
+
messages = %w(a b c d e)
|
78
|
+
messages.each do |m|
|
79
|
+
pub.send m
|
80
|
+
end
|
81
|
+
|
82
|
+
threads.each{|t| t.join }
|
83
|
+
assert threads.all?{|t| t.value == messages }
|
84
|
+
ensure
|
85
|
+
ctx.destroy
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'helper')
|
4
|
+
|
5
|
+
class TestPullSocket < ZmqTestCase
|
6
|
+
def test_behavior
|
7
|
+
ctx = ZMQ::Context.new
|
8
|
+
sock = ctx.socket(:PULL)
|
9
|
+
assert_equal ZMQ::PULL, sock.type
|
10
|
+
assert_equal "PULL socket", sock.to_s
|
11
|
+
assert_raises ZMQ::Error do
|
12
|
+
sock.send("message")
|
13
|
+
end
|
14
|
+
ensure
|
15
|
+
ctx.destroy
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'helper')
|
4
|
+
|
5
|
+
class TestPushPullSockets < ZmqTestCase
|
6
|
+
def test_flow
|
7
|
+
ctx = ZMQ::Context.new
|
8
|
+
push = ctx.bind(:PUSH, "inproc://test.push-pull-flow")
|
9
|
+
pull = ctx.connect(:PULL, "inproc://test.push-pull-flow")
|
10
|
+
push.send("a")
|
11
|
+
assert_equal "a", pull.recv
|
12
|
+
ensure
|
13
|
+
ctx.destroy
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_transfer
|
17
|
+
ctx = ZMQ::Context.new
|
18
|
+
push = ctx.bind(:PUSH, "inproc://test.push-pull-transfer")
|
19
|
+
pull = ctx.connect(:PULL, "inproc://test.push-pull-transfer")
|
20
|
+
push.send("message")
|
21
|
+
assert_equal "message", pull.recv
|
22
|
+
|
23
|
+
push.sendm("me")
|
24
|
+
push.sendm("ss")
|
25
|
+
push.send("age")
|
26
|
+
assert_equal "me", pull.recv
|
27
|
+
assert_equal "ss", pull.recv
|
28
|
+
assert_equal "age", pull.recv
|
29
|
+
|
30
|
+
push.send_frame ZMQ::Frame("frame")
|
31
|
+
assert_equal ZMQ::Frame("frame"), pull.recv_frame
|
32
|
+
|
33
|
+
5.times do |i|
|
34
|
+
frame = ZMQ::Frame("m#{i}")
|
35
|
+
push.send_frame(frame, ZMQ::Frame::MORE)
|
36
|
+
end
|
37
|
+
push.send_frame(ZMQ::Frame("m5"))
|
38
|
+
expected, frames = %w(m0 m1 m2 m3 m4 m5), []
|
39
|
+
5.times do
|
40
|
+
frames << pull.recv_frame.data
|
41
|
+
end
|
42
|
+
frames << pull.recv_frame.data
|
43
|
+
assert_equal expected, frames
|
44
|
+
|
45
|
+
msg = ZMQ::Message.new
|
46
|
+
msg.push ZMQ::Frame("header")
|
47
|
+
|
48
|
+
assert_nil push.send_message(msg)
|
49
|
+
|
50
|
+
recvd_msg = pull.recv_message
|
51
|
+
assert_instance_of ZMQ::Message, recvd_msg
|
52
|
+
assert_equal ZMQ::Frame("header"), recvd_msg.pop
|
53
|
+
ensure
|
54
|
+
ctx.destroy
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_distribution
|
58
|
+
ctx = ZMQ::Context.new
|
59
|
+
push = ctx.bind(:PUSH, "inproc://test.push-pull-distribution")
|
60
|
+
threads = []
|
61
|
+
5.times do |i|
|
62
|
+
threads << Thread.new do
|
63
|
+
pull = ctx.connect(:PULL, "inproc://test.push-pull-distribution")
|
64
|
+
msg = pull.recv
|
65
|
+
pull.close
|
66
|
+
msg
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
sleep 0.5 # "slow joiner" syndrome
|
71
|
+
messages = %w(a b c d e f)
|
72
|
+
messages.each do |m|
|
73
|
+
push.send m
|
74
|
+
end
|
75
|
+
|
76
|
+
threads.each{|t| t.join }
|
77
|
+
assert threads.all?{|t| messages.include?(t.value) }
|
78
|
+
ensure
|
79
|
+
ctx.destroy
|
80
|
+
end
|
81
|
+
end
|