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 if ($ENV{'PERL_CORE'}) {
20 @INC = '../lib' if -d '../lib' && -d '../ext';
23 require Test::More; import Test::More;
24 require Config; import Config;
26 if ($ENV{'PERL_CORE'} && $Config{'extensions'} !~ m[\bIPC/SysV\b]) {
27 plan(skip_all => 'IPC::SysV was not built');
31 if ($Config{'d_sem'} ne 'define') {
32 plan(skip_all => '$Config{d_sem} undefined');
34 elsif ($Config{'d_msg'} ne 'define') {
35 plan(skip_all => '$Config{d_msg} undefined');
40 # These constants are common to all tests.
41 # Later the sem* tests will import more for themselves.
43 use IPC::SysV qw(IPC_PRIVATE IPC_NOWAIT IPC_STAT IPC_RMID S_IRWXU);
51 return if $did_diag++;
53 if ($^O eq 'cygwin') {
56 It may be that the cygserver service isn't running.
60 diag(<<EOM) unless exists $ENV{CYGWIN} && $ENV{CYGWIN} eq 'server';
61 You also may have to set the CYGWIN environment variable
62 to 'server' before running the test suite:
71 It may be that your kernel does not have SysV IPC configured.
75 diag(<<EOM) if $^O eq 'freebsd';
76 You must have following options in your kernel:
90 my $SIGSYS_caught = 0;
97 return "$what failed: SIGSYS caught";
99 my $info = "$what failed: $why";
100 if ($why == &IPC::SysV::ENOSPC || $why == &IPC::SysV::ENOSYS ||
101 $why == &IPC::SysV::ENOMEM || $why == &IPC::SysV::EACCES) {
102 do_sys_diag() if $why == &IPC::SysV::ENOSYS;
111 if (exists $SIG{SYS}) {
112 local $SIG{SYS} = sub { $SIGSYS_caught++ };
119 # FreeBSD and cygwin are known to throw this if there's no SysV IPC
120 # in the kernel or the cygserver isn't running properly.
121 if (exists $SIG{SYS}) { # No SIGSYS with older perls...
124 diag('Bail out! SIGSYS caught');
133 my $N = do { my $foo = eval { pack "L!", 0 }; $@ ? '' : '!' };
136 skip('lacking d_msgget d_msgctl d_msgsnd d_msgrcv', 6) unless
137 $Config{'d_msgget'} eq 'define' &&
138 $Config{'d_msgctl'} eq 'define' &&
139 $Config{'d_msgsnd'} eq 'define' &&
140 $Config{'d_msgrcv'} eq 'define';
142 $msg = catchsig(sub { msgget(IPC_PRIVATE, $perm) });
144 # Very first time called after machine is booted value may be 0
145 unless (defined $msg && $msg >= 0) {
146 skip(skip_or_die('msgget', $!), 6);
149 pass('msgget IPC_PRIVATE S_IRWXU');
151 #Putting a message on the queue
153 my $msgtext = "hello";
159 $test_name = 'queue a message';
161 if (msgsnd($msg, pack("L$N a*", $msgtype, $msgtext), IPC_NOWAIT)) {
168 The failure of the subtest #2 may indicate that the message queue
169 resource limits either of the system or of the testing account
170 have been reached. Error message "Operating would block" is
171 usually indicative of this situation. The error message was now:
174 You can check the message queues with the 'ipcs' command and
175 you can remove unneeded queues with the 'ipcrm -q id' command.
176 You may also consider configuring your system or account
177 to have more message queue resources.
179 Because of the subtest #2 failing also the substests #5 and #6 will
180 very probably also fail.
185 ok(msgctl($msg, IPC_STAT, $data), 'msgctl IPC_STAT call');
187 cmp_ok(length($data), '>', 0, 'msgctl IPC_STAT data');
189 $test_name = 'message get call';
192 if (msgrcv($msg, $msgbuf, 256, 0, IPC_NOWAIT)) {
199 if ($test5bad && $test2bad) {
201 This failure was to be expected because the subtest #2 failed.
205 $test_name = 'message get data';
207 my($rmsgtype, $rmsgtext);
208 ($rmsgtype, $rmsgtext) = unpack("L$N a*", $msgbuf);
210 if ($rmsgtype == $msgtype && $rmsgtext eq $msgtext) {
218 if ($test6bad && $test2bad) {
220 This failure was to be expected because the subtest #2 failed.
228 skip('lacking d_semget d_semctl', 11) unless
229 $Config{'d_semget'} eq 'define' &&
230 $Config{'d_semctl'} eq 'define';
232 use IPC::SysV qw(IPC_CREAT GETALL SETALL);
234 # FreeBSD's default limit seems to be 9
237 $sem = catchsig(sub { semget(IPC_PRIVATE, $nsem, $perm | IPC_CREAT) });
239 # Very first time called after machine is booted value may be 0
240 unless (defined $sem && $sem >= 0) {
241 skip(skip_or_die('semget', $!), 11);
247 ok(semctl($sem, 0, IPC_STAT, $data), 'sem data call');
249 cmp_ok(length($data), '>', 0, 'sem data len');
251 ok(semctl($sem, 0, SETALL, pack("s$N*", (0) x $nsem)), 'set all sems');
254 ok(semctl($sem, 0, GETALL, $data), 'get all sems');
256 is(length($data), length(pack("s$N*", (0) x $nsem)), 'right length');
258 my @data = unpack("s$N*", $data);
260 my $adata = "0" x $nsem;
262 is(scalar(@data), $nsem, 'right amount');
263 cmp_ok(join("", @data), 'eq', $adata, 'right data');
268 ok(semctl($sem, 0, SETALL, pack("s$N*", @data)), 'poke it');
271 ok(semctl($sem, 0, GETALL, $data), 'and get it back');
273 @data = unpack("s$N*", $data);
274 my $bdata = "0" x $poke . "1" . "0" x ($nsem - $poke - 1);
276 cmp_ok(join("", @data), 'eq', $bdata, 'changed');
280 skip('lacking d_shm', 10) unless
281 $Config{'d_shm'} eq 'define';
283 use IPC::SysV qw(shmat shmdt memread memwrite ftok);
285 my $shm = catchsig(sub { shmget(IPC_PRIVATE, 4, S_IRWXU) });
287 # Very first time called after machine is booted value may be 0
288 unless (defined $shm && $shm >= 0) {
289 skip(skip_or_die('shmget', $!), 10);
294 ok(shmwrite($shm, pack("N", 0xdeadbeef), 0, 4), 'shmwrite(0xdeadbeef)');
296 my $addr = shmat($shm, undef, 0);
297 ok(defined $addr, 'shmat');
299 is(unpack("N", unpack("P4", $addr)), 0xdeadbeef, 'read shm by addr');
301 ok(defined shmctl($shm, IPC_RMID, 0), 'shmctl(IPC_RMID)');
304 ok(memread($addr, $var, 0, 4), 'memread($var)');
306 is(unpack("N", $var), 0xdeadbeef, 'read shm by memread');
308 ok(memwrite($addr, pack("N", 0xbadc0de5), 0, 4), 'memwrite(0xbadc0de5)');
310 is(unpack("N", unpack("P4", $addr)), 0xbadc0de5, 'read modified shm by addr');
312 ok(defined shmdt($addr), 'shmdt');
316 skip('lacking d_shm', 11) unless
317 $Config{'d_shm'} eq 'define';
319 use IPC::SysV qw(ftok);
321 my $key1i = ftok($0);
322 my $key1e = ftok($0, 1);
324 ok(defined $key1i, 'ftok implicit project id');
325 ok(defined $key1e, 'ftok explicit project id');
326 is($key1i, $key1e, 'keys match');
328 my $keyAsym = ftok($0, 'A');
329 my $keyAnum = ftok($0, ord('A'));
331 ok(defined $keyAsym, 'ftok symbolic project id');
332 ok(defined $keyAnum, 'ftok numeric project id');
333 is($keyAsym, $keyAnum, 'keys match');
336 my $key1 = ftok($0, 2);
337 my $key2 = ftok($0, ord('2'));
338 my $key3 = ftok($0, $two);
339 my $key4 = ftok($0, int($two));
341 is($key1, $key4, 'keys match');
342 isnt($key1, $key2, 'keys do not match');
343 is($key2, $key3, 'keys match');
345 eval { my $foo = ftok($0, 'AA') };
346 ok(index($@, 'invalid project id') >= 0, 'ftok error');
348 eval { my $foo = ftok($0, 3.14159) };
349 ok(index($@, 'invalid project id') >= 0, 'ftok error');
353 msgctl($msg, IPC_RMID, 0) if defined $msg;
354 semctl($sem, 0, IPC_RMID, 0) if defined $sem;