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.
- checksums.yaml +7 -0
- data/.travis.yml +1 -1
- data/AUTHORS.txt +5 -1
- data/History.txt +45 -0
- data/README.rdoc +58 -28
- data/Rakefile +15 -0
- data/examples/README.rdoc +1 -3
- data/examples/{v3api/latency_measurement.rb → latency_measurement.rb} +1 -2
- data/examples/{v3api/local_lat.rb → local_lat.rb} +1 -1
- data/examples/{v3api/local_lat_poll.rb → local_lat_poll.rb} +4 -4
- data/examples/{v3api/local_throughput.rb → local_throughput.rb} +1 -1
- data/examples/{v3api/pub.rb → pub.rb} +1 -1
- data/examples/{v2api/publish_subscribe.rb → publish_subscribe.rb} +2 -2
- data/examples/{v2api/remote_lat.rb → remote_lat.rb} +1 -1
- data/examples/{v3api/remote_throughput.rb → remote_throughput.rb} +4 -3
- data/examples/repreq_over_curve.rb +60 -0
- data/examples/{v2api/reqrep_poll.rb → reqrep_poll.rb} +3 -4
- data/examples/{v2api/request_response.rb → request_response.rb} +1 -2
- data/examples/{v3api/sub.rb → sub.rb} +1 -2
- data/examples/{v3api/throughput_measurement.rb → throughput_measurement.rb} +1 -1
- data/examples/{v3api/xreqxrep_poll.rb → xreqxrep_poll.rb} +6 -7
- data/ffi-rzmq.gemspec +4 -4
- data/lib/ffi-rzmq.rb +2 -3
- data/lib/ffi-rzmq/context.rb +25 -53
- data/lib/ffi-rzmq/device.rb +8 -4
- data/lib/ffi-rzmq/exceptions.rb +3 -0
- data/lib/ffi-rzmq/message.rb +24 -30
- data/lib/ffi-rzmq/poll.rb +5 -16
- data/lib/ffi-rzmq/socket.rb +132 -282
- data/lib/ffi-rzmq/util.rb +28 -36
- data/lib/ffi-rzmq/version.rb +1 -1
- data/spec/context_spec.rb +18 -23
- data/spec/device_spec.rb +13 -12
- data/spec/message_spec.rb +13 -13
- data/spec/multipart_spec.rb +11 -11
- data/spec/nonblocking_recv_spec.rb +22 -22
- data/spec/poll_spec.rb +49 -49
- data/spec/pushpull_spec.rb +12 -11
- data/spec/reqrep_spec.rb +11 -11
- data/spec/socket_spec.rb +109 -196
- data/spec/spec_helper.rb +3 -11
- data/spec/util_spec.rb +29 -0
- metadata +80 -104
- data/examples/v2api/latency_measurement.rb +0 -139
- data/examples/v2api/local_lat.rb +0 -58
- data/examples/v2api/local_lat_poll.rb +0 -66
- data/examples/v2api/local_throughput.rb +0 -58
- data/examples/v2api/pub.rb +0 -46
- data/examples/v2api/remote_throughput.rb +0 -39
- data/examples/v2api/sub.rb +0 -74
- data/examples/v2api/throughput_measurement.rb +0 -138
- data/examples/v2api/xreqxrep_poll.rb +0 -93
- data/examples/v3api/publish_subscribe.rb +0 -82
- data/examples/v3api/remote_lat.rb +0 -71
- data/examples/v3api/reqrep_poll.rb +0 -62
- data/examples/v3api/request_response.rb +0 -40
- data/lib/ffi-rzmq/constants.rb +0 -187
- data/lib/ffi-rzmq/libc.rb +0 -19
- 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
|
-
|
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
|
-
|
102
|
-
|
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
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
|
data/lib/ffi-rzmq/version.rb
CHANGED
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).
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
-
|
89
|
-
|
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.
|
103
|
-
ctx.socket(ZMQ::REQ).
|
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(:
|
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(:
|
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
|
-
|
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 =
|
38
|
-
|
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::
|
65
|
-
res.
|
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
|
-
|
73
|
-
Device.new(
|
74
|
-
}.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
119
|
+
expect(ObjectSpace).to receive(:define_finalizer)
|
120
120
|
ManagedMessage.new "text"
|
121
121
|
end
|
122
122
|
end # context initializing
|
data/spec/multipart_spec.rb
CHANGED
@@ -29,7 +29,7 @@ module ZMQ
|
|
29
29
|
sleep 1
|
30
30
|
strings = []
|
31
31
|
rc = @receiver.recv_strings(strings)
|
32
|
-
strings.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
124
|
-
msgs[1].copy_out_string.
|
125
|
-
msgs[2].copy_out_string.
|
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.
|
130
|
+
expect(msgs[0].copy_out_string).to eq(rep_data.last)
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|