App-karr
view release on metacpan or search on metacpan
t/93-syncguard-push-rejection.t view on Meta::CPAN
chdir $cwd or die "chdir $cwd: $!";
my $eh = gensym;
my $pid = open3( my $in, my $out, $eh, $^X, "-I$ROOT/lib", $BIN, @argv );
close $in;
my $stdout = do { local $/; <$out> };
my $stderr = do { local $/; <$eh> };
waitpid $pid, 0;
my $exit = $? >> 8;
chdir $old or die "chdir $old: $!";
return { exit => $exit, stdout => $stdout // '', stderr => $stderr // '' };
}
my $DAEMON_PID;
END { kill 'TERM', $DAEMON_PID if $DAEMON_PID }
sub start_daemon {
my ($work) = @_;
for ( 1 .. 5 ) {
my $port = 20000 + int rand 20000;
my $pid = fork();
return () unless defined $pid;
if ( !$pid ) {
open STDOUT, '>', "$work/daemon.log";
open STDERR, '>>', "$work/daemon.log";
exec( 'git', 'daemon', '--export-all', '--enable=receive-pack',
"--base-path=$work", "--port=$port", $work );
exit 1;
}
for ( 1 .. 25 ) {
Time::HiRes::sleep(0.1);
system("git ls-remote 'git://127.0.0.1:$port/origin.git' >/dev/null 2>&1");
return ( $pid, $port ) if $? == 0;
}
kill 'TERM', $pid;
waitpid $pid, 0;
}
return ();
}
subtest 'end to end: a command that dies into a refused push says so' => sub {
my $work = tempdir( CLEANUP => 1 );
system( 'git', 'init', '-q', '--bare', "$work/origin.git" );
path("$work/origin.git/git-daemon-export-ok")->spew('');
my ( $pid, $port ) = start_daemon($work);
plan skip_all => 'no git daemon on a loopback port here' unless $pid;
$DAEMON_PID = $pid;
system("git clone -q 'git://127.0.0.1:$port/origin.git' '$work/a' 2>/dev/null");
system( 'git', '-C', "$work/a", 'config', 'user.email', 'a@karr.test' );
system( 'git', '-C', "$work/a", 'config', 'user.name', 'agent-a' );
is run_karr( "$work/a", 'init', '--name', 'Demo' )->{exit}, 0,
'setup: the board is created and pushed';
is run_karr( "$work/a", 'create', 'task one' )->{exit}, 0,
'setup: and carries a task';
# Only now does the server start refusing.
my $hook = path("$work/origin.git/hooks/pre-receive");
$hook->spew("#!/bin/sh\necho 'board is protected' >&2\nexit 1\n");
chmod 0755, "$hook";
# Writes task 1, then dies on the missing 999 -- so the push happens from
# the END-block flush, with no sync_after ever reached.
my $r = run_karr( "$work/a", 'move', '1,999', 'in-progress',
'--claim', 'flush-agent' );
is $r->{exit}, 1, 'the command still fails on its own error';
like $r->{stderr}, qr/Task 999 not found/,
'and that error still reaches the user';
like $r->{stderr}, qr{refs/karr/tasks/1/data: pre-receive hook declined},
'the insurance push names the ref the server refused';
like $r->{stderr}, qr/Push rejected by the remote/,
'and reports it as a refusal';
unlike $r->{stderr}, qr/Push retry \d of 3/,
'without retrying an answer that was already given';
unlike $r->{stderr}, qr/Run 'karr sync' to retry/,
'and without advising a sync that would be refused identically';
kill 'TERM', $pid;
waitpid $pid, 0;
undef $DAEMON_PID;
};
done_testing;
( run in 1.274 second using v1.01-cache-2.11-cpan-6736b670a1e )