330 lines
14 KiB
Perl
330 lines
14 KiB
Perl
#!/usr/bin/env perl
|
|
|
|
#########################
|
|
|
|
use strict;
|
|
use Test::More;
|
|
use IO::Socket::UNIX qw( SOCK_STREAM SOMAXCONN );
|
|
use Data::Dumper;
|
|
use JSON::XS;
|
|
|
|
BEGIN {
|
|
eval {require threads;};
|
|
if ( $@ ) {
|
|
plan skip_all => 'need threads support for testing a real socket'
|
|
}
|
|
elsif( $^O eq 'MSWin32' ) {
|
|
plan skip_all => 'no sockets on windows';
|
|
}
|
|
else{
|
|
plan tests => 109
|
|
}
|
|
}
|
|
|
|
use File::Temp;
|
|
BEGIN { use_ok('Monitoring::Livestatus') };
|
|
|
|
#########################
|
|
# Normal Querys
|
|
#########################
|
|
my $line_seperator = 10;
|
|
my $column_seperator = 0;
|
|
my $test_data = [ ["alias","name","contacts"], # table header
|
|
["alias1","host1","contact1"], # row 1
|
|
["alias2","host2","contact2"], # row 2
|
|
["alias3","host3","contact3"], # row 3
|
|
];
|
|
my $test_hostgroups = [['']]; # test one row with no data
|
|
|
|
# expected results
|
|
my $selectall_arrayref1 = [ [ 'alias1', 'host1', 'contact1' ],
|
|
[ 'alias2', 'host2', 'contact2' ],
|
|
[ 'alias3', 'host3', 'contact3' ]
|
|
];
|
|
my $selectall_arrayref2 = [
|
|
{ 'contacts' => 'contact1', 'name' => 'host1', 'alias' => 'alias1' },
|
|
{ 'contacts' => 'contact2', 'name' => 'host2', 'alias' => 'alias2' },
|
|
{ 'contacts' => 'contact3', 'name' => 'host3', 'alias' => 'alias3' }
|
|
];
|
|
my $selectall_hashref = {
|
|
'host1' => { 'contacts' => 'contact1', 'name' => 'host1', 'alias' => 'alias1' },
|
|
'host2' => { 'contacts' => 'contact2', 'name' => 'host2', 'alias' => 'alias2' },
|
|
'host3' => { 'contacts' => 'contact3', 'name' => 'host3', 'alias' => 'alias3' }
|
|
};
|
|
my $selectcol_arrayref1 = [ 'alias1', 'alias2', 'alias3' ];
|
|
my $selectcol_arrayref2 = [ 'alias1', 'host1', 'alias2', 'host2', 'alias3', 'host3' ];
|
|
my $selectcol_arrayref3 = [ 'alias1', 'host1', 'contact1', 'alias2', 'host2', 'contact2', 'alias3', 'host3', 'contact3' ];
|
|
my @selectrow_array = ( 'alias1', 'host1', 'contact1' );
|
|
my $selectrow_arrayref = [ 'alias1', 'host1', 'contact1' ];
|
|
my $selectrow_hashref = { 'contacts' => 'contact1', 'name' => 'host1', 'alias' => 'alias1' };
|
|
|
|
#########################
|
|
# Single Querys
|
|
#########################
|
|
my $single_statement = "GET hosts\nColumns: alias\nFilter: name = host1";
|
|
my $selectscalar_value = 'alias1';
|
|
|
|
#########################
|
|
# Stats Querys
|
|
#########################
|
|
my $stats_statement = "GET services\nStats: state = 0\nStats: state = 1\nStats: state = 2\nStats: state = 3";
|
|
my $stats_data = [[4297,13,9,0]];
|
|
|
|
# expected results
|
|
my $stats_selectall_arrayref1 = [ [4297,13,9,0] ];
|
|
my $stats_selectall_arrayref2 = [ { 'state = 0' => '4297', 'state = 1' => '13', 'state = 2' => '9', 'state = 3' => 0 } ];
|
|
my $stats_selectcol_arrayref = [ '4297' ];
|
|
my @stats_selectrow_array = ( '4297', '13', '9', '0' );
|
|
my $stats_selectrow_arrayref = [ '4297', '13', '9', '0' ];
|
|
my $stats_selectrow_hashref = { 'state = 0' => '4297', 'state = 1' => '13', 'state = 2' => '9', 'state = 3' => 0 };
|
|
|
|
#########################
|
|
# Empty Querys
|
|
#########################
|
|
my $empty_statement = "GET services\nFilter: description = empty";
|
|
|
|
# expected results
|
|
my $empty_selectall_arrayref = [];
|
|
my $empty_selectcol_arrayref = [];
|
|
my @empty_selectrow_array;
|
|
my $empty_selectrow_arrayref;
|
|
my $empty_selectrow_hashref;
|
|
|
|
|
|
#########################
|
|
# get a temp file from File::Temp and replace it with our socket
|
|
my $fh = File::Temp->new(UNLINK => 0);
|
|
my $socket_path = $fh->filename;
|
|
unlink($socket_path);
|
|
my $thr1 = threads->create('create_socket', 'unix');
|
|
#########################
|
|
# get a temp file from File::Temp and replace it with our socket
|
|
my $server = 'localhost:32987';
|
|
my $thr2 = threads->create('create_socket', 'inet');
|
|
sleep(1);
|
|
|
|
#########################
|
|
my $objects_to_test = {
|
|
# create unix object with hash args
|
|
'unix_hash_args' => Monitoring::Livestatus->new(
|
|
verbose => 0,
|
|
socket => $socket_path,
|
|
line_seperator => $line_seperator,
|
|
column_seperator => $column_seperator,
|
|
),
|
|
|
|
# create unix object with a single arg
|
|
'unix_single_arg' => Monitoring::Livestatus::UNIX->new( $socket_path ),
|
|
|
|
# create inet object with hash args
|
|
'inet_hash_args' => Monitoring::Livestatus->new(
|
|
verbose => 0,
|
|
server => $server,
|
|
line_seperator => $line_seperator,
|
|
column_seperator => $column_seperator,
|
|
),
|
|
|
|
# create inet object with a single arg
|
|
'inet_single_arg' => Monitoring::Livestatus::INET->new( $server ),
|
|
|
|
};
|
|
|
|
for my $key (keys %{$objects_to_test}) {
|
|
my $ml = $objects_to_test->{$key};
|
|
isa_ok($ml, 'Monitoring::Livestatus');
|
|
|
|
# we dont need warnings for testing
|
|
$ml->warnings(0);
|
|
|
|
##################################################
|
|
# test settings
|
|
my $rt = $ml->verbose(1);
|
|
is($rt, '0', 'enable verbose');
|
|
$rt = $ml->verbose(0);
|
|
is($rt, '1', 'disable verbose');
|
|
|
|
$rt = $ml->errors_are_fatal(0);
|
|
is($rt, '1', 'disable errors_are_fatal');
|
|
$rt = $ml->errors_are_fatal(1);
|
|
is($rt, '0', 'enable errors_are_fatal');
|
|
|
|
##################################################
|
|
# do some sample querys
|
|
my $statement = "GET hosts";
|
|
|
|
#########################
|
|
my $ary_ref = $ml->selectall_arrayref($statement);
|
|
is_deeply($ary_ref, $selectall_arrayref1, 'selectall_arrayref($statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($selectall_arrayref1));
|
|
|
|
#########################
|
|
$ary_ref = $ml->selectall_arrayref($statement, { Slice => {} });
|
|
is_deeply($ary_ref, $selectall_arrayref2, 'selectall_arrayref($statement, { Slice => {} })')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($selectall_arrayref2));
|
|
|
|
#########################
|
|
my $hash_ref = $ml->selectall_hashref($statement, 'name');
|
|
is_deeply($hash_ref, $selectall_hashref, 'selectall_hashref($statement, "name")')
|
|
or diag("got: ".Dumper($hash_ref)."\nbut expected ".Dumper($selectall_hashref));
|
|
|
|
#########################
|
|
$ary_ref = $ml->selectcol_arrayref($statement);
|
|
is_deeply($ary_ref, $selectcol_arrayref1, 'selectcol_arrayref($statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($selectcol_arrayref1));
|
|
|
|
#########################
|
|
$ary_ref = $ml->selectcol_arrayref($statement, { Columns=>[1,2] });
|
|
is_deeply($ary_ref, $selectcol_arrayref2, 'selectcol_arrayref($statement, { Columns=>[1,2] })')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($selectcol_arrayref2));
|
|
|
|
$ary_ref = $ml->selectcol_arrayref($statement, { Columns=>[1,2,3] });
|
|
is_deeply($ary_ref, $selectcol_arrayref3, 'selectcol_arrayref($statement, { Columns=>[1,2,3] })')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($selectcol_arrayref3));
|
|
|
|
#########################
|
|
my @row_ary = $ml->selectrow_array($statement);
|
|
is_deeply(\@row_ary, \@selectrow_array, 'selectrow_array($statement)')
|
|
or diag("got: ".Dumper(\@row_ary)."\nbut expected ".Dumper(\@selectrow_array));
|
|
|
|
#########################
|
|
$ary_ref = $ml->selectrow_arrayref($statement);
|
|
is_deeply($ary_ref, $selectrow_arrayref, 'selectrow_arrayref($statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($selectrow_arrayref));
|
|
|
|
#########################
|
|
$hash_ref = $ml->selectrow_hashref($statement);
|
|
is_deeply($hash_ref, $selectrow_hashref, 'selectrow_hashref($statement)')
|
|
or diag("got: ".Dumper($hash_ref)."\nbut expected ".Dumper($selectrow_hashref));
|
|
|
|
##################################################
|
|
# stats querys
|
|
##################################################
|
|
$ary_ref = $ml->selectall_arrayref($stats_statement);
|
|
is_deeply($ary_ref, $stats_selectall_arrayref1, 'selectall_arrayref($stats_statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($stats_selectall_arrayref1));
|
|
|
|
$ary_ref = $ml->selectall_arrayref($stats_statement, { Slice => {} });
|
|
is_deeply($ary_ref, $stats_selectall_arrayref2, 'selectall_arrayref($stats_statement, { Slice => {} })')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($stats_selectall_arrayref2));
|
|
|
|
$ary_ref = $ml->selectcol_arrayref($stats_statement);
|
|
is_deeply($ary_ref, $stats_selectcol_arrayref, 'selectcol_arrayref($stats_statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($stats_selectcol_arrayref));
|
|
|
|
@row_ary = $ml->selectrow_array($stats_statement);
|
|
is_deeply(\@row_ary, \@stats_selectrow_array, 'selectrow_arrayref($stats_statement)')
|
|
or diag("got: ".Dumper(\@row_ary)."\nbut expected ".Dumper(\@stats_selectrow_array));
|
|
|
|
$ary_ref = $ml->selectrow_arrayref($stats_statement);
|
|
is_deeply($ary_ref, $stats_selectrow_arrayref, 'selectrow_arrayref($stats_statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($stats_selectrow_arrayref));
|
|
|
|
$hash_ref = $ml->selectrow_hashref($stats_statement);
|
|
is_deeply($hash_ref, $stats_selectrow_hashref, 'selectrow_hashref($stats_statement)')
|
|
or diag("got: ".Dumper($hash_ref)."\nbut expected ".Dumper($stats_selectrow_hashref));
|
|
|
|
my $scal = $ml->selectscalar_value($single_statement);
|
|
is($scal, $selectscalar_value, 'selectscalar_value($single_statement)')
|
|
or diag("got: ".Dumper($scal)."\nbut expected ".Dumper($selectscalar_value));
|
|
|
|
##################################################
|
|
# empty querys
|
|
##################################################
|
|
$ary_ref = $ml->selectall_arrayref($empty_statement);
|
|
is_deeply($ary_ref, $empty_selectall_arrayref, 'selectall_arrayref($empty_statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($empty_selectall_arrayref));
|
|
|
|
$ary_ref = $ml->selectcol_arrayref($empty_statement);
|
|
is_deeply($ary_ref, $empty_selectcol_arrayref, 'selectcol_arrayref($empty_statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($empty_selectcol_arrayref));
|
|
|
|
@row_ary = $ml->selectrow_array($empty_statement);
|
|
is_deeply(\@row_ary, \@empty_selectrow_array, 'selectrow_arrayref($empty_statement)')
|
|
or diag("got: ".Dumper(\@row_ary)."\nbut expected ".Dumper(\@empty_selectrow_array));
|
|
|
|
$ary_ref = $ml->selectrow_arrayref($empty_statement);
|
|
is_deeply($ary_ref, $empty_selectrow_arrayref, 'selectrow_arrayref($empty_statement)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($empty_selectrow_arrayref));
|
|
|
|
$hash_ref = $ml->selectrow_hashref($empty_statement);
|
|
is_deeply($hash_ref, $empty_selectrow_hashref, 'selectrow_hashref($empty_statement)')
|
|
or diag("got: ".Dumper($hash_ref)."\nbut expected ".Dumper($empty_selectrow_hashref));
|
|
|
|
##################################################
|
|
# empty rows and columns
|
|
##################################################
|
|
my $empty_hostgroups_stm = "GET hostgroups\nColumns: members";
|
|
$ary_ref = $ml->selectall_arrayref($empty_hostgroups_stm);
|
|
is_deeply($ary_ref, $test_hostgroups, 'selectall_arrayref($empty_hostgroups_stm)')
|
|
or diag("got: ".Dumper($ary_ref)."\nbut expected ".Dumper($test_hostgroups));
|
|
|
|
}
|
|
|
|
##################################################
|
|
# exit threads
|
|
$thr1->kill('KILL')->detach();
|
|
$thr2->kill('KILL')->detach();
|
|
exit;
|
|
|
|
|
|
#########################
|
|
# SUBS
|
|
#########################
|
|
# test socket server
|
|
sub create_socket {
|
|
my $type = shift;
|
|
my $listener;
|
|
|
|
$SIG{'KILL'} = sub { threads->exit(); };
|
|
|
|
if($type eq 'unix') {
|
|
print "creating unix socket\n";
|
|
$listener = IO::Socket::UNIX->new(
|
|
Type => SOCK_STREAM,
|
|
Listen => SOMAXCONN,
|
|
Local => $socket_path,
|
|
) or die("failed to open $socket_path as test socket: $!");
|
|
}
|
|
elsif($type eq 'inet') {
|
|
print "creating tcp socket\n";
|
|
$listener = IO::Socket::INET->new(
|
|
LocalAddr => $server,
|
|
Proto => 'tcp',
|
|
Listen => 1,
|
|
Reuse => 1,
|
|
) or die("failed to listen on $server: $!");
|
|
} else {
|
|
die("unknown type");
|
|
}
|
|
while( my $socket = $listener->accept() or die('cannot accept: $!') ) {
|
|
my $recv = "";
|
|
while(<$socket>) { $recv .= $_; last if $_ eq "\n" }
|
|
my $data;
|
|
my $status = 200;
|
|
if($recv =~ m/^GET .*?\s+Filter:.*?empty/m) {
|
|
$data = '';
|
|
}
|
|
elsif($recv =~ m/^GET hosts\s+Columns: alias/m) {
|
|
my @data = @{$test_data}[1..3];
|
|
$data = encode_json(\@data)."\n";
|
|
}
|
|
elsif($recv =~ m/^GET hosts\s+Columns: name/m) {
|
|
$data = encode_json(\@{$test_data}[1..3])."\n";
|
|
}
|
|
elsif($recv =~ m/^GET hosts/) {
|
|
$data = encode_json($test_data)."\n";
|
|
}
|
|
elsif($recv =~ m/^GET hostgroups/) {
|
|
$data = encode_json(\@{$test_hostgroups})."\n";
|
|
}
|
|
elsif($recv =~ m/^GET services/ and $recv =~ m/Stats:/m) {
|
|
$data = encode_json(\@{$stats_data})."\n";
|
|
}
|
|
my $content_length = sprintf("%11s", length($data));
|
|
print $socket $status." ".$content_length."\n";
|
|
print $socket $data;
|
|
close($socket);
|
|
}
|
|
unlink($socket_path);
|
|
}
|