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