* includes basic scenarios and pagination tests for Contracts * added threading support * a number of threads retrieve test cases and run them in parallel, completely isolated from the other test cases * deep comparison of data structures with is_deeply * perl code in YAML for complex testing scenarios * migrated test cases for Calls, BillingNetworks, Customer Change-Id: I6a58b753309fce570544a7c3f28959ee07d9aeb6changes/76/29576/5
parent
263f97a0dd
commit
818f22c5c7
@ -0,0 +1,180 @@
|
||||
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 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 ) = @_;
|
||||
|
||||
unless ( $self->file_path ) {
|
||||
return;
|
||||
}
|
||||
$YAML::XS::DumpCode = 1;
|
||||
$YAML::XS::LoadCode = 1;
|
||||
$YAML::XS::UseCode = 1;
|
||||
$YAML::XS::LoadBlessed = 1;
|
||||
|
||||
my $testing_data = LoadFile($self->file_path);
|
||||
|
||||
my $base_uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
|
||||
my $request_builder = NGCP::TestFramework::RequestBuilder->new({ base_uri => $base_uri });
|
||||
my $client = NGCP::TestFramework::Client->new( { uri => $base_uri, log_debug => 0 } );
|
||||
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)) };
|
||||
|
||||
foreach my $test ( @$testing_data ) {
|
||||
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
|
||||
});
|
||||
|
||||
# handle separate types
|
||||
if ( $test->{type} eq 'item' ) {
|
||||
my $result = $client->perform_request($request);
|
||||
if ( $test->{retain} ) {
|
||||
$self->_get_retained_elements( $test->{retain}, $retained, $result );
|
||||
}
|
||||
if ( $test->{operations} ) {
|
||||
$self->_perform_operations( $test->{operations}, $retained );
|
||||
}
|
||||
if ( $test->{perl_code} ){
|
||||
my $sub = $test->{perl_code};
|
||||
warn Dumper $sub;
|
||||
$sub->( $retained );
|
||||
}
|
||||
$test_executor->run_tests( $test->{conditions}, $result, $retained, $test->{name} ) if ( $test->{conditions} );
|
||||
}
|
||||
elsif ( $test->{type} eq 'batch' ) {
|
||||
foreach my $iteration ( 1..$test->{iterations} ) {
|
||||
my $result = $client->perform_request($request);
|
||||
if ( $test->{retain} ) {
|
||||
$self->_get_retained_elements( $test->{retain}, $retained, $result );
|
||||
}
|
||||
if ( $test->{operations} ) {
|
||||
$self->_perform_operations( $test->{operations}, $retained );
|
||||
}
|
||||
$test_executor->run_tests( $test->{conditions}, $result, $retained, $test->{name} ) if ( $test->{conditions} );
|
||||
}
|
||||
}
|
||||
elsif ( $test->{type} eq 'pagination' ) {
|
||||
my $nexturi = $test->{path};
|
||||
do {
|
||||
$request->uri( $base_uri.$nexturi );
|
||||
my $result = $client->perform_request($request);
|
||||
if ( $test->{retain} ) {
|
||||
$self->_get_retained_elements( $test->{retain}, $retained, $result );
|
||||
}
|
||||
if ( $test->{operations} ) {
|
||||
$self->_perform_operations( $test->{operations}, $retained );
|
||||
}
|
||||
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';
|
||||
}
|
||||
|
||||
$test_executor->run_tests( $test->{conditions}, $result, $retained, $test->{name} ) if ( $test->{conditions} );
|
||||
|
||||
if( $body->{_links}->{next}->{href} ) {
|
||||
$nexturi = $body->{_links}->{next}->{href};
|
||||
} else {
|
||||
$nexturi = undef;
|
||||
}
|
||||
} while ( $nexturi )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
@ -0,0 +1,191 @@
|
||||
package NGCP::TestFramework::Client;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
use Digest::MD5 qw/md5_hex/;
|
||||
use IO::Uncompress::Unzip;
|
||||
use LWP::UserAgent;
|
||||
use Moose;
|
||||
use Time::HiRes qw/gettimeofday tv_interval/;
|
||||
|
||||
has 'username' => (
|
||||
isa => 'Str',
|
||||
is => 'ro',
|
||||
default => sub {
|
||||
$ENV{API_USER} // 'administrator';
|
||||
}
|
||||
);
|
||||
|
||||
has 'password' => (
|
||||
isa => 'Str',
|
||||
is => 'ro',
|
||||
default => sub {
|
||||
$ENV{API_PASS} // 'administrator';
|
||||
}
|
||||
);
|
||||
|
||||
has 'role' => (
|
||||
isa => 'Str',
|
||||
is => 'ro',
|
||||
default => 'admin',
|
||||
);
|
||||
|
||||
has 'uri' => (
|
||||
isa => 'Str',
|
||||
is => 'ro',
|
||||
default => sub { $ENV{CATALYST_SERVER}; },
|
||||
);
|
||||
|
||||
has 'sub_uri' => (
|
||||
isa => 'Str',
|
||||
is => 'ro',
|
||||
default => sub { $ENV{CATALYST_SERVER_SUB}; },
|
||||
);
|
||||
|
||||
has '_uri' => (
|
||||
isa => 'Maybe[Str]',
|
||||
is => 'rw',
|
||||
);
|
||||
|
||||
has 'verify_ssl' => (
|
||||
isa => 'Int',
|
||||
is => 'ro',
|
||||
default => 0,
|
||||
);
|
||||
|
||||
has 'log_debug' => (
|
||||
isa => 'Bool',
|
||||
is => 'rw',
|
||||
default => 0,
|
||||
);
|
||||
|
||||
has '_crt_path' => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
my ($self) = @_;
|
||||
return '/tmp/' . md5_hex($self->username) . ".crt";
|
||||
}
|
||||
);
|
||||
|
||||
has 'last_rtt' => (
|
||||
is => 'rw',
|
||||
isa => 'Num',
|
||||
default => 0,
|
||||
);
|
||||
|
||||
has '_ua' => (
|
||||
isa => 'LWP::UserAgent',
|
||||
is => 'ro',
|
||||
lazy => 1,
|
||||
builder => '_build_ua'
|
||||
);
|
||||
|
||||
sub _build_ua {
|
||||
my $self = shift;
|
||||
|
||||
my $ua = LWP::UserAgent->new(keep_alive => 1);
|
||||
my $uri;
|
||||
if($self->role eq "admin" || $self->role eq "reseller") {
|
||||
$uri = $self->uri;
|
||||
} else {
|
||||
$uri = $self->sub_uri;
|
||||
}
|
||||
$self->_uri($uri);
|
||||
$self->debug("client using uri $uri\n");
|
||||
$uri =~ s/^https?:\/\///;
|
||||
$self->debug("client using ip:port $uri\n");
|
||||
my $realm;
|
||||
if($self->role eq 'admin' || $self->role eq 'reseller') {
|
||||
$realm = 'api_admin_http';
|
||||
} elsif($self->role eq 'subscriber') {
|
||||
$realm = 'api_subscriber_http';
|
||||
}
|
||||
$self->debug("client using realm $realm with user=" . $self->username . " and pass " . $self->password . "\n");
|
||||
$ua->credentials($uri, $realm, $self->username, $self->password);
|
||||
unless($self->verify_ssl) {
|
||||
$ua->ssl_opts(
|
||||
verify_hostname => 0,
|
||||
SSL_verify_mode => 0,
|
||||
);
|
||||
}
|
||||
if($self->role eq "admin" || $self->role eq "reseller") {
|
||||
unless(-f $self->_crt_path) {
|
||||
|
||||
# we have to setup a new connection here, because if we're already connected,
|
||||
# the connection will be re-used, thus no cert is used
|
||||
my $tmpua = LWP::UserAgent->new;
|
||||
$tmpua->credentials($uri, $realm, $self->username, $self->password);
|
||||
unless($self->verify_ssl) {
|
||||
$tmpua->ssl_opts(
|
||||
verify_hostname => 0,
|
||||
SSL_verify_mode => 0,
|
||||
);
|
||||
}
|
||||
|
||||
my $res = $tmpua->post(
|
||||
$self->_uri . '/api/admincerts/',
|
||||
Content_Type => 'application/json',
|
||||
Content => '{}'
|
||||
);
|
||||
unless($res->is_success) {
|
||||
die "Failed to fetch client certificate: " . $res->status_line . "\n";
|
||||
}
|
||||
my $zip = $res->decoded_content;
|
||||
my $z = IO::Uncompress::Unzip->new(\$zip, MultiStream => 0, Append => 1);
|
||||
my $data;
|
||||
while(!$z->eof() && (my $hdr = $z->getHeaderInfo())) {
|
||||
unless($hdr->{Name} =~ /\.pem$/) {
|
||||
# wrong file, just read stream, clear buffer and try next
|
||||
while($z->read($data) > 0) {}
|
||||
$data = undef;
|
||||
$z->nextStream();
|
||||
next;
|
||||
}
|
||||
while($z->read($data) > 0) {}
|
||||
last;
|
||||
}
|
||||
$z->close();
|
||||
unless($data) {
|
||||
die "Failed to find PEM file in client certificate zip file\n";
|
||||
}
|
||||
open my $fh, ">:raw", $self->_crt_path
|
||||
or die "Failed to open " . $self->_crt_path . ": $!\n";
|
||||
print $fh $data;
|
||||
close $fh;
|
||||
}
|
||||
$ua->ssl_opts(
|
||||
SSL_cert_file => $self->_crt_path,
|
||||
SSL_key_file => $self->_crt_path,
|
||||
);
|
||||
}
|
||||
return $ua;
|
||||
}
|
||||
|
||||
|
||||
sub perform_request {
|
||||
my ($self, $req) = @_;
|
||||
my $t0 = [gettimeofday];
|
||||
$self->debug("content of " . $req->method . " request to " . $req->uri . ":\n");
|
||||
$self->debug($req->content || "<empty request>");
|
||||
$self->debug("\n");
|
||||
my $res = $self->_ua->request($req);
|
||||
my $rtt = tv_interval($t0);
|
||||
$self->last_rtt($rtt);
|
||||
$self->debug("content of response:\n");
|
||||
$self->debug($res->decoded_content || "<empty response>");
|
||||
$self->debug("\n");
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub debug {
|
||||
my ($self, $msg) = @_;
|
||||
if($self->log_debug) {
|
||||
print $msg;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -0,0 +1,655 @@
|
||||
---
|
||||
#check options
|
||||
-
|
||||
name: check OPTIONS for billingnetworks
|
||||
type: item
|
||||
method: OPTIONS
|
||||
path: /api/billingnetworks/
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
header:
|
||||
Accept-Post: application/hal+json; profile=http://purl.org/sipwise/ngcp-api/#rel-billingnetworks
|
||||
ok:
|
||||
options:
|
||||
- GET
|
||||
- HEAD
|
||||
- OPTIONS
|
||||
- POST
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
$retained->{blocks} = [{ip=>'fdfe::5a55:caff:fefa:9089',mask=>128},
|
||||
{ip=>'fdfe::5a55:caff:fefa:908a'},
|
||||
{ip=>'fdfe::5a55:caff:fefa:908b',mask=>128},];
|
||||
}
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content:
|
||||
name: test billing network ${unique_id}
|
||||
description: test billing network description ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks: ${blocks}
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork: body
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
|
||||
#PUT test billingnetwork
|
||||
-
|
||||
name: PUT test billingnetwork
|
||||
type: item
|
||||
method: PUT
|
||||
path: '/${billingnetwork_path}'
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content:
|
||||
name: test billingnetwork PUT ${unique_id}
|
||||
description: test billing network description PUT ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks: ${blocks}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch PUT test billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork: body
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
|
||||
#PATCH test billingnetwork
|
||||
-
|
||||
name: PATCH test billingnetwork
|
||||
type: item
|
||||
method: PATCH
|
||||
path: '/${billingnetwork_path}'
|
||||
header:
|
||||
Content-Type: application/json-patch+json
|
||||
Prefer: return=representation
|
||||
content:
|
||||
-
|
||||
op: replace
|
||||
path: /name
|
||||
value: test billingnetwork PATCH ${unique_id}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch PATCHed test billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork: body
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
|
||||
#DELETE billingnetwork
|
||||
-
|
||||
name: terminate test billingnetwork
|
||||
type: item
|
||||
method: DELETE
|
||||
path: '${billingnetwork_path}'
|
||||
conditions:
|
||||
is:
|
||||
code: 204
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: try to fetch terminated billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork: body
|
||||
conditions:
|
||||
is:
|
||||
code: 404
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv6 billing network 1 ${unique_id}
|
||||
description: test ipv6 billing network description 1 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: 'fdfe::5a55:caff:fefa:9089'
|
||||
mask: 128
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv6_1: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv6_1}->{id};
|
||||
delete $retained->{billingnetwork_ipv6_1}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv6_1}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv6 billing network 2 ${unique_id}
|
||||
description: test ipv6 billing network description 2 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: 'fdfe::5a55:caff:fefa:908a'
|
||||
mask: null
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv6_2: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv6_2}->{id};
|
||||
delete $retained->{billingnetwork_ipv6_2}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv6_2}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv6 billing network 3 ${unique_id}
|
||||
description: test ipv6 billing network description 3 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: 'fdfe::5a55:caff:fefa:908b'
|
||||
mask: 128
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv6_3: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv6_3}->{id};
|
||||
delete $retained->{billingnetwork_ipv6_3}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv6_3}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv6 billing network 4 ${unique_id}
|
||||
description: test ipv6 billing network description 4 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: 'fdfe::5a55:caff:fefa:9089'
|
||||
mask: 128
|
||||
-
|
||||
ip: 'fdfe::5a55:caff:fefa:908a'
|
||||
mask: null
|
||||
-
|
||||
ip: 'fdfe::5a55:caff:fefa:908b'
|
||||
mask: 128
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv6_4: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv6_4}->{id};
|
||||
delete $retained->{billingnetwork_ipv6_4}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv6_4}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv4 billing network 1 ${unique_id}
|
||||
description: test ipv4 billing network description 1 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: '10.0.4.7'
|
||||
mask: 26
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv4_1: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv4_1}->{id};
|
||||
delete $retained->{billingnetwork_ipv4_1}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv4_1}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv4 billing network 2 ${unique_id}
|
||||
description: test ipv4 billing network description 2 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: '10.0.4.99'
|
||||
mask: 26
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv4_2: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv4_2}->{id};
|
||||
delete $retained->{billingnetwork_ipv4_2}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv4_2}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv4 billing network 3 ${unique_id}
|
||||
description: test ipv4 billing network description 3 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: '10.0.5.9'
|
||||
mask: 24
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv4_3: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv4_3}->{id};
|
||||
delete $retained->{billingnetwork_ipv4_3}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv4_3}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv4 billing network 4 ${unique_id}
|
||||
description: test ipv4 billing network description 4 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: '10.0.6.9'
|
||||
mask: 24
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv4_4: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv4_4}->{id};
|
||||
delete $retained->{billingnetwork_ipv4_4}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv4_4}': *content
|
||||
|
||||
#POST test billingnetwork
|
||||
-
|
||||
name: POST test billingnetwork
|
||||
type: item
|
||||
method: POST
|
||||
path: /api/billingnetworks/
|
||||
header:
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
content: &content
|
||||
name: test ipv4 billing network 5 ${unique_id}
|
||||
description: test ipv4 billing network description 5 ${unique_id}
|
||||
reseller_id: 1
|
||||
blocks:
|
||||
-
|
||||
ip: '10.0.4.7'
|
||||
mask: 26
|
||||
-
|
||||
ip: '10.0.4.99'
|
||||
mask: 26
|
||||
-
|
||||
ip: '10.0.5.9'
|
||||
mask: 24
|
||||
-
|
||||
ip: '10.0.6.9'
|
||||
mask: 24
|
||||
status: active
|
||||
retain:
|
||||
billingnetwork_path: header.location
|
||||
conditions:
|
||||
is:
|
||||
code: 201
|
||||
|
||||
#GET billingnetwork
|
||||
-
|
||||
name: fetch POSTed billingnetwork
|
||||
type: item
|
||||
method: GET
|
||||
path: '/${billingnetwork_path}'
|
||||
retain:
|
||||
billingnetwork_ipv4_5: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
delete $retained->{billingnetwork_ipv4_5}->{id};
|
||||
delete $retained->{billingnetwork_ipv4_5}->{_links};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${billingnetwork_ipv4_5}': *content
|
||||
|
||||
#compare filtered collection
|
||||
-
|
||||
name: compare filtered collection
|
||||
type: item
|
||||
method: GET
|
||||
path: '/api/billingnetworks/?page=1&rows=5&ip=fdfe::5a55:caff:fefa:9089&name=%25${unique_id}'
|
||||
retain:
|
||||
collection: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
$retained->{expected} = [ $retained->{billingnetwork_ipv6_1}, $retained->{billingnetwork_ipv6_4} ];
|
||||
map { delete $_->{id} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
map { delete $_->{_links} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${collection}._embedded.ngcp:billingnetworks': ${expected}
|
||||
|
||||
#compare filtered collection
|
||||
-
|
||||
name: compare filtered collection
|
||||
type: item
|
||||
method: GET
|
||||
path: '/api/billingnetworks/?page=1&rows=5&ip=10.0.4.0&name=%25${unique_id}'
|
||||
retain:
|
||||
collection: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
$retained->{expected} = [ $retained->{billingnetwork_ipv4_1}, $retained->{billingnetwork_ipv4_5} ];
|
||||
map { delete $_->{id} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
map { delete $_->{_links} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${collection}._embedded.ngcp:billingnetworks': ${expected}
|
||||
|
||||
#compare filtered collection
|
||||
-
|
||||
name: compare filtered collection
|
||||
type: item
|
||||
method: GET
|
||||
path: '/api/billingnetworks/?page=1&rows=5&ip=10.0.4.64&name=%25${unique_id}'
|
||||
retain:
|
||||
collection: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
$retained->{expected} = [ $retained->{billingnetwork_ipv4_2}, $retained->{billingnetwork_ipv4_5} ];
|
||||
map { delete $_->{id} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
map { delete $_->{_links} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${collection}._embedded.ngcp:billingnetworks': ${expected}
|
||||
|
||||
#compare filtered collection
|
||||
-
|
||||
name: compare filtered collection
|
||||
type: item
|
||||
method: GET
|
||||
path: '/api/billingnetworks/?page=1&rows=5&ip=10.0.5.255&name=%25${unique_id}'
|
||||
retain:
|
||||
collection: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
$retained->{expected} = [ $retained->{billingnetwork_ipv4_3}, $retained->{billingnetwork_ipv4_5} ];
|
||||
map { delete $_->{id} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
map { delete $_->{_links} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${collection}._embedded.ngcp:billingnetworks': ${expected}
|
||||
|
||||
#compare filtered collection
|
||||
-
|
||||
name: compare filtered collection
|
||||
type: item
|
||||
method: GET
|
||||
path: '/api/billingnetworks/?page=1&rows=5&ip=10.0.6.255&name=%25${unique_id}'
|
||||
retain:
|
||||
collection: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
$retained->{expected} = [ $retained->{billingnetwork_ipv4_4}, $retained->{billingnetwork_ipv4_5} ];
|
||||
map { delete $_->{id} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
map { delete $_->{_links} } @{$retained->{collection}->{'_embedded'}->{'ngcp:billingnetworks'}};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
is_deeply:
|
||||
'${collection}._embedded.ngcp:billingnetworks': ${expected}
|
@ -0,0 +1,35 @@
|
||||
---
|
||||
#get a subscriber for testing
|
||||
-
|
||||
name: get a subscriber for testing
|
||||
type: item
|
||||
method: GET
|
||||
path: '/api/subscribers/?page=1&rows=1&order_by=id&order_by_direction=desc'
|
||||
retain:
|
||||
subscriber: body
|
||||
perl_code: !!perl/code |
|
||||
{
|
||||
my ($retained) = @_;
|
||||
my $subscriber = $retained->{subscriber}->{'_embedded'}->{'ngcp:subscribers'}->[0];
|
||||
$retained->{subscriber} = $subscriber;
|
||||
$retained->{subscriber_id} = $subscriber->{id};
|
||||
}
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
ok:
|
||||
'${subscriber}.id': defined
|
||||
|
||||
#fetch calls for subscriber
|
||||
-
|
||||
name: get a subscriber for testing
|
||||
type: item
|
||||
method: GET
|
||||
path: '/api/calls/?page=1&rows=10&subscriber_id=${subscriber_id}'
|
||||
retain:
|
||||
calls: body
|
||||
conditions:
|
||||
is:
|
||||
code: 200
|
||||
ok:
|
||||
'${calls}.total_count': defined
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,105 @@
|
||||
package NGCP::TestFramework::RequestBuilder;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use HTTP::Request;
|
||||
use Cpanel::JSON::XS;
|
||||
use Moose;
|
||||
use Data::Dumper;
|
||||
|
||||
has 'base_uri' => (
|
||||
isa => 'Str',
|
||||
is => 'ro'
|
||||
);
|
||||
|
||||
sub build {
|
||||
my ( $self, $args ) = @_;
|
||||
|
||||
my @methods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'CONNECT', 'TRACE'];
|
||||
|
||||
if ( !$args->{method} && !grep { $_ eq $args->{method} } @methods ) {
|
||||
return {
|
||||
success => 0,
|
||||
message => 'HTTP method missing or incorrect!'
|
||||
};
|
||||
}
|
||||
|
||||
if ( !$args->{path} ) {
|
||||
return {
|
||||
success => 0,
|
||||
message => 'Path missing!'
|
||||
};
|
||||
}
|
||||
|
||||
$self->_replace_vars($args);
|
||||
|
||||
my $req = HTTP::Request->new( $args->{method}, $self->base_uri.$args->{path} );
|
||||
grep { $req->header( $_ => $args->{header}->{$_} ) } keys %{$args->{header}} if $args->{header};
|
||||
$req->content( encode_json( $args->{content} ) ) if $args->{content};
|
||||
|
||||
return $req;
|
||||
}
|
||||
|
||||
sub _replace_vars {
|
||||
my ( $self, $args ) = @_;
|
||||
|
||||
# substitute variables in path
|
||||
if ( $args->{path} =~ /\$\{(.*)\}/ ) {
|
||||
$args->{path} =~ s/\$\{(.*)\}/$args->{retain}->{$1}/;
|
||||
}
|
||||
|
||||
# substitute variables in content
|
||||
if ( $args->{content} ) {
|
||||
if ( ref $args->{content} eq 'HASH' ) {
|
||||
foreach my $content_key (keys %{$args->{content}}) {
|
||||
if ( $args->{content}->{$content_key} && $args->{content}->{$content_key} =~ /\$\{(.*)\}$/ ) {
|
||||
if ( ref $args->{retain}->{$1} eq 'ARRAY' || ref $args->{retain}->{$1} eq 'HASH' ) {
|
||||
$args->{content}->{$content_key} = $args->{retain}->{$1};
|
||||
}
|
||||
else {
|
||||
$args->{content}->{$content_key} =~ s/\$\{(.*)\}/$args->{retain}->{$1}/;
|
||||
}
|
||||
}
|
||||
elsif ( $args->{content}->{$content_key} && $args->{content}->{$content_key} =~ /^\$\{(.*)\}\..+/ ) {
|
||||
my @splitted_values = split (/\./, $args->{content}->{$content_key});
|
||||
$args->{content}->{$content_key} = $self->_retrieve_from_composed_key( \@splitted_values, $args->{retain} );
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ( ref $args->{content} eq 'ARRAY' ) {
|
||||
foreach my $content ( @{$args->{content}} ) {
|
||||
foreach my $content_key (keys %$content) {
|
||||
if ( $content->{$content_key} && $content->{$content_key} =~ /\$\{(.*)\}$/ ) {
|
||||
if ( ref $args->{retain}->{$1} eq 'ARRAY' || ref $args->{retain}->{$1} eq 'HASH' ) {
|
||||
$content->{$content_key} = $args->{retain}->{$1};
|
||||
}
|
||||
else {
|
||||
$content->{$content_key} =~ s/\$\{(.*)\}/$args->{retain}->{$1}/;
|
||||
}
|
||||
}
|
||||
elsif ( $content->{$content_key} && $content->{$content_key} =~ /^\$\{(.*)\}\..+/ ) {
|
||||
my @splitted_values = split (/\./, $content->{$content_key});
|
||||
$content->{$content_key} = $self->_retrieve_from_composed_key( \@splitted_values, $args->{retain} );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( $args->{content} =~ /\$\{(.*)\}/ ) {
|
||||
$args->{content} = $args->{retain}->{$1};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _retrieve_from_composed_key {
|
||||
my ( $self, $splitted_values, $retained ) = @_;
|
||||
|
||||
if ( $splitted_values->[0] =~ /\$\{(.*)\}/ ) {
|
||||
my $value = $retained->{$1};
|
||||
grep { $value = $value->{$splitted_values->[$_]} } (1..(scalar @$splitted_values - 1));
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
@ -0,0 +1,115 @@
|
||||
package NGCP::TestFramework::TestExecutor;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cpanel::JSON::XS;
|
||||
use Data::Walk;
|
||||
use Moose;
|
||||
use Test::More;
|
||||
use Data::Dumper;
|
||||
|
||||
sub run_tests {
|
||||
my ( $self, $conditions, $result, $retained, $test_name ) = @_;
|
||||
|
||||
foreach my $condition ( keys %$conditions ) {
|
||||
if ( $condition eq 'is' ) {
|
||||
while ( my ( $check_param, $check_value ) = each %{$conditions->{$condition}} ) {
|
||||
if ( $check_value =~ /^\$\{(.*)\}$/ ) {
|
||||
$check_value = $retained->{$1};
|
||||
}
|
||||
if ( $check_param =~ /^\$\{(.*)\}$/ ) {
|
||||
$check_param = $retained->{$1};
|
||||
}
|
||||
if ( $check_param =~ /.+\..+/ ) {
|
||||
my @splitted_values = split (/\./, $check_param);
|
||||
$check_param = $self->_retrieve_from_composed_key( $result, \@splitted_values, $retained );
|
||||
is ($check_param, $check_value, $test_name);
|
||||
}
|
||||
elsif ( $check_param eq 'code' ) {
|
||||
is ($result->code, $check_value, $test_name);
|
||||
}
|
||||
elsif ( $check_param eq 'header' ) {
|
||||
foreach my $header_condition ( keys %{$conditions->{$condition}->{$check_param}} ) {
|
||||
is ($result->header($header_condition), $check_value->{$header_condition}, $test_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
is ($check_param, $check_value, $test_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ( $condition eq 'ok' ) {
|
||||
foreach my $check_param (keys %{$conditions->{$condition}}) {
|
||||
if ( $check_param eq 'options' ) {
|
||||
my $body = decode_json($result->decoded_content);
|
||||
my @hopts = split /\s*,\s*/, $result->header('Allow');
|
||||
ok(exists $body->{methods} && ref $body->{methods} eq "ARRAY", $test_name);
|
||||
foreach my $opt(@{$conditions->{$condition}->{$check_param}}) {
|
||||
ok(grep { /^$opt$/ } @hopts, $test_name);
|
||||
ok(grep { /^$opt$/ } @{ $body->{methods} }, $test_name);
|
||||
}
|
||||
}
|
||||
if ( $conditions->{$condition}->{$check_param} eq 'defined' || $conditions->{$condition}->{$check_param} eq 'undefined') {
|
||||
if ( $check_param =~ /.+\..+/ ) {
|
||||
my @splitted_values = split (/\./, $check_param);
|
||||
my $check_value = $self->_retrieve_from_composed_key( $result, \@splitted_values, $retained );
|
||||
$conditions->{$condition}->{$check_param} eq 'defined' ?
|
||||
ok(defined $check_value, $test_name) : ok(!defined $check_value, $test_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ( $condition eq 'like' ) {
|
||||
foreach my $check_param (keys %{$conditions->{$condition}}) {
|
||||
if ( $check_param =~ /.+\..+/ ) {
|
||||
my @splitted_values = split (/\./, $check_param);
|
||||
my $check_value = $self->_retrieve_from_composed_key( $result, \@splitted_values, $retained );
|
||||
like ($check_value, qr/$conditions->{$condition}->{$check_param}/, $test_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ( $condition eq 'is_deeply' ) {
|
||||
foreach my $check_param (keys %{$conditions->{$condition}}) {
|
||||
*replace_variables = sub {
|
||||
if ( ref $_ eq 'HASH' ) {
|
||||
while ( my ( $key, $value ) = each %$_ ) {
|
||||
if ( $value && $value =~ /\$\{(.*)\}/ ) {
|
||||
$_->{$key} = $retained->{$1};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
walkdepth {wanted => \&replace_variables}, $conditions->{$condition}->{$check_param};
|
||||
if ( $conditions->{$condition}->{$check_param} =~ /^\$\{(.*)\}$/ ) {
|
||||
$conditions->{$condition}->{$check_param} = $retained->{$1};
|
||||
}
|
||||
my $check_value;
|
||||
if ( $check_param=~ /^\$\{(.*)\}$/ ) {
|
||||
$check_value = $retained->{$1};
|
||||
}
|
||||
if ( $check_param =~ /.+\..+/ ) {
|
||||
my @splitted_values = split (/\./, $check_param);
|
||||
$check_value = $self->_retrieve_from_composed_key( $result, \@splitted_values, $retained );
|
||||
}
|
||||
is_deeply ($check_value, $conditions->{$condition}->{$check_param}, $test_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _retrieve_from_composed_key {
|
||||
my ( $self, $result, $splitted_values, $retained ) = @_;
|
||||
|
||||
if ( $splitted_values->[0] eq 'body' ) {
|
||||
my $body = decode_json($result->decoded_content);
|
||||
return $body->{$splitted_values->[1]};
|
||||
}
|
||||
elsif ( $splitted_values->[0] =~ /\$\{(.*)\}/ ) {
|
||||
my $value = $retained->{$1};
|
||||
grep { $value = $value->{$splitted_values->[$_]} } (1..(scalar @$splitted_values - 1));
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
@ -0,0 +1,81 @@
|
||||
use lib '..';
|
||||
use strict;
|
||||
use warnings;
|
||||
use NGCP::TestFramework;
|
||||
use Test::More;
|
||||
use threads;
|
||||
use Thread::Queue;
|
||||
use Data::Dumper;
|
||||
|
||||
my $server = $ARGV[0] || undef;
|
||||
my $selected = $ARGV[1] || 'all';
|
||||
|
||||
if ( !$server ){
|
||||
print "Usage: \$ perl testrunner.pl [<testsystem>] [<testset>]\n";
|
||||
print "Usage example: \$ perl testrunner.pl 192.168.88.162\n";
|
||||
print "Usage example: \$ perl testrunner.pl 192.168.88.162 fast\n";
|
||||
print "Possible test set: all, stable, fast, t/lib/NGCP/TestFramework/Interface/Contracts.yaml\n";
|
||||
print "Default test set: all\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
my @test_files;
|
||||
|
||||
if ( $selected eq 'stable' ) {
|
||||
print "Test selection: stable\n";
|
||||
}
|
||||
elsif ( $selected eq 'fast' ) {
|
||||
print "Test selection: fast\n";
|
||||
}
|
||||
elsif ( $selected eq 'all' ) {
|
||||
print "Test selection: all\n";
|
||||
map { push @test_files, "TestFramework/Interface/$_" } `ls TestFramework/Interface`;
|
||||
}
|
||||
else{
|
||||
print "Test selection: $selected\n";
|
||||
push @test_files, $selected;
|
||||
}
|
||||
|
||||
print "################################################################################\n";
|
||||
print "Finished main setup, now running tests ...\n";
|
||||
|
||||
$ENV{CATALYST_SERVER_SUB}="https://$server:443";
|
||||
$ENV{CATALYST_SERVER}="https://$server:1443";
|
||||
$ENV{NGCP_SESSION_ID}=int(rand(1000)).time;
|
||||
|
||||
my @threads;
|
||||
my $tests_queue = Thread::Queue->new();
|
||||
|
||||
for ( @test_files ) {
|
||||
$tests_queue->enqueue($_);
|
||||
}
|
||||
|
||||
$tests_queue->end();
|
||||
|
||||
for (1..2) {
|
||||
push @threads, threads->create( {'context' => 'void'}, \&worker, $tests_queue );
|
||||
}
|
||||
|
||||
foreach ( @threads ){
|
||||
$_->join();
|
||||
}
|
||||
|
||||
done_testing();
|
||||
|
||||
sub worker {
|
||||
my ($tests_queue) = @_;
|
||||
|
||||
while ( my $test_file = $tests_queue->dequeue_nb() ) {
|
||||
my $start_time = time;
|
||||
print "Running tests from $test_file\n";
|
||||
my $test_framework = NGCP::TestFramework->new( {file_path => $test_file} );
|
||||
|
||||
my $result_code = $test_framework->run();
|
||||
|
||||
my $total_time = time - $start_time;
|
||||
print "Finished test execution for $test_file, test execution returned with exit code $result_code.\n";
|
||||
print "Tests for $test_file took $total_time seconds.\n";
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in new issue