362 lines
12 KiB
Perl
362 lines
12 KiB
Perl
|
|
use strict;
|
||
|
|
use warnings;
|
||
|
|
use 5.14.2;
|
||
|
|
|
||
|
|
use Data::Dumper;
|
||
|
|
use File::Temp qw[tempdir];
|
||
|
|
use POSIX qw( strftime );
|
||
|
|
use Time::Local qw( timelocal_modern );
|
||
|
|
use Test::Exception;
|
||
|
|
use Test::More; # see done_testing()
|
||
|
|
use Test::Differences;
|
||
|
|
|
||
|
|
my $t_path;
|
||
|
|
BEGIN {
|
||
|
|
use File::Spec::Functions qw( rel2abs );
|
||
|
|
use File::Basename qw( dirname );
|
||
|
|
$t_path = dirname( rel2abs( $0 ) );
|
||
|
|
}
|
||
|
|
use lib $t_path;
|
||
|
|
use TestUtil qw( RPCAPI );
|
||
|
|
|
||
|
|
use Zonemaster::Backend::Config;
|
||
|
|
|
||
|
|
my $db_backend = TestUtil::db_backend();
|
||
|
|
|
||
|
|
my $tempdir = tempdir( CLEANUP => 1 );
|
||
|
|
my $config = <<EOF;
|
||
|
|
[DB]
|
||
|
|
engine = $db_backend
|
||
|
|
|
||
|
|
[MYSQL]
|
||
|
|
host = localhost
|
||
|
|
user = zonemaster_test
|
||
|
|
password = zonemaster
|
||
|
|
database = zonemaster_test
|
||
|
|
|
||
|
|
[POSTGRESQL]
|
||
|
|
host = localhost
|
||
|
|
user = zonemaster_test
|
||
|
|
password = zonemaster
|
||
|
|
database = zonemaster_test
|
||
|
|
|
||
|
|
[SQLITE]
|
||
|
|
database_file = $tempdir/zonemaster.sqlite
|
||
|
|
|
||
|
|
[LANGUAGE]
|
||
|
|
locale = en_US
|
||
|
|
|
||
|
|
[PUBLIC PROFILES]
|
||
|
|
test_profile=$t_path/test_profile.json
|
||
|
|
EOF
|
||
|
|
|
||
|
|
my $user = {
|
||
|
|
username => 'user',
|
||
|
|
api_key => 'key'
|
||
|
|
};
|
||
|
|
|
||
|
|
# define the default properties for the tests
|
||
|
|
my $params = {
|
||
|
|
client_id => 'Unit Test',
|
||
|
|
client_version => '1.0',
|
||
|
|
ipv4 => JSON::PP::true,
|
||
|
|
ipv6 => JSON::PP::true,
|
||
|
|
profile => 'test_profile',
|
||
|
|
};
|
||
|
|
|
||
|
|
# Create Zonemaster::Backend::RPCAPI object
|
||
|
|
sub init_backend {
|
||
|
|
my ( $config ) = @_;
|
||
|
|
|
||
|
|
my $rpcapi = TestUtil::create_rpcapi( $config );
|
||
|
|
|
||
|
|
# create a user
|
||
|
|
$rpcapi->add_api_user( $user );
|
||
|
|
|
||
|
|
return $rpcapi;
|
||
|
|
}
|
||
|
|
|
||
|
|
sub to_timestamp {
|
||
|
|
my ( $date ) = @_;
|
||
|
|
|
||
|
|
my ( $year, $month, $day, $hour, $min, $sec ) = split( /[\s:-]+/, $date );
|
||
|
|
my $time = timelocal_modern( $sec, $min, $hour, $day, $month-1, $year );
|
||
|
|
return $time;
|
||
|
|
}
|
||
|
|
|
||
|
|
sub check_tolerance {
|
||
|
|
my ( $ref_time, $msg ) = @_;
|
||
|
|
|
||
|
|
my $current_time = strftime "%Y-%m-%d %H:%M:%S", gmtime( time() );
|
||
|
|
my $delta = abs( to_timestamp($current_time) - to_timestamp($ref_time) );
|
||
|
|
|
||
|
|
my $tolerance = 60; # 1 minute is tolerable between ret_time and current_time
|
||
|
|
|
||
|
|
cmp_ok( $delta, '<=', $tolerance, $msg);
|
||
|
|
}
|
||
|
|
|
||
|
|
subtest 'RPCAPI add_batch_job' => sub {
|
||
|
|
my $config = Zonemaster::Backend::Config->parse( $config );
|
||
|
|
my $rpcapi = init_backend( $config );
|
||
|
|
my $dbh = $rpcapi->{db}->dbh;
|
||
|
|
|
||
|
|
my @domains = ( 'afnic.fr' );
|
||
|
|
|
||
|
|
my $res = $rpcapi->add_batch_job(
|
||
|
|
{
|
||
|
|
%$user,
|
||
|
|
domains => \@domains,
|
||
|
|
test_params => $params
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
is( $res, 1, 'correct batch job id returned' );
|
||
|
|
|
||
|
|
subtest 'table "batch_jobs" contains an entry' => sub {
|
||
|
|
my ( $count ) = $dbh->selectrow_array( q[ SELECT count(*) FROM batch_jobs ] );
|
||
|
|
is( $count, 1, 'one row in table' );
|
||
|
|
|
||
|
|
my ( $id, $username, $created_at ) = $dbh->selectrow_array( q[ SELECT * FROM batch_jobs ]);
|
||
|
|
is( $id, 1, 'first batch id is 1' );
|
||
|
|
is( $username, $user->{username}, 'correct batch user' );
|
||
|
|
ok( $created_at, 'defined creation time' );
|
||
|
|
check_tolerance( $created_at, 'creation time in tolerance zone' );
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'table "test_results" contains an entry' => sub {
|
||
|
|
my ( $count ) = $dbh->selectrow_array( q[ SELECT count(*) FROM test_results ] );
|
||
|
|
is( $count, 1, 'one row in table' );
|
||
|
|
|
||
|
|
my ( $hash_id, $domain, $batch_id, $created_at, $started_at, $ended_at, $params ) = $dbh->selectrow_array(
|
||
|
|
q[
|
||
|
|
SELECT
|
||
|
|
hash_id,
|
||
|
|
domain,
|
||
|
|
batch_id,
|
||
|
|
created_at,
|
||
|
|
started_at,
|
||
|
|
ended_at,
|
||
|
|
params
|
||
|
|
FROM test_results
|
||
|
|
]
|
||
|
|
);
|
||
|
|
|
||
|
|
is( length($hash_id), 16, 'correct hash_id length' );
|
||
|
|
is( $domain, $domains[0], 'correct domain' );
|
||
|
|
is( $batch_id, 1, 'correct batch_id' );
|
||
|
|
ok( $created_at, 'defined creation time' );
|
||
|
|
check_tolerance( $created_at, 'creation time in tolerance zone' );
|
||
|
|
ok( ! defined $started_at, 'undefined start time' );
|
||
|
|
ok( ! defined $ended_at, 'undefined end time' );
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'RPCAPI batch_status' => sub {
|
||
|
|
my $config = Zonemaster::Backend::Config->parse( $config );
|
||
|
|
my $rpcapi = init_backend( $config );
|
||
|
|
subtest 'batch job exists' => sub {
|
||
|
|
my @domains = ( 'afnic.fr' );
|
||
|
|
|
||
|
|
my $batch_id = $rpcapi->add_batch_job(
|
||
|
|
{
|
||
|
|
%$user,
|
||
|
|
domains => \@domains,
|
||
|
|
test_params => $params
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
is( $batch_id, 1, 'correct batch job id returned' );
|
||
|
|
|
||
|
|
my $res = $rpcapi->batch_status( { batch_id => $batch_id } );
|
||
|
|
is( $res->{waiting_count}, scalar @domains, 'correct number of runninng tests' );
|
||
|
|
is( $res->{running_count}, 0, 'correct number of finished tests' );
|
||
|
|
is( $res->{finished_count}, 0, 'correct number of finished tests' );
|
||
|
|
ok( !exists $res->{waiting_tests}, 'list of waiting tests expected to be absent' );
|
||
|
|
ok( !exists $res->{running_tests}, 'list of running tests expected to be absent' );
|
||
|
|
ok( !exists $res->{finished_tests}, 'list of finished tests to be absent' );
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'unknown batch (batch_status)' => sub {
|
||
|
|
my $unknown_batch = 10;
|
||
|
|
dies_ok {
|
||
|
|
$rpcapi->batch_status( { batch_id => $unknown_batch } );
|
||
|
|
} 'getting results for an unknown batch_id should die';
|
||
|
|
my $res = $@;
|
||
|
|
is( $res->{error}, 'Zonemaster::Backend::Error::ResourceNotFound', 'correct error type' );
|
||
|
|
is( $res->{message}, 'Unknown batch', 'correct error message' );
|
||
|
|
is( $res->{data}->{batch_id}, $unknown_batch, 'correct data type returned' );
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'batch with several domains' => sub {
|
||
|
|
my $config = Zonemaster::Backend::Config->parse( $config );
|
||
|
|
my $rpcapi = init_backend( $config );
|
||
|
|
my $dbh = $rpcapi->{db}->dbh;
|
||
|
|
|
||
|
|
my @domains = sort( 'afnic.fr', 'iis.se' );
|
||
|
|
|
||
|
|
my $res = $rpcapi->add_batch_job(
|
||
|
|
{
|
||
|
|
%$user,
|
||
|
|
domains => \@domains,
|
||
|
|
test_params => $params
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
is( $res, 1, 'correct batch job id returned' );
|
||
|
|
|
||
|
|
# No lists of test IDs requested
|
||
|
|
$res = $rpcapi->batch_status( { batch_id => 1 } );
|
||
|
|
|
||
|
|
is( $res->{waiting_count}, scalar @domains, 'correct number of running tests' );
|
||
|
|
is( $res->{running_count}, 0, 'correct number of finished tests' );
|
||
|
|
is( $res->{finished_count}, 0, 'correct number of finished tests' );
|
||
|
|
ok( !exists $res->{waiting_tests}, 'list of waiting tests expected to be absent' );
|
||
|
|
ok( !exists $res->{running_tests}, 'list of running tests expected to be absent' );
|
||
|
|
ok( !exists $res->{finished_tests}, 'list of finished tests expected to be absent' );
|
||
|
|
|
||
|
|
# List of waiting test IDs requested
|
||
|
|
$res = $rpcapi->batch_status( { batch_id => 1, list_waiting_tests => 1 } );
|
||
|
|
|
||
|
|
is( $res->{waiting_count}, scalar @domains, 'correct number of runninng tests' );
|
||
|
|
is( $res->{running_count}, 0, 'correct number of finished tests' );
|
||
|
|
is( $res->{finished_count}, 0, 'correct number of finished tests' );
|
||
|
|
is( scalar @{ $res->{waiting_tests} }, scalar @domains, 'correct number of elements in waiting_tests' );
|
||
|
|
ok( !exists $res->{running_tests}, 'list of running tests expected to be absent' );
|
||
|
|
ok( !exists $res->{finished_tests}, 'list of finished tests expected to be absent' );
|
||
|
|
|
||
|
|
subtest 'table "test_results" contains 2 entries' => sub {
|
||
|
|
my ( $count ) = $dbh->selectrow_array( q[ SELECT count(*) FROM test_results ] );
|
||
|
|
is( $count, @domains, 'two rows in table' );
|
||
|
|
|
||
|
|
my $rows = $dbh->selectall_hashref(
|
||
|
|
q[
|
||
|
|
SELECT
|
||
|
|
hash_id,
|
||
|
|
domain,
|
||
|
|
batch_id,
|
||
|
|
created_at,
|
||
|
|
started_at,
|
||
|
|
ended_at,
|
||
|
|
params
|
||
|
|
FROM test_results
|
||
|
|
],
|
||
|
|
'domain'
|
||
|
|
);
|
||
|
|
|
||
|
|
my @keys = sort keys %$rows;
|
||
|
|
is_deeply( \@keys, \@domains, 'correct domains' );
|
||
|
|
|
||
|
|
foreach my $domain ( @keys ) {
|
||
|
|
is( length($rows->{$domain}->{hash_id}), 16, "[$domain] correct hash_id length" );
|
||
|
|
is( $rows->{$domain}->{batch_id}, 1, "[$domain] correct batch_id" );
|
||
|
|
ok( $rows->{$domain}->{created_at}, "[$domain] defined creation time" );
|
||
|
|
check_tolerance( $rows->{$domain}->{created_at}, "[$domain] creation time in tolerance zone" );
|
||
|
|
ok( ! defined $rows->{$domain}->{started_at}, "[$domain] undefined start time" );
|
||
|
|
ok( ! defined $rows->{$domain}->{ended_at}, "[$domain] undefined end time" );
|
||
|
|
}
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'batch job still running' => sub {
|
||
|
|
my $config = Zonemaster::Backend::Config->parse( $config );
|
||
|
|
my $rpcapi = init_backend( $config );
|
||
|
|
my $dbh = $rpcapi->{db}->dbh;
|
||
|
|
|
||
|
|
my @domains = ( 'afnic.fr' );
|
||
|
|
|
||
|
|
my $batch_id = $rpcapi->add_batch_job(
|
||
|
|
{
|
||
|
|
%$user,
|
||
|
|
domains => \@domains,
|
||
|
|
test_params => $params
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
is( $batch_id, 1, 'correct batch job id returned' );
|
||
|
|
|
||
|
|
|
||
|
|
subtest 'a batch is already running for the user, new batch creation should not fail' => sub {
|
||
|
|
my $batch_id = $rpcapi->add_batch_job(
|
||
|
|
{
|
||
|
|
%$user,
|
||
|
|
domains => \@domains,
|
||
|
|
test_params => $params
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
is( $batch_id, 2, 'same user can create another batch' );
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'use another user' => sub {
|
||
|
|
my $another_user = { username => 'another', api_key => 'token' };
|
||
|
|
$rpcapi->add_api_user( $another_user );
|
||
|
|
my $batch_id = $rpcapi->add_batch_job(
|
||
|
|
{
|
||
|
|
%$another_user,
|
||
|
|
domains => \@domains,
|
||
|
|
test_params => $params
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
is( $batch_id, 3, 'another_user can create another batch' );
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'duplicate user should fail' => sub {
|
||
|
|
my $config = Zonemaster::Backend::Config->parse( $config );
|
||
|
|
my $rpcapi = init_backend( $config );
|
||
|
|
|
||
|
|
# do not output any error message
|
||
|
|
my $printerror_before = $rpcapi->{db}->dbh->{PrintError};
|
||
|
|
$rpcapi->{db}->dbh->{PrintError} = 0;
|
||
|
|
|
||
|
|
dies_ok {
|
||
|
|
$rpcapi->add_api_user( { username => $user->{username}, api_key => "another api key" } );
|
||
|
|
} 'a user with the same username already exists, add_api_user should die';
|
||
|
|
my $res = $@;
|
||
|
|
is( $res->{error}, 'Zonemaster::Backend::Error::Conflict', 'correct error type' );
|
||
|
|
is( $res->{message}, 'User already exists', 'correct error message' );
|
||
|
|
is( $res->{data}->{username}, $user->{username}, 'correct data type returned' );
|
||
|
|
|
||
|
|
# reset attribute value
|
||
|
|
$rpcapi->{db}->dbh->{PrintError} = $printerror_before;
|
||
|
|
};
|
||
|
|
|
||
|
|
subtest 'normalize "domain" column' => sub {
|
||
|
|
my $config = Zonemaster::Backend::Config->parse( $config );
|
||
|
|
my $rpcapi = init_backend( $config );
|
||
|
|
my $dbh = $rpcapi->{db}->dbh;
|
||
|
|
|
||
|
|
my %domains_to_test = (
|
||
|
|
"aFnIc.Fr" => "afnic.fr",
|
||
|
|
"afnic.fr." => "afnic.fr",
|
||
|
|
"aFnic.Fr." => "afnic.fr"
|
||
|
|
);
|
||
|
|
my @domains = keys %domains_to_test;
|
||
|
|
|
||
|
|
my $batch_id = $rpcapi->add_batch_job(
|
||
|
|
{
|
||
|
|
%$user,
|
||
|
|
domains => \@domains,
|
||
|
|
test_params => $params
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
my @db_domain = map { $$_[0] } $dbh->selectall_array( "SELECT domain FROM test_results WHERE batch_id=?", undef, $batch_id );
|
||
|
|
|
||
|
|
is( @db_domain, 3, '3 tests created' );
|
||
|
|
my @expected = values %domains_to_test;
|
||
|
|
is_deeply( \@db_domain, \@expected, 'domains are normalized' );
|
||
|
|
};
|
||
|
|
|
||
|
|
# TODO: create an agent and run batch tests
|
||
|
|
|
||
|
|
## Create the agent
|
||
|
|
#use_ok( 'Zonemaster::Backend::TestAgent' );
|
||
|
|
#my $agent = Zonemaster::Backend::TestAgent->new( { dbtype => "$db_backend", config => $config } );
|
||
|
|
#isa_ok($agent, 'Zonemaster::Backend::TestAgent', 'agent');
|
||
|
|
|
||
|
|
done_testing();
|