1 ################################################################################
5 # $Date: 2008/11/28 18:08:11 +0100 $
7 ################################################################################
9 # Version 2.x, Copyright (C) 2007, Marcus Holland-Moritz <mhx@cpan.org>.
10 # Version 1.x, Copyright (C) 1999, Graham Barr <gbarr@pobox.com>.
12 # This program is free software; you can redistribute it and/or
13 # modify it under the same terms as Perl itself.
15 ################################################################################
18 require Test::More; import Test::More;
19 require Config; import Config;
21 if ($ENV{'PERL_CORE'} && $Config{'extensions'} !~ m[\bIPC/SysV\b]) {
22 plan(skip_all => 'IPC::SysV was not built');
26 if ($Config{'d_sem'} ne 'define') {
27 plan(skip_all => '$Config{d_sem} undefined');
29 elsif ($Config{'d_msg'} ne 'define') {
30 plan(skip_all => '$Config{d_msg} undefined');
35 # These constants are common to all tests.
36 # Later the sem* tests will import more for themselves.
38 use IPC::SysV qw(IPC_PRIVATE IPC_NOWAIT IPC_STAT IPC_RMID S_IRWXU);
46 return if $did_diag++;
48 if ($^O eq 'cygwin') {
51 It may be that the cygserver service isn't running.
55 diag(<<EOM) unless exists $ENV{CYGWIN} && $ENV{CYGWIN} eq 'server';
56 You also may have to set the CYGWIN environment variable
57 to 'server' before running the test suite:
66 It may be that your kernel does not have SysV IPC configured.
70 diag(<<EOM) if $^O eq 'freebsd';
71 You must have following options in your kernel:
85 my $SIGSYS_caught = 0;
92 return "$what failed: SIGSYS caught";
94 my $info = "$what failed: $why";
95 if ($why == &IPC::SysV::ENOSPC || $why == &IPC::SysV::ENOSYS ||
96 $why == &IPC::SysV::ENOMEM || $why == &IPC::SysV::EACCES) {
97 do_sys_diag() if $why == &IPC::SysV::ENOSYS;
106 if (exists $SIG{SYS}) {
107 local $SIG{SYS} = sub { $SIGSYS_caught++ };
114 # FreeBSD and cygwin are known to throw this if there's no SysV IPC
115 # in the kernel or the cygserver isn't running properly.
116 if (exists $SIG{SYS}) { # No SIGSYS with older perls...
119 diag('Bail out! SIGSYS caught');
128 my $N = do { my $foo = eval { pack "L!", 0 }; $@ ? '' : '!' };
131 skip('lacking d_msgget d_msgctl d_msgsnd d_msgrcv', 6) unless
132 $Config{'d_msgget'} eq 'define' &&
133 $Config{'d_msgctl'} eq 'define' &&
134 $Config{'d_msgsnd'} eq 'define' &&
135 $Config{'d_msgrcv'} eq 'define';
137 $msg = catchsig(sub { msgget(IPC_PRIVATE, $perm) });
139 # Very first time called after machine is booted value may be 0
140 unless (defined $msg && $msg >= 0) {
141 skip(skip_or_die('msgget', $!), 6);
144 pass('msgget IPC_PRIVATE S_IRWXU');
146 #Putting a message on the queue
148 my $msgtext = "hello";
154 $test_name = 'queue a message';
156 if (msgsnd($msg, pack("L$N a*", $msgtype, $msgtext), IPC_NOWAIT)) {
163 The failure of the subtest #2 may indicate that the message queue
164 resource limits either of the system or of the testing account
165 have been reached. Error message "Operating would block" is
166 usually indicative of this situation. The error message was now:
169 You can check the message queues with the 'ipcs' command and
170 you can remove unneeded queues with the 'ipcrm -q id' command.
171 You may also consider configuring your system or account
172 to have more message queue resources.
174 Because of the subtest #2 failing also the substests #5 and #6 will
175 very probably also fail.
180 ok(msgctl($msg, IPC_STAT, $data), 'msgctl IPC_STAT call');
182 cmp_ok(length($data), '>', 0, 'msgctl IPC_STAT data');
184 $test_name = 'message get call';
187 if (msgrcv($msg, $msgbuf, 256, 0, IPC_NOWAIT)) {
194 if ($test5bad && $test2bad) {
196 This failure was to be expected because the subtest #2 failed.
200 $test_name = 'message get data';
202 my($rmsgtype, $rmsgtext);
203 ($rmsgtype, $rmsgtext) = unpack("L$N a*", $msgbuf);
205 if ($rmsgtype == $msgtype && $rmsgtext eq $msgtext) {
213 if ($test6bad && $test2bad) {
215 This failure was to be expected because the subtest #2 failed.
223 skip('lacking d_semget d_semctl', 11) unless
224 $Config{'d_semget'} eq 'define' &&
225 $Config{'d_semctl'} eq 'define';
227 use IPC::SysV qw(IPC_CREAT GETALL SETALL);
229 # FreeBSD's default limit seems to be 9
232 $sem = catchsig(sub { semget(IPC_PRIVATE, $nsem, $perm | IPC_CREAT) });
234 # Very first time called after machine is booted value may be 0
235 unless (defined $sem && $sem >= 0) {
236 skip(skip_or_die('semget', $!), 11);
242 ok(semctl($sem, 0, IPC_STAT, $data), 'sem data call');
244 cmp_ok(length($data), '>', 0, 'sem data len');
246 ok(semctl($sem, 0, SETALL, pack("s$N*", (0) x $nsem)), 'set all sems');
249 ok(semctl($sem, 0, GETALL, $data), 'get all sems');
251 is(length($data), length(pack("s$N*", (0) x $nsem)), 'right length');
253 my @data = unpack("s$N*", $data);
255 my $adata = "0" x $nsem;
257 is(scalar(@data), $nsem, 'right amount');
258 cmp_ok(join("", @data), 'eq', $adata, 'right data');
263 ok(semctl($sem, 0, SETALL, pack("s$N*", @data)), 'poke it');
266 ok(semctl($sem, 0, GETALL, $data), 'and get it back');
268 @data = unpack("s$N*", $data);
269 my $bdata = "0" x $poke . "1" . "0" x ($nsem - $poke - 1);
271 cmp_ok(join("", @data), 'eq', $bdata, 'changed');
275 skip('lacking d_shm', 10) unless
276 $Config{'d_shm'} eq 'define';
278 use IPC::SysV qw(shmat shmdt memread memwrite ftok);
280 my $shm = catchsig(sub { shmget(IPC_PRIVATE, 4, S_IRWXU) });
282 # Very first time called after machine is booted value may be 0
283 unless (defined $shm && $shm >= 0) {
284 skip(skip_or_die('shmget', $!), 10);
289 ok(shmwrite($shm, pack("N", 0xdeadbeef), 0, 4), 'shmwrite(0xdeadbeef)');
291 my $addr = shmat($shm, undef, 0);
292 ok(defined $addr, 'shmat');
294 is(unpack("N", unpack("P4", $addr)), 0xdeadbeef, 'read shm by addr');
296 ok(defined shmctl($shm, IPC_RMID, 0), 'shmctl(IPC_RMID)');
299 ok(memread($addr, $var, 0, 4), 'memread($var)');
301 is(unpack("N", $var), 0xdeadbeef, 'read shm by memread');
303 ok(memwrite($addr, pack("N", 0xbadc0de5), 0, 4), 'memwrite(0xbadc0de5)');
305 is(unpack("N", unpack("P4", $addr)), 0xbadc0de5, 'read modified shm by addr');
307 ok(defined shmdt($addr), 'shmdt');
311 skip('lacking d_shm', 11) unless
312 $Config{'d_shm'} eq 'define';
314 use IPC::SysV qw(ftok);
316 my $key1i = ftok($0);
317 my $key1e = ftok($0, 1);
319 ok(defined $key1i, 'ftok implicit project id');
320 ok(defined $key1e, 'ftok explicit project id');
321 is($key1i, $key1e, 'keys match');
323 my $keyAsym = ftok($0, 'A');
324 my $keyAnum = ftok($0, ord('A'));
326 ok(defined $keyAsym, 'ftok symbolic project id');
327 ok(defined $keyAnum, 'ftok numeric project id');
328 is($keyAsym, $keyAnum, 'keys match');
331 my $key1 = ftok($0, 2);
332 my $key2 = ftok($0, ord('2'));
333 my $key3 = ftok($0, $two);
334 my $key4 = ftok($0, int($two));
336 is($key1, $key4, 'keys match');
337 isnt($key1, $key2, 'keys do not match');
338 is($key2, $key3, 'keys match');
340 eval { my $foo = ftok($0, 'AA') };
341 ok(index($@, 'invalid project id') >= 0, 'ftok error');
343 eval { my $foo = ftok($0, 3.14159) };
344 ok(index($@, 'invalid project id') >= 0, 'ftok error');
348 msgctl($msg, IPC_RMID, 0) if defined $msg;
349 semctl($sem, 0, IPC_RMID, 0) if defined $sem;