t/unit/MGH_Biostat/TravEpi/SimpleRulesBase/Logger/log.t
#!/usr/bin/env perl
use Modern::Perl '2013';
use Test2::V0;
use Test2::Tools::Spec;
use Plack::Test;
use HTTP::Request;
use JSON::Tiny 'encode_json';
use MGH_Biostat::TravEpi::SimpleRulesBase::Logger;
tests 'logger' => sub {
my $mock_logger = mock { 'lines' => [] } => (
add => [
'print' => sub {
my $self = shift;
my ($line) = @_;
push @{ $self->{'lines'} }, $line;
},
]
);
my $logger = MGH_Biostat::TravEpi::SimpleRulesBase::Logger->new($mock_logger);
# override loggers removal of localhost, so that we can have something to test against
shift @{ $MGH_Biostat::TravEpi::SimpleRulesBase::Logger::filters->{'remove_ips'} };
my $action = sub {
my ( $ua, $ip, $hash, $lang, $action, $extra ) = @_;
my $plack = Plack::Test->create(
sub {
my $env = shift;
if ( defined( $env->{'HTTP_REMOTE_ADDR'} ) ) { $env->{'REMOTE_ADDR'} = $env->{'HTTP_REMOTE_ADDR'}; }
$logger->log( $env, $hash, $lang, $action, $extra );
return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'ok' ] ];
} );
my $request = HTTP::Request->new( 'GET' => '/' );
$request->header( 'User-Agent' => $ua );
if ($ip) {
if ( defined( $ip->{'REMOTE_ADDR'} ) ) {
$request->header( 'Remote-Addr' => $ip->{'REMOTE_ADDR'} );
}
if ( defined( $ip->{'X_FORWARDED_FOR'} ) ) {
$request->header( 'X-Forwarded-For' => $ip->{'X_FORWARDED_FOR'} );
}
}
$plack->request($request);
};
my $loglines = [
{ 'ua' => 'testua1', 'ip' => '', 'hash' => 'testhash1', 'lang' => 'testlang1', 'action' => 'testaction1', 'extra' => 'testextra1', 'keep' => 1 },
{ 'ua' => 'testua2', 'ip' => { 'REMOTE_ADDR' => '10.0.0.1', 'EXPECTED' => '10.0.0.1' }, 'hash' => 'testhash2', 'lang' => 'testlang2', 'action' => 'testaction2', 'extra' => 'testextra2', 'keep' => 1 },
{ 'ua' => 'UptimeRobot foo', 'ip' => '', 'hash' => 'testhash3', 'lang' => 'testlang3', 'action' => 'testaction3', 'extra' => 'testextra3', 'keep' => 0 },
];
foreach my $logline (@$loglines) {
$action->( @{$logline}{qw(ua ip hash lang action extra)} );
}
my $expectedlines = [];
foreach my $line (@$loglines) {
next unless $line->{'keep'};
my $ips_json = ips_to_json( $line->{'ip'} );
push @$expectedlines, match qr/^
\d{4}-\d{2}-\d{2}\ \d{2}:\d{2}:\d{2}
\t
\Q$line->{hash}\E
\t
\Q$ips_json\E
\t
\Q$line->{lang}\E
\t
\Q$line->{action}\E
\t
\Q$line->{ua}\E
\t
\Q$line->{extra}\E
$/x;
}
is( $mock_logger->{'lines'}, $expectedlines, 'logged lines (text) match expected' );
};
done_testing();
sub ips_to_json {
my $ip_spec = shift;
my $ip_array = [];
if ( $ip_spec and ( $ip_spec->{'EXPECTED'} ) ) {
## if any ip specification is provided, we need to know what is expected
push @$ip_array, split( ',' => $ip_spec->{'EXPECTED'} );
}
elsif ( !$ip_spec ) {
## if we don't override anything, then we expect the ip address to be localhost
push @$ip_array, '127.0.0.1';
}
return encode_json($ip_array);
}