1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
# Create a log file on a file system that can be easily filled.
# The client writes messages to Sys::Syslog native method.
# While writing messages, the client fills the log file system.
# After the file system has been filled, send sigterm to syslogd.
# The syslogd writes it into a file and through a pipe and to tty.
# The syslogd passes it via UDP to the loghost.
# The server receives the message on its UDP socket.
# Find the message in client, file, pipe, console, user, syslogd, server log.
# Check that syslogd error 'No space left on device' error is logged to server.
# Check that kernel error 'file system full' error is logged.
# Check that the final 'dropped messages to file' is logged by server.
use strict;
use warnings;
use Errno ':POSIX';
use File::Path qw(remove_tree);
use Time::HiRes;
my @errors = (ENOSPC);
my $errors = "(". join("|", map { $! = $_ } @errors). ")";
my $fspath = "/mnt/regress-syslogd";
my $fslog = "$fspath/file.log";
my $fsbig = "$fspath/big";
remove_tree($fspath, { safe => 1, keep_root => 1 });
open(my $log, '>', $fslog)
or die "Create $fslog failed: $!";
our %args = (
client => {
func => sub { write_between2logs(shift, sub {
my $self = shift;
open(my $big, '>', $fsbig)
or die ref($self), " create $fsbig failed: $!";
${$self->{syslogd}}->loggrep(get_firstlog(), 5)
or die ref($self), " first log not in syslogd log";
undef $!;
for (my $i = 0; $i < 100000; $i++) {
syswrite($big, "regress syslogd file system full\n")
or last;
}
$!{ENOSPC}
or die ref($self), " fill $fsbig failed: $!";
# a single message still fits, write 4 KB logs to reach next block
write_lines($self, 100, 70);
write_lines($self, 9, 1);
${$self->{syslogd}}->loggrep(qr/write to file .* $errors/, 10)
or die ref($self), " write to file error not in syslogd log";
close($big);
# wait until syslogd has processed everything
write_message($self, get_secondlog());
${$self->{server}}->loggrep(get_secondlog(), 8)
or die ref($self), " second log not in server log";
})},
},
syslogd => {
outfile => $fslog,
loggrep => {
get_charlog() => 100,
},
},
server => {
func => sub {
my $self = shift;
read_log($self);
${$self->{syslogd}}->kill_syslogd('TERM');
${$self->{syslogd}}->loggrep("syslogd: exited", 5)
or die ref($self), " no 'syslogd: exited' in syslogd log";
read_message($self, "exiting on signal 15");
},
loggrep => {
get_firstlog() => 1,
get_secondlog() => 1,
get_testgrep() => 1,
qr/syslogd\[\d+\]: start/ => 1,
qr/syslogd\[\d+\]: restart/ => 0,
qr/syslogd\[\d+\]: write to file "$fslog": /.
qr/No space left on device/ => '>=1',
qr/bsd: .* on $fspath: file system full/ => '>=1',
qr/syslogd\[\d+\]: dropped \d+ messages to file$/ => 1,
},
},
file => {
loggrep => {
get_firstlog() => 1,
get_testgrep() => 0,
qr/syslogd\[\d+\]: write to file "$fslog": /.
qr/No space left on device/ => 0,
qr/syslogd\[\d+\]: dropped \d+ messages to file$/ => 0,
},
},
pipe => { nocheck => 1 },
tty => { nocheck => 1 },
);
1;
|