The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#
#	IPC::Mmap test script
#
use vars qw($tests $loaded);
BEGIN {
	push @INC, './t';
	$tests = 3;

	print STDERR "
 *** NOTE: this test may fail on older versions of Perl due to
 *** problems with the Win32 fork() emulation.
 "
 		if ($^O eq 'MSWin32');

	$^W= 1;
	$| = 1;
	print "1..$tests\n";
}

END {print "not ok 1\n" unless $loaded;}

#use threads;
#use threads::shared;
use Time::HiRes qw(time usleep);
use IPC::Mmap;

use strict;
use warnings;

our $testtype = 'single thread, multiprocess';
my $testno = 1;

sub report_result {
	my ($result, $testmsg, $okmsg, $notokmsg) = @_;

	if ($result) {

		$okmsg = '' unless $okmsg;
		print STDOUT (($result eq 'skip') ?
			"ok $testno # skip $testmsg for $testtype\n" :
			"ok $testno # $testmsg $okmsg for $testtype\n");
	}
	else {
		$notokmsg = '' unless $notokmsg;
		print STDOUT
			"not ok $testno # $testmsg $notokmsg for $testtype\n";
	}
	$testno++;
}

$loaded = 1;
#
#	create w/ filename, but wo/ a backing file
#	(works for both Win32 and POSIX)
#
sub create_mmap {
	my $mmap = ($^O eq 'MAWin32') ?
		IPC::Mmap->new('test2_mmap.tmp', 10000,
			PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON) :
		IPC::Mmap->new('test2_mmap.tmp', 10000,
			PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE);
	return $mmap;
}

my $mmap = create_mmap;
report_result(defined($mmap), 'create from filename');

unless (defined($mmap)) {
#	skip the rest
	report_result('skip', 'no mmap, skipping')
		while ($testno < $tests);
	exit 1;
}

#my $thrdlock : shared = 0;	# to coordinate threads
#
#	create 2 threads; 1st writes, 2nd reads
#	lock the mmap first to control sequencing
#
$mmap->lock();
my $writer = fork();

die "Can't fork writer" unless defined($writer);

unless ($writer) {
	write_mmap();
	exit 1;
}

$mmap->unlock();

#race condition - will the writer be always faster than the reader?
#let's give it a little time, say 10milliseconds
usleep(10000);

my $reader = fork();

die "Can't fork reader" unless defined($reader);

unless ($reader) {
	read_mmap();
	exit 1;
}

waitpid($writer, 0);
waitpid($reader, 0);

sub read_mmap {
	my $mmap = create_mmap;
	$mmap->lock();
	my $value;
	my $result = $mmap->read($value, 100, 2000);
	report_result((defined($result) && ($result == 2000) &&
		defined($value) && (length($value) == $result) &&
		($value eq ('K' x 2000))),
		'read thread', '', 'length of value: ' . length($value) .
			' value: ' . substr($value, 0, 20) );
	$mmap->unlock();

	sleep 3;
#
#	unpack something
#
	$mmap->lock();
	my @vals = $mmap->unpack(1000, 36, 'l n S d a20');
	report_result((scalar @vals == 5) &&
		($vals[0] == 123456) && ($vals[1] == 2345) && ($vals[2] == 5432) &&
		($vals[3] == 123.456789) && ($vals[4] eq ('Z' x 20)), 'unpack()');
	$mmap->unlock();

	return 1;
}

sub write_mmap {
#
#	no result report here, else Test harness will get confused
#
	my $mmap = create_mmap;
	my $result = $mmap->lock();
	$result = $mmap->write('K' x 2000, 100);
	$result = $mmap->unlock();

	sleep 2;
#
#	pack something
#
	$mmap->lock();
	$result = $mmap->pack(1000, 'l n S d a20', 123456, 2345, 5432, 123.456789, 'Z' x 20);
	$mmap->unlock();
#
#	Win32 needs some settle time before we close the mmap
#
	sleep 2;
#	$mmap->lock();
#	$mmap->unlock();

	return 1;
}