1 # -*- encoding: binary -*-
6 $stderr.sync = $stdout.sync = true
8 class Test_POSIX_MQ < Test::Unit::TestCase
10 POSIX_MQ.method_defined?(:to_io) or
11 warn "POSIX_MQ#to_io not supported on this platform: #{RUBY_PLATFORM}"
12 POSIX_MQ.method_defined?(:notify) or
13 warn "POSIX_MQ#notify not supported on this platform: #{RUBY_PLATFORM}"
17 @path = "/posix_mq.rb.#{Time.now.to_i}.#$$.#{rand}"
22 assert_equal @mq, @mq.unlink
28 def test_open_with_null_byte
29 assert_raises(ArgumentError) { POSIX_MQ.open("/hello\0world", :rw) }
32 def test_unlink_with_null_byte
33 assert_raises(ArgumentError) { POSIX_MQ.open("/hello\0world", :rw) }
37 assert_nothing_raised do
38 2025.times { POSIX_MQ.new(@path, :rw) }
39 2025.times { @mq = POSIX_MQ.new(@path, :rw); @mq.to_io }
41 end unless defined?RUBY_ENGINE && RUBY_ENGINE == "rbx"
43 def test_name_clobber_proof
44 @mq = POSIX_MQ.new(@path, :rw)
47 assert_nothing_raised { @mq.name.gsub!(/\A/, "foo") }
48 assert_equal tmp, @mq.name
49 assert tmp.object_id != @mq.name.object_id
53 @mq = POSIX_MQ.new(@path, :rw)
55 assert_equal @mq.object_id, dup.object_id
57 assert_equal @mq.object_id, clone.object_id
60 def test_timed_receive_float
62 @mq = POSIX_MQ.new(@path, :rw)
63 assert ! @mq.nonblock?
65 maybe_timeout { @mq.receive "", interval } or return
66 elapsed = Time.now - t0
67 assert elapsed > interval, elapsed.inspect
68 assert elapsed < 0.02, elapsed.inspect
71 def test_timed_receive_divmod
73 def interval.divmod(num)
74 num == 1 ? [ 0, 0.01 ] : nil
76 @mq = POSIX_MQ.new(@path, :rw)
77 assert ! @mq.nonblock?
79 maybe_timeout { @mq.receive "", interval } or return
80 elapsed = Time.now - t0
81 assert elapsed >= 0.01, elapsed.inspect
82 assert elapsed <= 0.02, elapsed.inspect
85 def test_timed_receive_fixnum
87 @mq = POSIX_MQ.new(@path, :rw)
88 assert ! @mq.nonblock?
90 maybe_timeout { @mq.receive "", interval } or return
91 elapsed = Time.now - t0
92 assert elapsed >= interval, elapsed.inspect
93 assert elapsed < 1.10, elapsed.inspect
98 @mq = POSIX_MQ.new(@path, :rw, 0666, POSIX_MQ::Attr[0, 1, 1, 0])
99 assert ! @mq.nonblock?
100 assert_nothing_raised {
102 @mq.send "A", 1, interval
103 rescue NotImplementedError
108 maybe_timeout { @mq.send "B", 1, interval } or return
109 elapsed = Time.now - t0
110 assert elapsed > interval
114 POSIX_MQ.open(@path, IO::CREAT|IO::WRONLY, 0666) do |mq|
116 assert mq.kind_of?(POSIX_MQ)
117 assert_equal @path, mq.name
118 assert_nil mq.send("HI", 0)
119 assert_equal 1, mq.attr.curmsgs
121 assert_raises(IOError) { mq.close }
125 POSIX_MQ.unlink(@path)
129 path = "" << @path.dup
131 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
132 assert_equal path, @mq.name
135 def test_new_readonly
136 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
137 rd = POSIX_MQ.new @path, IO::RDONLY
138 assert_equal @mq.name, rd.name
142 def test_send0_receive
143 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
144 assert_equal(@mq, @mq << "hello")
145 assert_equal [ "hello", 0 ], @mq.receive
149 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
150 @mq << "hello" << "world"
151 assert_equal [ "hello", 0 ], @mq.receive
152 assert_equal [ "world", 0 ], @mq.receive
156 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
158 assert_equal "hello", @mq.shift
163 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
165 assert_equal "hello", @mq.shift(buf)
166 assert_equal "hello", buf
169 def test_send_receive
170 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
171 assert_nil @mq.send("hello", 0)
172 assert_equal [ "hello", 0 ], @mq.receive
175 def test_send_receive_buf
177 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
178 assert_nil @mq.send("hello", 0)
179 assert_equal [ "hello", 0 ], @mq.receive(buf)
180 assert_equal "hello", buf
183 def test_send_receive_prio
184 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
185 assert_nil @mq.send("hello", 2)
186 assert_equal [ "hello", 2 ], @mq.receive
190 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
192 assert_equal POSIX_MQ::Attr, mq_attr.class
193 assert mq_attr.flags.kind_of?(Integer)
194 assert mq_attr.maxmsg.kind_of?(Integer)
195 assert mq_attr.msgsize.kind_of?(Integer)
196 assert mq_attr.curmsgs.kind_of?(Integer)
200 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
201 assert @mq.to_io.kind_of?(IO)
202 assert_nothing_raised { IO.select([@mq], nil, nil, 0) }
203 end if POSIX_MQ.method_defined?(:to_io)
207 orig = trap(:USR1) { wr.syswrite('.') }
208 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
209 assert_nothing_raised { @mq.notify = :SIGUSR1 }
210 assert_nothing_raised { @mq.send("hello", 0) }
211 assert_equal [[rd], [], []], IO.select([rd], nil, nil, 10)
212 assert_equal '.', rd.sysread(1)
213 assert_nil(@mq.notify = nil)
214 assert_nothing_raised { @mq.send("hello", 0) }
215 assert_nil IO.select([rd], nil, nil, 0.1)
221 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
222 assert_nothing_raised { @mq.notify = false }
233 _, status = Process.waitpid2(pid)
234 assert status.success?, status.inspect
238 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
239 mq_attr = POSIX_MQ::Attr.new(IO::NONBLOCK)
241 assert_equal IO::NONBLOCK, @mq.attr.flags
242 assert mq_attr.flags.kind_of?(Integer)
246 assert_equal 0, @mq.attr.flags
249 def test_new_nonblocking
250 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY|IO::NONBLOCK, 0666
254 def test_new_blocking
255 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
256 assert ! @mq.nonblock?
259 def test_nonblock_toggle
260 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
261 assert ! @mq.nonblock?
265 assert ! @mq.nonblock?
266 assert_raises(ArgumentError) { @mq.nonblock = nil }
270 @mq = POSIX_MQ.new @path, :w
271 assert_equal IO::WRONLY, @mq.to_io.fcntl(Fcntl::F_GETFL)
272 end if POSIX_MQ.method_defined?(:to_io)
275 @mq = POSIX_MQ.new @path, :w
277 assert_nothing_raised { mq = POSIX_MQ.new @path, :r }
278 assert_equal IO::RDONLY, mq.to_io.fcntl(Fcntl::F_GETFL)
280 end if POSIX_MQ.method_defined?(:to_io)
282 def test_new_path_only
283 @mq = POSIX_MQ.new @path, :w
285 assert_nothing_raised { mq = POSIX_MQ.new @path }
286 assert_equal IO::RDONLY, mq.to_io.fcntl(Fcntl::F_GETFL)
288 end if POSIX_MQ.method_defined?(:to_io)
291 @mq = POSIX_MQ.new @path, :rw
292 assert_equal IO::RDWR, @mq.to_io.fcntl(Fcntl::F_GETFL)
293 end if POSIX_MQ.method_defined?(:to_io)
296 mq_attr = POSIX_MQ::Attr.new(IO::NONBLOCK, 1, 1, 0)
297 @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666, mq_attr
299 assert_equal mq_attr, @mq.attr
301 assert_raises(Errno::EAGAIN) { @mq.receive }
302 assert_raises(Errno::EMSGSIZE) { @mq << '..' }
303 assert_nothing_raised { @mq << '.' }
304 assert_equal [ '.', 0 ], @mq.receive
305 assert_nothing_raised { @mq << '.' }
306 assert_raises(Errno::EAGAIN) { @mq << '.' }
310 min_posix_mq_prio_max = 31 # defined by POSIX
311 assert POSIX_MQ::PRIO_MAX >= min_posix_mq_prio_max
315 assert POSIX_MQ::OPEN_MAX.kind_of?(Integer)
318 def test_notify_block_replace
320 @mq = POSIX_MQ.new(@path, :rw)
321 assert_nothing_raised { @mq.notify { |mq| q << mq } }
322 assert_nothing_raised { Process.waitpid2(fork { @mq << "hi" }) }
323 assert_equal @mq.object_id, q.pop.object_id
324 assert_equal "hi", @mq.receive.first
325 assert_nothing_raised { @mq.notify { |mq| q << "hi" } }
326 assert_nothing_raised { Process.waitpid2(fork { @mq << "bye" }) }
327 assert_equal "hi", q.pop
328 end if POSIX_MQ.method_defined?(:notify)
330 def test_notify_thread
332 @mq = POSIX_MQ.new(@path, :rw)
333 @mq.notify { |mq| q << Thread.current }
336 assert x.instance_of?(Thread)
337 assert Thread.current != x
338 end if POSIX_MQ.method_defined?(:notify)
340 def test_bad_open_mode
341 assert_raises(ArgumentError) { mq = POSIX_MQ.new(@path, "rw") }
344 def test_bad_open_attr
345 assert_raises(TypeError) { POSIX_MQ.new(@path, :rw, 0666, [0, 1, 1, 0]) }
349 @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
350 assert_raises(TypeError) { @mq.attr = {} }
351 assert_raises(TypeError) { @mq.attr = Struct.new(:a,:b,:c,:d).new }
356 assert_raises(exc) { } # FAIL
358 rescue Errno::ETIMEDOUT => e
360 rescue NotImplementedError => e