3 #=======================================================================
5 # File ID: aed76eda-6124-11e0-aeaf-adf3f75e27a6
7 # Test suite for gitspreadd(1).
10 # ©opyleft 2011– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License version 2 or later, see end of
12 # file for legal stuff.
13 #=======================================================================
19 # push(@INC, "$ENV{'HOME'}/bin/STDlibdirDTS");
20 use Test
::More
qw{no_plan
};
33 our $CMD = '../gitspreadd';
46 $progname =~ s/^.*\/(.*?)$/$1/;
47 our $VERSION = '0.11.0+git';
49 Getopt
::Long
::Configure
('bundling');
52 'all|a' => \
$Opt{'all'},
53 'help|h' => \
$Opt{'help'},
54 'todo|t' => \
$Opt{'todo'},
55 'verbose|v+' => \
$Opt{'verbose'},
56 'version' => \
$Opt{'version'},
58 ) || die("$progname: Option error. Use -h for help.\n");
60 $Opt{'help'} && usage
(0);
61 if ($Opt{'version'}) {
66 my $SHOULD_NOT_EXIST = 0;
70 my $tmpdir = "$orig_dir/tmpdir";
71 my $repo = "$tmpdir/repo.git";
72 my $mirror = "$tmpdir/mirror.git";
73 my $hook = "$repo/hooks/post-receive";
74 my $wrkdir = "$tmpdir/wrkdir";
75 my $spooldir = "$tmpdir/spool";
76 my $logfile = "$tmpdir/gitspreadd.log";
77 my $pidfile = "$tmpdir/pid";
78 my $stopfile = "$tmpdir/stop";
79 my $CMD_GIT = defined($ENV{'GITSPREAD_GIT'}) ?
$ENV{'GITSPREAD_GIT'} : 'git';
88 diag
(sprintf('========== Executing %s v%s ==========',
92 unless (ok
(-e
'gitspreadd.t' && -e
'../gitspreadd' && -e
'../post-receive',
93 'We are in the correct directory')) {
94 diag
('Has to be run from inside the gitspread/t/ directory.');
98 if ($Opt{'todo'} && !$Opt{'all'}) {
104 testcmd("$CMD command", # {{{
117 diag
('Testing -h (--help) option...');
118 likecmd
("$CMD -h", # {{{
119 '/ Show this help\./',
122 'Option -h prints help screen',
126 diag
('Testing -q (--quiet) option...');
127 likecmd
("$CMD --version -q", # {{{
128 '/^\d\.\d+\.\d+(\+git)?\n/s',
131 'Option -q with --version does not output program name',
135 diag
('Testing -v (--verbose) option...');
136 likecmd
("$CMD -hv", # {{{
137 '/^\n\S+ \d\.\d+\.\d+(\+git)?\n/s',
140 'Option --version with -h returns version number and help screen',
144 diag
('Testing --version option...');
145 likecmd
("$CMD --version", # {{{
146 '/^\S+ \d\.\d+\.\d+(\+git)?\n/',
149 'Option --version returns version number',
154 my $datefmt = '20\d\d-\d\d-\d\d \d\d:\d\d:\d\dZ';
157 testcmd
("$CMD -1 -r \"$tmpdir\"", # {{{
159 "gitspreadd: $tmpdir: Missing repository top directory\n",
161 'Complain about missing repodir',
166 likecmd
("$CMD -1 -r \"$tmpdir\"", # {{{
167 '/^Starting gitspreadd \d\.\d+\.\d+(\+git)?, PID = \d+\n$/s',
170 'Run with -r option',
174 ok
(-d
$spooldir, "$spooldir exists");
175 ok
(-e
$logfile, "$logfile exists");
176 like
(file_data
($logfile), # {{{
177 "/^$datefmt - Starting gitspreadd \\d\\.\\d+\\.\\d+(\\+git)?, PID = \\d+\\n\$/s",
184 likecmd
("GITSPREAD_REPODIR=\"$tmpdir\" $CMD -1", # {{{
185 '/^Starting gitspreadd \d\.\d+\.\d+(\+git)?, PID = \d+\n$/s',
188 'Use GITSPREAD_REPODIR environment variable',
192 ok
(-d
$spooldir, "$spooldir exists");
193 ok
(-e
$logfile, "$logfile exists");
195 diag
('Set up repositories...');
203 create_file
('newfile');
204 add_and_commit_file
('newfile');
205 push_to_repo_succeeds
();
206 check_log
($SHOULD_EXIST, $mirror, 'newfile', 'newfile exists in mirror.git');
208 diag
('Check gitspread.forcepush config option...');
209 reset_wrkdir_to_first_commit
();
210 push_to_repo_denied
();
211 push_to_repo_force_update
();
212 check_log
($SHOULD_EXIST, $mirror, 'newfile', 'newfile still exists in mirror.git');
214 enable_gitspread_forcepush
();
215 create_file
('newfile');
216 add_and_commit_file
('newfile');
217 push_to_repo_succeeds
();
218 reset_wrkdir_to_first_commit
();
219 push_to_repo_force_update
();
220 check_log
($SHOULD_NOT_EXIST, $mirror, 'newfile', 'newfile is gone from mirror.git');
222 diag
('Create branch, push it, and then remove it...');
223 create_branch
('newbranch1');
224 create_file
('branchfile1');
225 add_and_commit_file
('branchfile1');
226 create_branch
('newbranch2');
227 create_file
('branchfile2');
228 add_and_commit_file
('branchfile2');
229 push_new_branch
('newbranch1', 'newbranch2');
230 check_log
($SHOULD_EXIST, $mirror, 'branchfile1', 'branchfile1 exists in mirror.git');
231 check_log
($SHOULD_EXIST, $mirror, 'branchfile2', 'branchfile2 exists in mirror.git');
232 delete_branch
('newbranch1', 'newbranch2');
233 delete_remote_branch
('newbranch1', 'newbranch2');
234 check_log
($SHOULD_NOT_EXIST, $mirror, 'branchfile1', 'branchfile1 is gone from mirror.git');
235 check_log
($SHOULD_NOT_EXIST, $mirror, 'branchfile2', 'branchfile2 is gone from mirror.git');
243 if ($Opt{'all'} || $Opt{'todo'}) {
244 diag
('Running TODO tests...'); # {{{
249 # Insert TODO tests here.
255 diag
('Testing finished.');
262 ok
(chdir($orig_dir), "chdir $orig_dir");
263 testcmd
("rm -rf \"$tmpdir\"", '', '', 0, 'Delete tmpdir');
264 ok
(!-e
$tmpdir, "$tmpdir does not exist");
271 ok
(mkdir($tmpdir), "mkdir $tmpdir");
272 ok
(-d
$tmpdir, 'tmpdir exists');
279 my ($dir, $bare) = @_;
281 my $bare_str = $bare ?
" --bare" : "";
282 my $bare_msg = $bare ?
" bare repository" : "";
283 likecmd
("$CMD_GIT clone$bare_str \"$orig_dir/repo.bundle\" \"$tmpdir/$dir\"",
287 "Clone repo.bundle into $dir"
289 ok
(chdir("$tmpdir/$dir"), "chdir $tmpdir/$dir");
290 my $git_str = $bare ?
"" : ".git/";
291 ok
(-f
"${git_str}HEAD" && -f
"${git_str}config" && -d
"${git_str}objects",
292 "$tmpdir/$dir looks like a real repository");
299 diag
('Create repo.git...');
300 testcmd
("rm -rf \"$repo\"", '', '', 0, 'Make sure repo.git does not exist');
301 clone_bundle
('repo.git', 1);
303 ok
(chdir($repo), 'chdir repo.git');
304 testcmd
("$CMD_GIT remote add mirror \"$mirror\"", '', '', 0, 'Set up mirror remote');
305 ok
(copy
("$orig_dir/../post-receive", $hook), "Copy ../post-receive to $hook");
306 ok
(-e
$hook, 'Yes, it was really copied');
307 ok
(chmod(0755, $hook), "Make $hook executable");
308 is
((stat($hook))[2] & 07777, 0755, "$hook has correct permissions");
309 ok
(chdir($bck_dir), 'Return to previous directory');
316 testcmd
("rm -rf \"$wrkdir\"", '', '', 0, 'Make sure wrkdir does not exist');
317 clone_bundle
('wrkdir', 0);
318 ok
(chdir($wrkdir), 'chdir wrkdir');
319 testcmd
("$CMD_GIT remote add dest \"$repo\"", '', '', 0, 'Set up dest remote');
326 testcmd
("rm -rf \"$mirror\"", '', '', 0, 'Make sure mirror.git does not exist');
327 clone_bundle
('mirror.git', 1);
328 check_log
($SHOULD_NOT_EXIST, $mirror, 'newfile', 'newfile does not exist in mirror.git yet');
332 sub add_and_commit_file
{
335 diag
('Make a commit...');
336 ok
(chdir($wrkdir), "chdir $wrkdir");
337 testcmd
("$CMD_GIT add \"$file\"", '', '', 0, "Add $file for commit");
338 likecmd
("$CMD_GIT commit -m 'Adding new file $file'",
339 "/^.*Adding new file $file\\n.*\$/s",
342 "Commit addition of $file",
346 } # add_and_commit_file()
350 my ($should_exist, $dir, $file, $msg) = @_;
351 ok
(chdir($dir), "chdir $dir");
352 if ($should_exist == $SHOULD_EXIST) {
353 like
(`$CMD_GIT log --all`, "/^.*Adding new file $file.*\$/s", $msg);
355 unlike
(`$CMD_GIT log --all`, "/^.*Adding new file $file.*\$/s", $msg);
363 my $filename = shift;
364 ok
(chdir($wrkdir), "chdir $wrkdir");
365 ok
(open(my $newfile, '>', $filename), "Create $filename");
366 ok
(print($newfile "This is $filename\n"), "Write to $filename");
367 ok
(close($newfile), "Close $filename");
375 ok
(chdir($wrkdir), "chdir $wrkdir");
376 likecmd
("$CMD_GIT checkout -b \"$branch\"",
378 "/^Switched to a new branch .$branch.\\n\$/s",
380 "Create branch $branch",
389 ok
(chdir($wrkdir), "chdir $wrkdir");
390 my $branch_str = join(' ', @branches);
391 likecmd
("$CMD_GIT checkout master",
395 'Checkout branch master',
397 likecmd
("$CMD_GIT branch -D $branch_str",
398 "/^Deleted branch $branches[0].*\$/s",
401 "Delete branch(es) '$branch_str'",
407 sub enable_gitspread_forcepush
{
409 diag
('Enable gitspread.forcepush in repo.git...');
410 ok
(chdir($repo), 'chdir repo.git');
411 likecmd
("$CMD_GIT config gitspread.forcepush true",
415 'Enable gitspread.forcepush'
419 } # enable_gitspread_forcepush()
421 sub push_to_repo_succeeds
{
423 ok
(chdir($wrkdir), 'chdir wrkdir');
424 likecmd
("GITSPREAD_REPODIR=\"$tmpdir\" $CMD_GIT push dest",
427 'Spreading repo commits:.*' .
428 'a1989e25c8e7c23a3c455731f9433ed0932ec193 ' .
429 '[0-9a-f]{40} refs/heads/master.*' .
430 'Waiting for spreading to complete\.\.\..*' .
431 'Spreading finished.*$/s',
433 'Push to dest remote'
437 } # push_to_repo_succeeds()
439 sub push_new_branch
{
442 ok
(chdir($wrkdir), 'chdir wrkdir');
443 my $branch_str = join(' ', @branches);
444 likecmd
("GITSPREAD_REPODIR=\"$tmpdir\" $CMD_GIT push dest $branch_str",
447 'Spreading repo commits:.*' .
449 "[0-9a-f]{40} refs/heads/$branches[0].*" .
450 'Waiting for spreading to complete\.\.\..*' .
451 'Spreading finished.*$/s',
453 "Push '$branch_str' branch(es) to dest remote"
457 } # push_new_branch()
459 sub delete_remote_branch
{
462 ok
(chdir($wrkdir), 'chdir wrkdir');
463 my $branch_str = ':' . join(' :', @branches);
464 likecmd
("GITSPREAD_REPODIR=\"$tmpdir\" $CMD_GIT push dest $branch_str",
467 'Spreading repo commits:.*' .
469 "0{40} refs/heads/$branches[0].*" .
470 'Waiting for spreading to complete\.\.\..*' .
471 'Spreading finished.*$/s',
473 "Delete remote branch(es) '$branch_str'"
477 } # delete_remote_branch()
479 sub push_to_repo_denied
{
481 ok
(chdir($wrkdir), 'chdir wrkdir');
482 likecmd
("GITSPREAD_REPODIR=\"$tmpdir\" $CMD_GIT push dest",
486 'Denied non-fast-forward push'
488 check_log
($SHOULD_EXIST, $repo, 'newfile', "newfile still exists in $repo");
491 } # push_to_repo_denied()
493 sub push_to_repo_force_update
{
495 ok
(chdir($wrkdir), 'chdir wrkdir');
496 likecmd
("GITSPREAD_REPODIR=\"$tmpdir\" $CMD_GIT push -f dest",
499 'Spreading repo commits:.*' .
501 'a1989e25c8e7c23a3c455731f9433ed0932ec193 refs/heads/master.*' .
502 'Waiting for spreading to complete\.\.\..*' .
503 'Spreading finished.*/s',
505 'Force-push to dest remote'
509 } # push_to_repo_force_update()
511 sub reset_wrkdir_to_first_commit
{
513 ok
(chdir($wrkdir), 'chdir wrkdir');
514 likecmd
("$CMD_GIT reset --hard a1989e2",
515 '/^HEAD is now at a198[0-9a-f]* Initial empty commit\n$/',
518 'Reset HEAD to first commit'
522 } # reset_wrkdir_to_first_commit()
526 diag
('Starting daemon...');
527 my $tmpfile = ".gitspread-start-output.tmp";
528 system("\"$orig_dir/$CMD\" -r \"$tmpdir\" >$tmpfile");
529 like
(file_data
($tmpfile),
530 '/^Starting gitspreadd \d+\.\d+\.\d+(\+git)?, PID = \d+\n$/s',
531 'stdout from daemon looks ok',
533 ok
(-e
$pidfile, 'PID file exists');
534 like
(file_data
($pidfile), '/^\d+\n$/s', 'PID file looks ok');
541 diag
('Stopping daemon...');
542 ok
(open(my $stopfh, '>', $stopfile), "Create stop file $stopfile");
543 ok
(close($stopfh), 'Close stop file');
544 diag
('Waiting for process to stop...');
545 while(-e
$stopfile) { }
546 ok
(!-e
$pidfile, 'PID file is removed');
551 sub regexp_friendly
{
554 $str =~ s/\//\\\
//gs;
558 } # regexp_friendly()
562 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
570 my $TMP_STDERR = 'gitspreadd-stderr.tmp';
572 if (defined($Exp_stderr)) {
573 $stderr_cmd = " 2>$TMP_STDERR";
575 is
(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
577 if (defined($Exp_stderr)) {
578 is
(file_data
($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
581 diag
("Warning: stderr not defined for '$Txt'");
583 is
($ret_val >> 8, $Exp_retval, "$Txt (retval)");
590 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
598 my $TMP_STDERR = 'gitspreadd-stderr.tmp';
600 if (defined($Exp_stderr)) {
601 $stderr_cmd = " 2>$TMP_STDERR";
603 like
(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
605 if (defined($Exp_stderr)) {
606 like
(file_data
($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
609 diag
("Warning: stderr not defined for '$Txt'");
611 is
($ret_val >> 8, $Exp_retval, "$Txt (retval)");
617 # Return file content as a string {{{
620 if (open(my $fp, '<', $File)) {
632 # Print program version {{{
633 print("$progname $VERSION\n");
639 # Send the help message to stdout {{{
642 if ($Opt{'verbose'}) {
648 Usage: $progname [options] [file [files [...]]]
650 Contains tests for the gitspreadd(1) program.
655 Run all tests, also TODOs.
659 Run only the TODO tests.
661 Increase level of verbosity. Can be repeated.
663 Print version information. "Semantic versioning" is used, described
664 at <http://semver.org>.
666 To use an alternative version of git, set the \$GITSPREAD_GIT
667 environment variable to the git executable to use. For example:
669 export GITSPREAD_GIT=/usr/local/bin/git
678 # Print a status message to stderr based on verbosity level {{{
679 my ($verbose_level, $Txt) = @_;
681 if ($Opt{'verbose'} >= $verbose_level) {
682 print(STDERR
"$progname: $Txt\n");
690 # This program is free software: you can redistribute it and/or modify
691 # it under the terms of the GNU General Public License as published by
692 # the Free Software Foundation, either version 2 of the License, or (at
693 # your option) any later version.
695 # This program is distributed in the hope that it will be useful, but
696 # WITHOUT ANY WARRANTY; without even the implied warranty of
697 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
698 # See the GNU General Public License in the file COPYING for more
701 # You should have received a copy of the GNU General Public License
702 # along with this program.
703 # If not, see L<http://www.gnu.org/licenses/gpl-2.0.txt>.
705 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :