5
0
mirror of git://git.proxmox.com/git/pve-common.git synced 2024-12-22 21:33:47 +03:00
pve-common/test/lock_file.pl
Fiona Ebner 903d285751 test: have lock file test use run_fork() helper
There are differences for error handling in the old and new helper, in
particular when the child is signaled. But the test here does not
explicitly check for specific error conditions or messages and is
therefore still correct with the new helper.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2024-11-14 20:44:53 +01:00

126 lines
2.6 KiB
Perl
Executable File

#!/usr/bin/perl
use lib '../src';
use strict;
use warnings;
use Socket;
use POSIX (); # don't import assert()
use PVE::Tools 'lock_file_full';
my $name = "test.lockfile.$$-";
# Book-keeping:
my %_ran;
sub new {
%_ran = ();
}
sub ran {
my ($what) = @_;
$_ran{$what} = 1;
}
sub assert {
my ($what) = @_;
die "code didn't run: $what\n" if !$_ran{$what};
}
sub assert_not {
my ($what) = @_;
die "code shouldn't have run: $what\n" if $_ran{$what};
}
# Does it actually lock? (shared=0)
# Can we get two simultaneous shared locks? (shared=1)
sub forktest1($) {
my ($shared) = @_;
new();
# socket pair for synchronization
socketpair(my $fmain, my $fother, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair(): $!\n";
my $other = sub {
# other side
close($fmain);
my $line;
lock_file_full($name, 60, $shared, sub {
ran('other side');
# tell parent we've acquired the lock
print {$fother} "1\n";
$fother->flush();
# wait for parent to be done trying to lock
$line = <$fother>;
});
die $@ if $@;
die "parent failed\n" if !$line || $line ne "2\n";
assert('other side');
return;
};
my $main = sub {
# main process
# Wait for our child to lock:
close($fother);
my $line = <$fmain>;
die "child failed to acquire a lock\n" if !$line || $line ne "1\n";
lock_file_full($name, 1, $shared, sub {
ran('local side');
});
if ($shared) {
assert('local side');
} else {
assert_not('local side');
}
print {$fmain} "2\n";
$fmain->flush();
};
PVE::Tools::run_fork($other, { afterfork => $main });
close($fmain);
}
eval {
# Regular lock:
new();
lock_file_full($name, 10, 0, sub { ran('single lock') });
assert('single lock');
# Lock multiple times in a row:
new();
lock_file_full($name, 10, 0, sub { ran('lock A') });
assert('lock A');
lock_file_full($name, 10, 0, sub { ran('lock B') });
assert('lock B');
# Nested lock:
new();
lock_file_full($name, 10, 0, sub {
ran('lock A');
lock_file_full($name, 10, 0, sub { ran('lock B') });
assert('lock B');
ran('lock C');
});
assert('lock A');
assert('lock B');
assert('lock C');
# Independent locks:
new();
lock_file_full($name, 10, 0, sub {
ran('lock A');
# locks file "${name}2"
lock_file_full($name.2, 10, 0, sub { ran('lock B') });
assert('lock B');
ran('lock C');
});
assert('lock A');
assert('lock B');
assert('lock C');
# Does it actually lock? (shared=0)
# Can we get two simultaneous shared locks? (shared=1)
forktest1(0);
forktest1(1);
};
my $err = $@;
system("rm $name*");
die $err if $err;