posix_mq 0.2.0
[ruby_posix_mq.git] / test / test_posix_mq.rb
blobdccc54726eca340b9312608455418c088b373584
1 # -*- encoding: binary -*-
2 require 'test/unit'
3 require 'posix_mq'
4 require 'fcntl'
5 $stderr.sync = $stdout.sync = true
7 class Test_POSIX_MQ < Test::Unit::TestCase
9   HAVE_TO_IO = if POSIX_MQ.instance_methods.grep(/\Ato_io\z/).empty?
10     warn "POSIX_MQ#to_io not supported on this platform: #{RUBY_PLATFORM}"
11     false
12   else
13     true
14   end
16   def setup
17     @mq = nil
18     @path = "/posix_mq.rb.#{Time.now.to_i}.#$$.#{rand}"
19   end
21   def teardown
22     @mq or return
23     assert_equal @mq, @mq.unlink
24     assert ! @mq.closed?
25     assert_nil @mq.close
26     assert @mq.closed?
27   end
29   def test_timed_receive
30     interval = 0.01
31     @mq = POSIX_MQ.new(@path, :rw)
32     assert ! @mq.nonblock?
33     t0 = Time.now
34     assert_raises(Errno::ETIMEDOUT) { @mq.receive "", interval }
35     elapsed = Time.now - t0
36     assert elapsed > interval
37   end
39   def test_timed_send
40     interval = 0.01
41     @mq = POSIX_MQ.new(@path, :rw, 0666, POSIX_MQ::Attr[0, 1, 1, 0])
42     assert ! @mq.nonblock?
43     assert_nothing_raised { @mq.send "A", 1, interval }
44     t0 = Time.now
45     assert_raises(Errno::ETIMEDOUT) { @mq.send "B", 1, interval }
46     elapsed = Time.now - t0
47     assert elapsed > interval
48   end
50   def test_open
51     POSIX_MQ.open(@path, IO::CREAT|IO::WRONLY, 0666) do |mq|
52       @mq = mq
53       assert mq.kind_of?(POSIX_MQ)
54       assert_equal @path, mq.name
55       assert_nil mq.send("HI", 0)
56       assert_equal 1, mq.attr.curmsgs
57       assert_nil mq.close
58       assert_raises(IOError) { mq.close }
59     end
60     assert @mq.closed?
61     @mq = nil
62     POSIX_MQ.unlink(@path)
63   end
65   def test_name
66     path = "" << @path.dup
67     path.freeze
68     @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
69     assert_equal path, @mq.name
70   end
72   def test_new_readonly
73     @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
74     rd = POSIX_MQ.new @path, IO::RDONLY
75     assert_equal @mq.name, rd.name
76     assert_nil rd.close
77   end
79   def test_send0_receive
80     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
81     assert_equal(@mq, @mq << "hello")
82     assert_equal [ "hello", 0 ], @mq.receive
83   end
85   def test_send0_chain
86     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
87     @mq << "hello" << "world"
88     assert_equal [ "hello", 0 ], @mq.receive
89     assert_equal [ "world", 0 ], @mq.receive
90   end
92   def test_send_receive
93     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
94     assert_nil @mq.send("hello", 0)
95     assert_equal [ "hello", 0 ], @mq.receive
96   end
98   def test_send_receive_buf
99     buf = ""
100     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
101     assert_nil @mq.send("hello", 0)
102     assert_equal [ "hello", 0 ], @mq.receive(buf)
103     assert_equal "hello", buf
104   end
106   def test_send_receive_prio
107     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
108     assert_nil @mq.send("hello", 2)
109     assert_equal [ "hello", 2 ], @mq.receive
110   end
112   def test_getattr
113     @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
114     mq_attr = @mq.attr
115     assert_equal POSIX_MQ::Attr, mq_attr.class
116     assert mq_attr.flags.kind_of?(Integer)
117     assert mq_attr.maxmsg.kind_of?(Integer)
118     assert mq_attr.msgsize.kind_of?(Integer)
119     assert mq_attr.curmsgs.kind_of?(Integer)
120   end
122   def test_to_io
123     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
124     assert @mq.to_io.kind_of?(IO)
125     assert_nothing_raised { IO.select([@mq], nil, nil, 0) }
126   end if HAVE_TO_IO
128   def test_notify
129     rd, wr = IO.pipe
130     orig = trap(:USR1) { wr.syswrite('.') }
131     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
132     assert_nothing_raised { @mq.notify = :SIGUSR1 }
133     assert_nothing_raised { @mq.send("hello", 0) }
134     assert_equal [[rd], [], []], IO.select([rd], nil, nil, 10)
135     assert_equal '.', rd.sysread(1)
136     assert_nil(@mq.notify = nil)
137     assert_nothing_raised { @mq.send("hello", 0) }
138     assert_nil IO.select([rd], nil, nil, 0.1)
139     ensure
140       trap(:USR1, orig)
141   end
143   def test_notify_none
144     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
145     assert_nothing_raised { @mq.notify = false }
146     pid = fork do
147       begin
148         @mq.notify = :USR1
149       rescue Errno::EBUSY
150         exit 0
151       rescue => e
152         p e
153       end
154       exit! 1
155     end
156     _, status = Process.waitpid2(pid)
157     assert status.success?, status.inspect
158   end
160   def test_setattr
161     @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
162     mq_attr = POSIX_MQ::Attr.new(IO::NONBLOCK)
163     @mq.attr = mq_attr
164     assert_equal IO::NONBLOCK, @mq.attr.flags
165     assert mq_attr.flags.kind_of?(Integer)
167     mq_attr.flags = 0
168     @mq.attr = mq_attr
169     assert_equal 0, @mq.attr.flags
170   end
172   def test_new_nonblocking
173     @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY|IO::NONBLOCK, 0666
174     assert @mq.nonblock?
175   end
177   def test_new_blocking
178     @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
179     assert ! @mq.nonblock?
180   end
182   def test_nonblock_toggle
183     @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
184     assert ! @mq.nonblock?
185     @mq.nonblock = true
186     assert @mq.nonblock?
187     @mq.nonblock = false
188     assert ! @mq.nonblock?
189     assert_raises(ArgumentError) { @mq.nonblock = nil }
190   end
192   def test_new_sym_w
193     @mq = POSIX_MQ.new @path, :w
194     assert_equal IO::WRONLY, @mq.to_io.fcntl(Fcntl::F_GETFL)
195   end if HAVE_TO_IO
197   def test_new_sym_r
198     @mq = POSIX_MQ.new @path, :w
199     mq = nil
200     assert_nothing_raised { mq = POSIX_MQ.new @path, :r }
201     assert_equal IO::RDONLY, mq.to_io.fcntl(Fcntl::F_GETFL)
202     assert_nil mq.close
203   end if HAVE_TO_IO
205   def test_new_path_only
206     @mq = POSIX_MQ.new @path, :w
207     mq = nil
208     assert_nothing_raised { mq = POSIX_MQ.new @path }
209     assert_equal IO::RDONLY, mq.to_io.fcntl(Fcntl::F_GETFL)
210     assert_nil mq.close
211   end if HAVE_TO_IO
213   def test_new_sym_wr
214     @mq = POSIX_MQ.new @path, :rw
215     assert_equal IO::RDWR, @mq.to_io.fcntl(Fcntl::F_GETFL)
216   end if HAVE_TO_IO
218   def test_new_attr
219     mq_attr = POSIX_MQ::Attr.new(IO::NONBLOCK, 1, 1, 0)
220     @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666, mq_attr
221     assert @mq.nonblock?
222     assert_equal mq_attr, @mq.attr
224     assert_raises(Errno::EAGAIN) { @mq.receive }
225     assert_raises(Errno::EMSGSIZE) { @mq << '..' }
226     assert_nothing_raised { @mq << '.' }
227     assert_equal [ '.', 0 ], @mq.receive
228     assert_nothing_raised { @mq << '.' }
229     assert_raises(Errno::EAGAIN) { @mq << '.' }
230   end
232   def test_prio_max
233     min_posix_mq_prio_max = 31 # defined by POSIX
234     assert POSIX_MQ::PRIO_MAX >= min_posix_mq_prio_max
235   end
237   def test_open_max
238     assert POSIX_MQ::OPEN_MAX.kind_of?(Integer)
239   end