File Coverage

blib/lib/Test/Rsyslog.pm
Criterion Covered Total %
statement 104 112 92.8
branch 21 40 52.5
condition 5 9 55.5
subroutine 20 20 100.0
pod 5 5 100.0
total 155 186 83.3


line stmt bran cond sub pod time code
1             package Test::Rsyslog;
2              
3 5     5   70526 use 5.010;
  5         15  
4 5     5   17 use strict;
  5         5  
  5         89  
5 5     5   11 use warnings;
  5         11  
  5         116  
6 5     5   3033 use File::Temp();
  5         79631  
  5         109  
7 5     5   29 use Fcntl();
  5         5  
  5         50  
8 5     5   15 use File::Spec();
  5         5  
  5         44  
9 5     5   1899 use FileHandle();
  5         8288  
  5         113  
10 5     5   2101 use English qw( -no_match_vars );
  5         6538  
  5         20  
11 5     5   1464 use Carp();
  5         9  
  5         50  
12 5     5   2073 use POSIX();
  5         21740  
  5         105  
13 5     5   25 use Config;
  5         5  
  5         4548  
14              
15             our $VERSION = '0.01';
16              
17 4     4   36 sub _USER_READ_WRITE_PERMISSIONS { return 600 }
18 4     4   568 sub _USER_READ_WRITE_EXECUTE_PERMISSIONS { return 700 }
19              
20             sub socket_path {
21 3     3 1 1251 my ($self) = @_;
22 3         54 return $self->{_socket_path};
23             }
24              
25             sub find {
26 6     6 1 67 my ( $self, $string ) = @_;
27 6         14 my @found;
28 6         99 my $handle = FileHandle->new( $self->{_messages_path}, Fcntl::O_RDONLY() );
29 6     3   829 binmode $handle, ':encoding(UTF-8)';
  3         33  
  3         6  
  3         24  
30 6 50       25219 if ($handle) {
    0          
31 6         24 $string =~ s/([\x00-\x1F])/'#' . sprintf '%03o', ord $1/smxeg;
  36         66  
32 6         26 my $quoted = quotemeta $string;
33 6         173 while ( my $line = <$handle> ) {
34 24         194 chomp $line;
35 24 100       264 if ( $line =~ /$quoted/smx ) {
36 3         22 push @found, $line;
37             }
38             }
39             }
40             elsif ( $OS_ERROR == POSIX::ENOENT() ) {
41             }
42             else {
43 0         0 Carp::croak(
44             "Failed to open $self->{_messages_path} for reading:$OS_ERROR");
45             }
46 6         96 return @found;
47             }
48              
49             sub new {
50 4     4 1 366588 my ($class) = @_;
51 4         8 my $self = bless {}, $class;
52 4         744 $self->{_root_directory} = File::Temp::mktemp(
53             File::Spec->catfile(
54             File::Spec->tmpdir(), 'perl_test_rsyslog_XXXXXXXXXXX'
55             )
56             );
57 4 50       868 mkdir $self->{_root_directory}, oct _USER_READ_WRITE_EXECUTE_PERMISSIONS()
58             or Carp::croak("Failed to mkdir $self->{_root_directory}:$OS_ERROR");
59             $self->{_socket_path} =
60 4         48 File::Spec->catfile( $self->{_root_directory}, 'rsyslog.sock' );
61             $self->{_messages_path} =
62 4         24 File::Spec->catfile( $self->{_root_directory}, 'messages' );
63 4         20 $self->{_pid_path} = File::Spec->catfile( $self->{_root_directory}, 'pid' );
64             $self->{_config_path} =
65 4         20 File::Spec->catfile( $self->{_root_directory}, 'rsyslog.conf' );
66             my $config_handle = FileHandle->new(
67             $self->{_config_path},
68 4 50       12 Fcntl::O_WRONLY() | Fcntl::O_CREAT() | Fcntl::O_EXCL(),
69             oct _USER_READ_WRITE_PERMISSIONS()
70             )
71             or
72             Carp::croak("Failed to open $self->{_config_path} for writing:$OS_ERROR");
73 4 50       580 $config_handle->print(
74             <<"_CONF_") or Carp::croak("Failed to print to $self->{_config_path}:$OS_ERROR");
75             \$ModLoad imuxsock
76             \$InputUnixListenSocketCreatePath on
77             \$AddUnixListenSocket $self->{_socket_path}
78             \$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
79             \$OmitLocalLogging off
80             *.* $self->{_messages_path}
81             _CONF_
82 4 50       120 $config_handle->close()
83             or Carp::croak("Failed to close $self->{_config_path}:$OS_ERROR");
84 4         220 $self->start();
85 3         78 return $self;
86             }
87              
88             sub start {
89 9     9 1 6492 my ($self) = @_;
90 9         123 my $dev_null = File::Spec->devnull();
91 9 50 66     115 if ( ( defined $self->{_pid} ) && ( kill 0, $self->{_pid} ) ) {
92 0         0 Carp::cluck('Temporary rsyslog daemon is already running...');
93 0         0 return;
94             }
95 9 100       6258 if ( $self->{_pid} = fork ) {
    50          
96 6         222 while ( not -e $self->{_socket_path} ) {
97 6         6000858 sleep 1;
98             }
99             }
100             elsif ( defined $self->{_pid} ) {
101              
102             eval {
103             # clear any possible tainted environment variables
104 3         1035 local %ENV = %ENV;
105 3         147 local $ENV{'PATH'} = '/usr/bin:/usr/sbin:/sbin:/bin:';
106 3         55 delete $ENV{'BASH_ENV'};
107 3         27 delete $ENV{'ENV'};
108 3         153 delete $ENV{'IFS'};
109 3         174 delete $ENV{'CDPATH'};
110 3 50       386 open STDERR, q[>], $dev_null
111             or die "Failed to redirect STDERR:$OS_ERROR\n";
112 3 50       70 open STDOUT, q[>], $dev_null
113             or die "Failed to redirect STDOUT:$OS_ERROR\n";
114 3         0 exec {'rsyslogd'} 'rsyslogd', '-n', '-d',
115             '-f' => $self->{_config_path},
116             '-i' => $self->{_pid_path}
117 3 0       12 or die "Failed to exec 'rsyslogd':$OS_ERROR\n";
118 3 0       113 } or do {
119 0         0 chomp $EVAL_ERROR;
120 0         0 warn "$EVAL_ERROR\n";
121             };
122 0         0 exit 1;
123             }
124             else {
125 0         0 Carp::croak("Failed to fork:$OS_ERROR");
126             }
127 6         92 return;
128             }
129              
130             sub stop {
131 7     7 1 7646 my ($self) = @_;
132 7 50       39 if ( $self->{_pid} ) {
133 7         423 my @signal_numbers = split q[ ], $Config{'sig_num'};
134 7         216 my @signal_names = split q[ ], $Config{'sig_name'};
135 7         15 my %signals_by_name;
136 7         13 my $signal_index = 0;
137 7         16 foreach my $signal_name (@signal_names) {
138 483         651 $signals_by_name{$signal_name} = $signal_numbers[$signal_index];
139 483         481 $signal_index += 1;
140             }
141 7 100       222 if ( kill $signals_by_name{'TERM'}, $self->{_pid} ) {
    50          
142 6         7607 waitpid $self->{_pid}, 0;
143             }
144             elsif ( $OS_ERROR == POSIX::ESRCH() ) {
145             }
146             else {
147 0         0 Carp::croak("Failed to kill $self->{_pid}:$OS_ERROR");
148             }
149             }
150 7         30 return;
151             }
152              
153             sub DESTROY {
154 1     1   763 my ($self) = @_;
155 1         4 $self->stop();
156 1         2 foreach my $key ( sort { $a cmp $b } keys %{$self} ) {
  10         50  
  1         19  
157 6 100       25 if ( $key =~ /_path$/smx ) {
158 4 50 66     154 unlink $self->{$key}
159             or ( $OS_ERROR == POSIX::ENOENT() )
160             or Carp::croak("Failed to unlink $self->{$key}:$OS_ERROR");
161             }
162             }
163             rmdir $self->{_root_directory}
164 1 50 33     96 or ( $OS_ERROR == POSIX::ENOENT() )
165             or Carp::croak("Failed to rmdir $self->{_root_directory}:$OS_ERROR");
166 1         53 return;
167             }
168              
169             1;
170             __END__