You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ngcp-panel/t/lib/NGCP/TestFramework.pm

238 lines
9.4 KiB

package NGCP::TestFramework;
use strict;
use warnings;
use Cpanel::JSON::XS;
use Data::Walk;
use DateTime qw();
use DateTime::Format::Strptime qw();
use DateTime::Format::ISO8601 qw();
use Digest::MD5 qw/md5_hex/;
use Log::Log4perl qw(:easy);
use Moose;
use Net::Domain qw(hostfqdn);
use Test::More;
use URI;
use YAML::XS qw(LoadFile);
use Data::Dumper;
use NGCP::TestFramework::RequestBuilder;
use NGCP::TestFramework::Client;
use NGCP::TestFramework::TestExecutor;
has 'file_path' => (
isa => 'Str',
is => 'ro'
);
sub run {
my ( $self ) = @_;
my $test_case_name = $self->file_path;
$test_case_name =~ s/.+\/(\w+).yaml/$1/;
chomp $test_case_name;
Log::Log4perl->easy_init( { level => $DEBUG,
file => ">>/var/log/ngcp/test-framework/$test_case_name.log",
category => "TestFramework::Client",
layout => '%d - %F{1} line %L - %M: %m%n' },
{ level => $DEBUG,
file => ">>/var/log/ngcp/test-framework/$test_case_name.log",
category => "TestFramework::RequestBuilder",
layout => '%d - %F{1} line %L - %M: %m%n' },
{ level => $DEBUG,
file => ">>/var/log/ngcp/test-framework/$test_case_name.log",
category => "TestFramework::TestExecutor",
layout => '%d - %F{1} line %L - %M: %m%n' },
{ level => $DEBUG,
file => ">/var/log/ngcp/test-framework/$test_case_name.log",
layout => '%d - %F{1} line %L - %M: %m%n' }
);
INFO( "Started running the Test TestFramework!" );
unless ( $self->file_path ) {
return;
}
$YAML::XS::DumpCode = 1;
$YAML::XS::LoadCode = 1;
$YAML::XS::UseCode = 1;
$YAML::XS::LoadBlessed = 1;
INFO( "Loading YAML file." );
my $testing_data = LoadFile($self->file_path);
INFO( "Setting up the base URI." );
my $base_uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
INFO( "Setting up the RequestBuilder." );
my $request_builder = NGCP::TestFramework::RequestBuilder->new({ base_uri => $base_uri });
INFO( "Setting up the Client." );
my $client = NGCP::TestFramework::Client->new( { uri => $base_uri } );
INFO( "Setting up the Test Executor." );
my $test_executor = NGCP::TestFramework::TestExecutor->new();
# initializing time to add to fields which need to be unique
my $retained = { unique_id => int(rand(100000)) };
my $test_case_result = { success => 1, error_count => 0 };
foreach my $test ( @$testing_data ) {
DEBUG( "In test '".$test->{name}."'" );
next if ( $test->{skip} );
# build request
my $request = $request_builder->build({
method => $test->{method},
path => $test->{path},
header => $test->{header} || undef,
content => $test->{content} || undef,
retain => $retained
});
DEBUG ( "Request: ".Dumper $request );
# handle separate types
if ( $test->{type} eq 'item' ) {
INFO( "Performing request." );
my $result = $client->perform_request($request);
DEBUG ( "Result: ".Dumper $result );
if ( $test->{retain} ) {
INFO( "Storing retained variables." );
$self->_get_retained_elements( $test->{retain}, $retained, $result );
}
if ( $test->{perl_code} ){
INFO( "Executing perl code." );
my $sub = $test->{perl_code};
$sub->( $retained );
}
if ( $test->{conditions} ) {
INFO( "Running tests." );
my $tests_result = $test_executor->run_tests( $test->{conditions}, $result, $retained, $test->{name} );
if ( !$tests_result->{success} ) {
map { print $_." in test case '$test_case_name'\n" } @{$tests_result->{errors}};
$test_case_result->{success} = 0;
$test_case_result->{error_count} += scalar @{$tests_result->{errors}};
}
}
}
elsif ( $test->{type} eq 'batch' ) {
foreach my $iteration ( 1..$test->{iterations} ) {
INFO( "Performing request for iteration $iteration." );
my $result = $client->perform_request($request);
DEBUG ( "Result: ".Dumper $result );
if ( $test->{retain} ) {
INFO( "Storing retained variables." );
$self->_get_retained_elements( $test->{retain}, $retained, $result );
}
if ( $test->{conditions} ) {
INFO( "Running tests." );
my $tests_result = $test_executor->run_tests( $test->{conditions}, $result, $retained, $test->{name} );
if ( !$tests_result->{success} ) {
map { print $_." in test case '$test_case_name'\n" } @{$tests_result->{errors}};
$test_case_result->{success} = 0;
$test_case_result->{error_count} += scalar @{$tests_result->{errors}};
}
}
$retained->{unique_id}=int(rand(100000));
}
}
elsif ( $test->{type} eq 'pagination' ) {
my $nexturi = $test->{path};
do {
INFO( "Performing request for pagination." );
$request->uri( $base_uri.$nexturi );
my $result = $client->perform_request($request);
DEBUG ( "Result: ".Dumper $result );
if ( $test->{retain} ) {
INFO( "Storing retained variables." );
$self->_get_retained_elements( $test->{retain}, $retained, $result );
}
my $body = decode_json( $result->decoded_content() );
#build default conditions for pagination
$test->{conditions}->{is}->{$nexturi} = $body->{_links}->{self}->{href};
my $colluri = URI->new($base_uri.$body->{_links}->{self}->{href});
my %q = $colluri->query_form;
$test->{conditions}->{ok}->{$q{page}} = 'defined';
$test->{conditions}->{ok}->{$q{rows}} = 'defined';
my $page = int($q{page});
my $rows = int($q{rows});
if($page == 1) {
$test->{conditions}->{ok}->{'${collection}._links.prev.href'} = 'undefined';
} else {
$test->{conditions}->{ok}->{'${collection}._links.prev.href'} = 'defined';
}
if(($retained->{collection}->{total_count} / $rows) <= $page) {
$test->{conditions}->{ok}->{'${collection}._links.next.href'} = 'undefined';
} else {
$test->{conditions}->{ok}->{'${collection}._links.next.href'} = 'defined';
}
if ( $test->{conditions} ) {
INFO( "Running tests." );
my $tests_result = $test_executor->run_tests( $test->{conditions}, $result, $retained, $test->{name} );
if ( !$tests_result->{success} ) {
map { print $_." in test case '$test_case_name'\n" } @{$tests_result->{errors}};
$test_case_result->{success} = 0;
$test_case_result->{error_count} += scalar @{$tests_result->{errors}};
}
}
if( $body->{_links}->{next}->{href} ) {
$nexturi = $body->{_links}->{next}->{href};
} else {
$nexturi = undef;
}
} while ( $nexturi )
}
}
return $test_case_result;
}
sub _get_retained_elements {
my ( $self, $retain, $retained, $result ) = @_;
while ( my ( $retain_elem, $retain_value ) = each %{$retain} ) {
if ( $retain_value =~ /.+\..+/ ) {
my @splitted_values = split (/\./, $retain_value);
$retained->{$retain_elem} = $self->_retrieve_from_composed_key( $result, \@splitted_values, $retain_elem );
}
elsif ( $retain_value eq 'body' ) {
$retained->{$retain_elem} = decode_json( $result->decoded_content() );
}
else {
return {
success => 0,
message => 'Wrong retain instructions!'
}
}
}
}
sub _retrieve_from_composed_key {
my ( $self, $result, $splitted_values, $retain_elem ) = @_;
if ( $splitted_values->[0] eq 'header' ) {
my $value = $result->header(ucfirst $splitted_values->[1]);
if ( $retain_elem =~ /^.+_id$/ ) {
$value =~ /^.+\/(\d+)$/;
$value = $1;
}
return $value;
}
}
sub _variables_available {
my( $self, $retained, $test ) = @_;
return 0 if ( $test->{path} =~ /\$\{(.*)\}/ && !$retained->{$1} );
# substitute variables in content
if ( $test->{content} && ref $test->{content} eq 'HASH' ) {
foreach my $content_key (keys %{$test->{content}}) {
return 0 if ( $test->{content}->{$content_key} =~ /\$\{(.*)\}/ && !$retained->{$1} );
}
}
return 1;
}
1;