forked from os-autoinst/openQA
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9a6e277
commit d698970
Showing
2 changed files
with
217 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,228 @@ | ||
# Copyright SUSE LLC | ||
#!/usr/bin/env perl | ||
# Copyright 2015-2021 SUSE LLC | ||
# SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
use Test::Most; | ||
use Test::Warnings ':report_warnings'; | ||
use Test::MockModule; | ||
use Test::MockObject; | ||
|
||
use FindBin; | ||
use lib "$FindBin::Bin/lib", "$FindBin::Bin/../external/os-autoinst-common/lib"; | ||
use OpenQA::Test::TimeLimit '10'; | ||
use Data::Dumper; | ||
use OpenQA::Git; | ||
use OpenQA::Utils; | ||
use OpenQA::Task::Needle::Save; | ||
use OpenQA::Test::Case; | ||
use OpenQA::Test::TimeLimit '10'; | ||
use Mojo::File 'tempdir'; | ||
use Test::MockModule; | ||
use Test::Mojo; | ||
use Test::Warnings ':report_warnings'; | ||
use Test::Output 'stdout_like'; | ||
|
||
my $mock = Test::MockModule->new('OpenQA::Utils'); | ||
$mock->redefine('run_cmd_with_log_return_error', sub { | ||
my ($cmd) = @_; | ||
# allow catching log messages via stdout_like | ||
delete $ENV{OPENQA_LOGFILE}; | ||
|
||
if ($cmd->[1] eq 'push') { | ||
# Simulate a failure when attempting to push | ||
return { status => 0 }; | ||
} | ||
# Simulate success for other git commands ('add', 'commit') | ||
return { status => 1 }; | ||
}); | ||
my $fixtures = '01-jobs.pl 03-users.pl 05-job_modules.pl 07-needles.pl'; | ||
my $schema = OpenQA::Test::Database->new->create(fixtures_glob => $fixtures); | ||
my $first_user = $schema->resultset('Users')->first; | ||
my $t = Test::Mojo->new('OpenQA::WebAPI'); | ||
|
||
subtest 'make git commit (error handling)' => sub { | ||
throws_ok( | ||
sub { | ||
OpenQA::Git->new({app => $t->app, dir => 'foo/bar'})->commit(); | ||
}, | ||
qr/no user specified/, | ||
'OpenQA::Git throws an exception if parameter missing' | ||
); | ||
|
||
my $empty_tmp_dir = tempdir(); | ||
my $git = OpenQA::Git->new({app => $t->app, dir => $empty_tmp_dir, user => $first_user}); | ||
my $res; | ||
stdout_like { $res = $git->commit({cmd => 'status', message => 'test'}) } | ||
qr/.*\[warn\].*fatal: Not a git repository/i, 'git message found'; | ||
like $res, qr'^Unable to commit via Git: fatal: (N|n)ot a git repository \(or any', 'Git error message returned'; | ||
}; | ||
|
||
# setup mocking | ||
my @executed_commands; | ||
my %mock_return_value = ( | ||
status => 1, | ||
stderr => undef, | ||
); | ||
|
||
my $mock_app = Test::MockObject->new(); | ||
$mock_app->set_always('config', { | ||
'global' => { 'scm' => 'git' }, | ||
'scm git' => { 'do_push' => 'yes' } | ||
}); | ||
sub _run_cmd_mock{ | ||
my ($cmd) = @_; | ||
push(@executed_commands, $cmd); | ||
return \%mock_return_value; | ||
} | ||
|
||
my $mock_user = Test::MockObject->new(); | ||
$mock_user->set_always('fullname', 'Test User'); | ||
$mock_user->set_always('email', '[email protected]'); | ||
subtest 'git commands with mocked run_cmd_with_log_return_error | ||
' => sub { | ||
# check default config | ||
my $utils_mock = Test::MockModule->new('OpenQA::Git'); | ||
$utils_mock->redefine( | ||
run_cmd_with_log_return_error => \&_run_cmd_mock | ||
); | ||
my $git = OpenQA::Git->new(app => $t->app, dir => 'foo/bar', user => $first_user); | ||
is($git->app, $t->app, 'app is set'); | ||
is($git->dir, 'foo/bar', 'dir is set'); | ||
is($git->user, $first_user, 'user is set'); | ||
ok(!$git->enabled, 'git is not enabled by default'); | ||
my $git_config = $t->app->config->{'scm git'}; | ||
is($git->config, $git_config, 'global git config is mirrored'); | ||
is($git->config->{update_remote}, '', 'by default no remote configured'); | ||
is($git->config->{update_branch}, '', 'by default no branch configured'); | ||
|
||
# read-only getters | ||
$git->enabled(1); | ||
ok(!$git->enabled, 'enabled is read-only'); | ||
$git->config({}); | ||
is($git->config, $git_config, 'config is read-only'); | ||
|
||
# test set_to_latest_master effectively being a no-op because no update remote and branch have been configured | ||
is($git->set_to_latest_master, undef, 'no error if no update remote and branch configured'); | ||
is_deeply(\@executed_commands, [], 'no commands executed if no update remote and branch configured') | ||
or diag explain \@executed_commands; | ||
|
||
# configure update branch and remote | ||
$git->config->{update_remote} = 'origin'; | ||
$git->config->{update_branch} = 'origin/master'; | ||
$git->config->{do_cleanup} = 'yes'; | ||
is($git_config->{update_remote}, $git->config->{update_remote}, 'global git config reflects all changes'); | ||
|
||
# test set_to_latest_master (non-error case) | ||
is($git->set_to_latest_master, undef, 'no error'); | ||
is_deeply( | ||
\@executed_commands, | ||
[ | ||
[qw(git -C foo/bar remote update origin)], [qw(git -C foo/bar reset --hard HEAD)], | ||
[qw(git -C foo/bar rebase origin/master)], | ||
], | ||
'git remote update and rebase executed', | ||
) or diag explain \@executed_commands; | ||
|
||
# test set_to_latest_master (error case) | ||
@executed_commands = (); | ||
$mock_return_value{status} = 0; | ||
$mock_return_value{stderr} = 'mocked error'; | ||
$mock_return_value{stdout} = ''; | ||
is( | ||
$git->set_to_latest_master, | ||
'Unable to fetch from origin master: mocked error', | ||
'an error occurred on remote update' | ||
); | ||
is_deeply(\@executed_commands, [[qw(git -C foo/bar remote update origin)],], 'git reset not attempted',) | ||
or diag explain \@executed_commands; | ||
|
||
# test commit | ||
@executed_commands = (); | ||
$mock_return_value{status} = 1; | ||
is( | ||
$git->dir('/repo/path')->commit( | ||
{ | ||
message => 'add rm test', | ||
add => [qw(foo.png foo.json)], | ||
rm => [qw(bar.png bar.json)], | ||
} | ||
), | ||
undef, | ||
'no error occured' | ||
); | ||
is_deeply( | ||
\@executed_commands, | ||
[ | ||
[qw(git -C /repo/path add foo.png foo.json)], | ||
[qw(git -C /repo/path rm bar.png bar.json)], | ||
[ | ||
qw(git -C /repo/path commit -q -m), | ||
'add rm test', | ||
'--author=openQA system user <[email protected]>', | ||
qw(foo.png foo.json bar.png bar.json) | ||
], | ||
], | ||
'changes staged and committed', | ||
) or diag explain \@executed_commands; | ||
|
||
$git->config->{do_push} = 'yes'; | ||
|
||
local $mock_return_value{status} = 1; | ||
local $mock_return_value{stderr} = 'mocked push error'; | ||
local $mock_return_value{stdout} = ''; | ||
|
||
$utils_mock->redefine( | ||
run_cmd_with_log_return_error => sub { | ||
my ($cmd) = @_; | ||
push(@executed_commands, $cmd); | ||
if ($cmd->[3] eq 'push') { | ||
$mock_return_value{status} = 0; | ||
} | ||
return \%mock_return_value; | ||
}); | ||
is( | ||
$git->commit( | ||
{ | ||
message => 'failed push test', | ||
} | ||
), | ||
'Unable to push Git commit: mocked push error', | ||
'an error occurred during push' | ||
); | ||
|
||
$git->config->{do_push} = ''; | ||
}; | ||
|
||
subtest 'saving needle via Git' => sub { | ||
my $utils_mock = Test::MockModule->new('OpenQA::Git'); | ||
$utils_mock->redefine( | ||
run_cmd_with_log_return_error => \&_run_cmd_mock | ||
); | ||
{ | ||
package Test::FakeMinionJob; # uncoverable statement | ||
sub finish { } | ||
sub fail { | ||
Test::Most::fail("Minion job shouldn't have failed."); # uncoverable statement | ||
Test::Most::note(Data::Dumper::Dumper(\@_)); # uncoverable statement | ||
} | ||
} | ||
|
||
my $git = OpenQA::Git->new(app => $mock_app, dir => '.', user => $mock_user); | ||
# configure use of Git | ||
$t->app->config->{global}->{scm} = 'git'; | ||
my $empty_tmp_dir = tempdir(); | ||
|
||
my $result = $git->commit({ | ||
add => ['t/16-utils-git.t'], | ||
message => 'Test commit message', | ||
}); | ||
# trigger saving needles like Minion would do | ||
@executed_commands = (); | ||
OpenQA::Task::Needle::Save::_save_needle( | ||
$t->app, | ||
bless({} => 'Test::FakeMinionJob'), | ||
{ | ||
job_id => 99926, | ||
user_id => 99903, | ||
needle_json => '{"area":[{"xpos":0,"ypos":0,"width":0,"height":0,"type":"match"}],"tags":["foo"]}', | ||
needlename => 'foo', | ||
needledir => $empty_tmp_dir, | ||
imagedir => 't/data/openqa/share/tests/archlinux/needles', | ||
imagename => 'test-rootneedle.png', | ||
}); | ||
is_deeply( | ||
\@executed_commands, | ||
[ | ||
[qw(git -C), $empty_tmp_dir, qw(remote update origin)], | ||
[qw(git -C), $empty_tmp_dir, qw(reset --hard HEAD)], | ||
[qw(git -C), $empty_tmp_dir, qw(rebase origin/master)], | ||
[qw(git -C), $empty_tmp_dir, qw(add), "foo.json", "foo.png"], | ||
[ | ||
qw(git -C), $empty_tmp_dir, | ||
qw(commit -q -m), | ||
'foo for opensuse-Factory-staging_e-x86_64-Build87.5011-minimalx@32bit', | ||
'--author=Percival <[email protected]>', | ||
"foo.json", "foo.png" | ||
], | ||
], | ||
'commands executed as expected' | ||
) or diag explain \@executed_commands; | ||
|
||
is $result, 'Unable to push Git commit', 'Commit method correctly handles push failure'; | ||
# note: Saving needles is already tested in t/ui/12-needle-edit.t. However, Git is disabled in that UI test so | ||
# it is tested here explicitly. | ||
}; | ||
|
||
done_testing; | ||
done_testing(); |
Oops, something went wrong.