openqa/SOURCES/23-fedora-messaging.t

318 lines
11 KiB
Perl

#! /usr/bin/perl
# Copyright (C) 2016-2019 SUSE LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
BEGIN {
unshift @INC, 'lib';
}
use Mojo::Base;
use Mojo::IOLoop;
use FindBin;
use lib "$FindBin::Bin/lib";
use OpenQA::Client;
use OpenQA::Jobs::Constants;
use OpenQA::Test::Database;
use Test::MockModule;
use Test::More;
use Test::Mojo;
use Test::Warnings;
use Mojo::File qw(tempdir path);
use OpenQA::WebAPI::Plugin::AMQP;
my %published;
my $plugin_mock_callcount;
my $uuid_mock = Test::MockModule->new('UUID::URandom');
$uuid_mock->mock(
create_uuid_string => sub {
return '9fbba7a5-2402-4f6b-a20e-af478eee05f5';
}
);
# we mock the parent class here so we can test the child class
my $plugin_mock = Test::MockModule->new('OpenQA::WebAPI::Plugin::AMQP');
$plugin_mock->mock(
publish_amqp => sub {
my ($self, $topic, $body, $headerframe) = @_;
# ignore the non-fedoraci messages, makes it easier to
# understand the expected call counts
if ($topic =~ /\.ci\./) {
$plugin_mock_callcount++;
# strip the time-based bits, at least till
# https://github.com/cho45/Test-Time/issues/14 is done
delete $body->{'generated_at'};
delete $headerframe->{'headers'}->{'sent-at'};
$published{$topic} = [$body, $headerframe];
}
}
);
OpenQA::Test::Database->new->create(fixtures_glob => '01-jobs.pl 03-users.pl 05-job_modules.pl');
# this test also serves to test plugin loading via config file
my $conf = << 'EOF';
[global]
plugins=FedoraMessaging
base_url=https://openqa.stg.fedoraproject.org
[amqp]
topic_prefix=org.fedoraproject.stg
EOF
my $tempdir = tempdir;
$ENV{OPENQA_CONFIG} = $tempdir;
path($ENV{OPENQA_CONFIG})->make_path->child("openqa.ini")->spurt($conf);
my $t = Test::Mojo->new('OpenQA::WebAPI');
# XXX: Test::Mojo loses its app when setting a new ua
# https://github.com/kraih/mojo/issues/598
my $app = $t->app;
$t->ua(
OpenQA::Client->new(apikey => 'PERCIVALKEY02', apisecret => 'PERCIVALSECRET02')->ioloop(Mojo::IOLoop->singleton));
$t->app($app);
my $settings = {
DISTRI => 'Unicorn',
FLAVOR => 'pink',
VERSION => '42',
BUILD => 'Fedora-Rawhide-20180129.n.0',
TEST => 'rainbow',
ISO => 'whatever.iso',
DESKTOP => 'DESKTOP',
KVM => 'KVM',
ISO_MAXSIZE => 1,
MACHINE => "RainbowPC",
ARCH => 'x86_64',
SUBVARIANT => 'workstation',
TEST_TARGET => 'ISO',
};
my $expected_artifact = {
id => 'Fedora-Rawhide-20180129.n.0',
type => 'productmd-compose',
compose_type => 'nightly',
};
my $expected_contact = {
name => 'Fedora openQA',
team => 'Fedora QA',
url => 'https://openqa.stg.fedoraproject.org',
docs => 'https://fedoraproject.org/wiki/OpenQA',
irc => '#fedora-qa',
email => 'qa-devel@lists.fedoraproject.org',
};
my $expected_image = {
id => 'whatever.iso',
name => 'whatever.iso',
type => 'ISO',
};
my $expected_pipeline = {
id => 'openqa.Fedora-Rawhide-20180129.n.0.rainbow.RainbowPC.pink.x86_64',
name => 'openqa.Fedora-Rawhide-20180129.n.0.rainbow.RainbowPC.pink.x86_64',
};
my $expected_run = {
url => '',
log => '',
id => '',
};
my $expected_system = {
os => 'fedora-42',
provider => 'openqa',
architecture => 'x86_64',
variant => 'workstation',
};
my $expected_test = {
category => 'validation',
type => 'rainbow RainbowPC pink x86_64',
namespace => 'compose',
lifetime => 240,
};
my $expected_error;
my $expected_version = '0.2.1';
sub get_expected {
my $expected = {
artifact => $expected_artifact,
contact => $expected_contact,
image => $expected_image,
pipeline => $expected_pipeline,
run => $expected_run,
system => [$expected_system],
test => $expected_test,
version => $expected_version,
};
$expected->{'error'} = $expected_error if ($expected_error);
return $expected;
}
# create a job via API
my $job;
my $newjob;
subtest 'create job' => sub {
# reset the call count
$plugin_mock_callcount = 0;
$t->post_ok("/api/v1/jobs" => form => $settings)->status_is(200);
ok($job = $t->tx->res->json->{id}, 'got ID of new job');
ok($plugin_mock_callcount == 1, 'plugin mock was called');
my ($body, $headerframe) = @{$published{'org.fedoraproject.stg.ci.productmd-compose.test.queued'}};
$expected_run = {
url => "https://openqa.stg.fedoraproject.org/tests/$job",
log => "https://openqa.stg.fedoraproject.org/tests/$job/file/autoinst-log.txt",
id => $job,
};
my $expected = get_expected;
my $expected_headerframe = {
headers => {
fedora_messaging_severity => 20,
fedora_messaging_schema => 'base.message',
},
content_encoding => 'utf-8',
delivery_mode => 2,
# if this fails, probably means mock broke
message_id => '9fbba7a5-2402-4f6b-a20e-af478eee05f5',
};
is_deeply($body, $expected, 'job create triggers standardized amqp');
is_deeply($headerframe, $expected_headerframe, 'amqp header frame is as expected');
};
subtest 'mark job as done' => sub {
$plugin_mock_callcount = 0;
$t->post_ok("/api/v1/jobs/$job/set_done")->status_is(200);
ok($plugin_mock_callcount == 1, 'mock was called');
my ($body, $headerframe) = @{$published{'org.fedoraproject.stg.ci.productmd-compose.test.error'}};
$expected_error = {reason => INCOMPLETE,};
delete $expected_test->{'lifetime'};
my $expected = get_expected;
is_deeply($body, $expected, 'job done (failed) triggers standardized amqp');
};
subtest 'duplicate and cancel job' => sub {
$plugin_mock_callcount = 0;
$t->post_ok("/api/v1/jobs/$job/duplicate")->status_is(200);
$newjob = $t->tx->res->json->{id};
ok($plugin_mock_callcount == 1, 'mock was called');
my ($body, $headerframe) = @{$published{'org.fedoraproject.stg.ci.productmd-compose.test.queued'}};
$expected_run = {
clone_of => $job,
url => "https://openqa.stg.fedoraproject.org/tests/$newjob",
log => "https://openqa.stg.fedoraproject.org/tests/$newjob/file/autoinst-log.txt",
id => $newjob,
};
$expected_test->{'lifetime'} = 240;
$expected_error = '';
delete $expected_test->{'result'};
my $expected = get_expected;
is_deeply($body, $expected, 'job duplicate triggers standardized amqp');
$plugin_mock_callcount = 0;
$t->post_ok("/api/v1/jobs/$newjob/cancel")->status_is(200);
ok($plugin_mock_callcount == 1, 'mock was called');
my ($body, $headerframe) = @{$published{'org.fedoraproject.stg.ci.productmd-compose.test.error'}};
$expected_error = {reason => 'user_cancelled',};
delete $expected_test->{'lifetime'};
delete $expected_run->{'clone_of'};
my $expected = get_expected;
is_deeply($body, $expected, 'job cancel triggers standardized amqp');
};
subtest 'duplicate and pass job' => sub {
$plugin_mock_callcount = 0;
$t->post_ok("/api/v1/jobs/$newjob/duplicate")->status_is(200);
my $newerjob = $t->tx->res->json->{id};
# explicitly set job as passed
$t->post_ok("/api/v1/jobs/$newerjob/set_done?result=passed")->status_is(200);
ok($plugin_mock_callcount == 2, 'mock was called');
my ($body, $headerframe) = @{$published{'org.fedoraproject.stg.ci.productmd-compose.test.complete'}};
$expected_run = {
url => "https://openqa.stg.fedoraproject.org/tests/$newerjob",
log => "https://openqa.stg.fedoraproject.org/tests/$newerjob/file/autoinst-log.txt",
id => $newerjob,
};
$expected_test->{'result'} = 'passed';
$expected_error = '';
my $expected = get_expected;
is_deeply($body, $expected, 'job done (passed) triggers standardized amqp');
};
subtest 'create update job' => sub {
$plugin_mock_callcount = 0;
diag("Count: $plugin_mock_callcount");
$settings->{BUILD} = 'Update-FEDORA-2019-6bda4c81f4';
# this is intentionally not in alphabetical order
$settings->{ADVISORY_NVRS} = 'kernel-5.2.7-100.fc29 kernel-tools-5.2.7-100.fc29 kernel-headers-5.2.7-100.fc29';
# let's test HDD_* impact on system->{os} here too
$settings->{HDD_1} = 'disk_f40_minimal.qcow2';
$settings->{BOOTFROM} = 'c';
# some update tests don't have SUBVARIANT, in which case system
# variant should not be set
delete $settings->{SUBVARIANT};
$t->post_ok("/api/v1/jobs" => form => $settings)->status_is(200);
ok(my $updatejob = $t->tx->res->json->{id}, 'got ID of update job');
diag("Count: $plugin_mock_callcount");
ok($plugin_mock_callcount == 1, 'mock was called');
my ($body, $headerframe) = @{$published{'org.fedoraproject.stg.ci.fedora-update.test.queued'}};
$expected_artifact = {
alias => 'FEDORA-2019-6bda4c81f4',
builds => [
{
nvr => 'kernel-5.2.7-100.fc29'
},
{
nvr => 'kernel-headers-5.2.7-100.fc29'
},
{
nvr => 'kernel-tools-5.2.7-100.fc29'
}
],
id => 'sha256:cf6f57a196a213606246070a99b94053160fee43c7987d071f422de30b2f2953',
type => 'fedora-update',
release => {
version => '42',
name => 'F42'
},
};
$expected_pipeline = {
id => 'openqa.Update-FEDORA-2019-6bda4c81f4.rainbow.RainbowPC.pink.x86_64',
name => 'openqa.Update-FEDORA-2019-6bda4c81f4.rainbow.RainbowPC.pink.x86_64',
};
$expected_run = {
url => "https://openqa.stg.fedoraproject.org/tests/$updatejob",
log => "https://openqa.stg.fedoraproject.org/tests/$updatejob/file/autoinst-log.txt",
id => $updatejob,
};
$expected_system->{'os'} = 'fedora-40';
$expected_test->{'namespace'} = 'update';
$expected_test->{'lifetime'} = 240;
delete $expected_system->{'variant'};
delete $expected_test->{'result'};
my $expected = get_expected;
# no image for update message
delete $expected->{'image'};
is_deeply($body, $expected, 'update job create triggers standardized amqp');
};
done_testing();