use strict; use warnings; use Test::More tests => 10; use Test::NoWarnings; use Fcntl qw( ); use File::Temp qw( tmpnam ); use lib './lib'; use File::Util qw( SL NL OS ); my $f = File::Util->new( { onfail => 'zero' } ); my ( $tfh, $tmpf ) = tmpnam(); close $tfh; # I didn't want it opened! unlink $tmpf; # ^^ our auto-flock won't work on duped FH my $have_flock = sub { local $@; eval { flock( STDIN, &Fcntl::LOCK_SH ); flock( STDIN, &Fcntl::LOCK_UN ); }; return $@ ? 0 : 1; }->(); my $have_perms = $f->is_writable( $f->return_path( $tmpf ) ); SKIP: { if ( !$have_flock ) { skip 'Your system cannot flock' => 9; } elsif ( !$have_perms ) { skip 'Insufficient permissions' => 9; } elsif ( $^O =~ /solaris|sunos/i ) { skip 'Solaris flock has issues' => 9; } ok $f->can_flock( ) == $have_flock, 'File::Util correctly detects flock() support'; # flock-ing usage toggles ok $f->use_flock( ) == 1, 'test flock on' ; # test 1 ok $f->use_flock(1) == 1, 'test on toggle' ; # test 2 ok $f->use_flock(0) == 0, 'test off toggle' ; # test 3 ok $f->use_flock( ) == 0, 'test toggled off' ; # test 4 ok $f->use_flock(1) == 1, 'test toggle back on' ; # test 5 # get/set flock-ing failure policy ok( # test 6 join( ' ', $f->flock_rules() ) eq 'NOBLOCKEX FAIL', 'expecting ' . join( ' ', $f->flock_rules() ) ); ok( # test 7 join( ' ', $f->flock_rules( qw/ NOBLOCKEX ZERO / ) ) eq 'NOBLOCKEX ZERO', 'expecting ' . join( ' ', $f->flock_rules( qw/ NOBLOCKEX ZERO / ) ) ); # actual flock test is fight_for_lock(), 'failed correctly', 'contending flock OPs must fail' ; # test 8 last; my $fh = $f->open_handle ( $tmpf, 'write' => { onfail => warn => diag => 1 } ); is $f->unlock_open_handle ( $fh => { onfail => warn => diag => 1 } ), 1, 'File::Util can un-flock OK'; close $fh; } unlink $tmpf; exit; # put flock to the "test" sub fight_for_lock { $f->flock_rules( qw( NOBLOCKEX FAIL ) ); # auto-locks file, keep open handle on it my $fh = $f->open_handle( $tmpf => 'write' ); # this should fail, and return a "0" instead of a filehandle return $f->open_handle ( $tmpf => write => { onfail => sub { 'failed correctly' } } ); }