Skip to content

Commit

Permalink
Add test for uncovered code
Browse files Browse the repository at this point in the history
* Catch unhandled output
* Don't use system directories but meaningful temp directory names
  • Loading branch information
perlpunk committed Sep 23, 2024
1 parent 095d0c9 commit 543bc19
Showing 1 changed file with 51 additions and 32 deletions.
83 changes: 51 additions & 32 deletions t/14-grutasks-git.t
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use OpenQA::Task::Git::Clone;
require OpenQA::Test::Database;
use OpenQA::Test::Utils qw(run_gru_job perform_minion_jobs);
use OpenQA::Test::TimeLimit '20';
use Test::Output qw(stderr_like);
use Test::MockModule;
use Test::Mojo;
use Test::Warnings qw(:report_warnings);
Expand All @@ -25,6 +26,7 @@ chdir $workdir;
path('t/data/openqa/db')->make_path;
my $git_clones = "$workdir/git-clones";
mkdir $git_clones;
mkdir "$git_clones/$_" for qw(default branch dirty-error dirty-status nodefault wrong-url);

my $schema = OpenQA::Test::Database->new->create();
my $t = Test::Mojo->new('OpenQA::WebAPI');
Expand All @@ -40,9 +42,9 @@ subtest 'git clone' => sub {
my $openqa_git = Test::MockModule->new('OpenQA::Git');
my @mocked_git_calls;
my $clone_dirs = {
'/etc/' => 'http://localhost/foo.git',
'/root/' => 'http://localhost/foo.git#foobranch',
'/this_directory_does_not_exist/' => 'http://localhost/bar.git',
"$git_clones/default/" => 'http://localhost/foo.git',
"$git_clones/branch/" => 'http://localhost/foo.git#foobranch',
"$git_clones/this_directory_does_not_exist/" => 'http://localhost/bar.git',
};
$openqa_git->redefine(
run_cmd_with_log_return_error => sub ($cmd) {
Expand All @@ -60,6 +62,9 @@ subtest 'git clone' => sub {
elsif ($path =~ m/opensuse/) {
$stdout = 'http://osado';
}
elsif ($path =~ m/wrong-url/) {
$stdout = 'http://other';
}
}
elsif ($action eq 'ls-remote') {
$stdout = 'ref: refs/heads/master HEAD';
Expand All @@ -69,9 +74,9 @@ subtest 'git clone' => sub {
$stdout = 'master';
}
elsif ($action eq 'diff-index') {
$return_code = 1 if $path eq '/opt/'; # /opt/ simulates dirty checkout
$return_code = 1 if $path =~ m/dirty-status/;
$return_code = 2
if $path eq '/lib/'; # /lib/ simulates error when checking checkout dirty status
if $path =~ m/dirty-error/;
}
return {
status => $return_code == 0,
Expand All @@ -80,23 +85,24 @@ subtest 'git clone' => sub {
stdout => $stdout,
};
});
my $res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
my @gru_args = ($t->app, 'git_clone', $clone_dirs, {priority => 10});
my $res = run_gru_job(@gru_args);
is $res->{result}, 'Job successfully executed', 'minion job result indicates success';
#<<< no perltidy
my $expected_calls = [
# /etc/
['get-url' => 'git -C /etc/ remote get-url origin'],
['check dirty' => 'git -C /etc/ diff-index HEAD --exit-code'],
# /branch
['get-url' => 'git -C /branch/ remote get-url origin'],
['check dirty' => 'git -C /branch/ diff-index HEAD --exit-code'],
['current branch' => 'git -C /branch/ branch --show-current'],
['fetch branch' => 'env GIT_SSH_COMMAND="ssh -oBatchMode=yes" git -C /branch/ fetch origin foobranch'],

# /default/
['get-url' => 'git -C /default/ remote get-url origin'],
['check dirty' => 'git -C /default/ diff-index HEAD --exit-code'],
['default remote' => 'env GIT_SSH_COMMAND="ssh -oBatchMode=yes" git ls-remote --symref http://localhost/foo.git HEAD'],
['current branch' => 'git -C /etc/ branch --show-current'],
['fetch default' => 'env GIT_SSH_COMMAND="ssh -oBatchMode=yes" git -C /etc/ fetch origin master'],
['reset' => 'git -C /etc/ reset --hard origin/master'],

# /root
['get-url' => 'git -C /root/ remote get-url origin'],
['check dirty' => 'git -C /root/ diff-index HEAD --exit-code'],
['current branch' => 'git -C /root/ branch --show-current'],
['fetch branch' => 'env GIT_SSH_COMMAND="ssh -oBatchMode=yes" git -C /root/ fetch origin foobranch'],
['current branch' => 'git -C /default/ branch --show-current'],
['fetch default' => 'env GIT_SSH_COMMAND="ssh -oBatchMode=yes" git -C /default/ fetch origin master'],
['reset' => 'git -C /default/ reset --hard origin/master'],

# /this_directory_does_not_exist/
['clone' => 'env GIT_SSH_COMMAND="ssh -oBatchMode=yes" git clone http://localhost/bar.git /this_directory_does_not_exist/'],
Expand All @@ -109,8 +115,9 @@ subtest 'git clone' => sub {

subtest 'no default remote branch' => sub {
$ENV{OPENQA_GIT_CLONE_RETRIES} = 0;
$clone_dirs = {'/tmp/' => 'http://localhost/nodefault.git'};
my $res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
%$clone_dirs = ("$git_clones/nodefault" => 'http://localhost/nodefault.git');
stderr_like { $res = run_gru_job(@gru_args) }
qr(Error detecting remote default), 'error on stderr';
is $res->{state}, 'failed', 'minion job failed';
like $res->{result}, qr/Error detecting remote default.*ref: something/, 'error message';
};
Expand All @@ -119,35 +126,47 @@ subtest 'git clone' => sub {
$ENV{OPENQA_GIT_CLONE_RETRIES} = 1;
my $openqa_clone = Test::MockModule->new('OpenQA::Task::Git::Clone');
$openqa_clone->redefine(_git_clone => sub (@) { die "fake error\n" });
$res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
$res = run_gru_job(@gru_args);
is $res->{retries}, 1, 'job retries incremented';
is $res->{state}, 'inactive', 'job set back to inactive';
};
subtest 'git clone fails when all retry attempts exhausted' => sub {
$ENV{OPENQA_GIT_CLONE_RETRIES} = 0;
my $openqa_clone = Test::MockModule->new('OpenQA::Task::Git::Clone');
$openqa_clone->redefine(_git_clone => sub (@) { die "fake error\n" });
$res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
stderr_like { $res = run_gru_job(@gru_args) }
qr(fake error), 'error message on stderr';
is $res->{retries}, 0, 'job retries not incremented';
is $res->{state}, 'failed', 'job considered failed';
};

subtest 'dirty git checkout' => sub {
# /opt/ is mocked to be always reported as dirty
$clone_dirs = {'/opt/' => 'http://localhost/foo.git'};
my $res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
%$clone_dirs = ("$git_clones/dirty-status" => 'http://localhost/foo.git');
stderr_like { $res = run_gru_job(@gru_args) }
qr(git diff-index HEAD), 'error about diff on stderr';
is $res->{state}, 'failed', 'minion job failed';
like $res->{result}, qr/NOT updating dirty git checkout/, 'error message';
};

subtest 'error testing dirty git checkout' => sub {
# /lib/ is mocked to be always reported as dirty
$clone_dirs = {'/lib/' => 'http://localhost/foo.git'};
my $res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
%$clone_dirs = ("$git_clones/dirty-error/" => 'http://localhost/foo.git');
stderr_like { $res = run_gru_job(@gru_args) }
qr(Unexpected exit code 2), 'error message on stderr';
is $res->{state}, 'failed', 'minion job failed';
like $res->{result}, qr/Internal Git error: Unexpected exit code 2/, 'error message';
};

subtest 'error because of different url' => sub {
%$clone_dirs = ();
my $clone_dirs2 = {"$git_clones/wrong-url/" => 'http://localhost/different.git'};
stderr_like {
$res = run_gru_job($t->app, 'git_clone', $clone_dirs2, {priority => 10})
}
qr(Local checkout.*has origin.*but requesting to clone from), 'Warning about different url';
is $res->{state}, 'finished', 'minion job finished';
is $res->{result}, 'Job successfully executed', 'minion job result indicates success';
};

subtest 'update clones without CASEDIR' => sub {
@mocked_git_calls = ();
#<<< no perltidy
Expand All @@ -170,11 +189,11 @@ subtest 'git clone' => sub {
];
#>>> no perltidy
$ENV{OPENQA_GIT_CLONE_RETRIES} = 0;
$clone_dirs = {
%$clone_dirs = (
"$git_clones/opensuse" => undef,
"$git_clones/opensuse/needles" => undef,
};
my $res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
);
my $res = run_gru_job(@gru_args);
is $res->{state}, 'finished', 'minion job finished';
is $res->{result}, 'Job successfully executed', 'minion job result indicates success';
for my $i (0 .. $#$expected_calls) {
Expand All @@ -186,7 +205,7 @@ subtest 'git clone' => sub {
subtest 'minion guard' => sub {
my $guard = $t->app->minion->guard('limit_needle_task', ONE_HOUR);
my $start = time;
$res = run_gru_job($t->app, 'git_clone', $clone_dirs, {priority => 10});
$res = run_gru_job(@gru_args);
is $res->{state}, 'inactive', 'job is inactive';
ok(($res->{delayed} - $start) > 5, 'job delayed as expected');
};
Expand Down

0 comments on commit 543bc19

Please sign in to comment.