3 #=======================================================================
5 # File ID: f7855efa-7a4f-11e5-968c-02010e0a6634
7 # Test suite for git-dbr(1).
10 # ©opyleft 2015– Ø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 use Test
::More
qw{no_plan
};
27 our $CMD_BASENAME = "git-dbr";
28 our $CMD = "../$CMD_BASENAME";
33 'git' => defined($ENV{'GIT_DBR_GIT'}) ?
$ENV{'GIT_DBR_GIT'} : 'git',
43 $progname =~ s/^.*\/(.*?)$/$1/;
44 our $VERSION = '0.0.0';
46 my %descriptions = ();
48 Getopt
::Long
::Configure
('bundling');
51 'all|a' => \
$Opt{'all'},
52 'git|g=s' => \
$Opt{'git'},
53 'help|h' => \
$Opt{'help'},
54 'quiet|q+' => \
$Opt{'quiet'},
55 'todo|t' => \
$Opt{'todo'},
56 'verbose|v+' => \
$Opt{'verbose'},
57 'version' => \
$Opt{'version'},
59 ) || die("$progname: Option error. Use -h for help.\n");
61 $Opt{'verbose'} -= $Opt{'quiet'};
62 $Opt{'help'} && usage
(0);
63 if ($Opt{'version'}) {
68 my $GIT = $Opt{'git'};
76 diag
(sprintf('========== Executing %s v%s ==========',
77 $progname, $VERSION));
79 if ($Opt{'todo'} && !$Opt{'all'}) {
85 testcmd("$CMD command", # {{{
98 diag
('Testing -h (--help) option...');
99 likecmd
("$CMD -h", # {{{
100 '/ Show this help/i',
103 'Option -h prints help screen',
107 diag
('Testing -v (--verbose) option...');
108 likecmd
("$CMD -hv", # {{{
109 '/^\n\S+ \d+\.\d+\.\d+/s',
112 'Option -v with -h returns version number and help screen',
116 diag
('Testing --version option...');
117 likecmd
("$CMD --version", # {{{
118 '/^\S+ \d+\.\d+\.\d+/',
121 'Option --version returns version number',
125 my $Tmptop = "tmp-git-dangling-t-$$-" . substr(rand, 2, 8);
126 ok
(mkdir($Tmptop), "mkdir [Tmptop]");
127 ok
(chdir($Tmptop), "chdir [Tmptop]");
128 diag
("Initialise test repos");
129 likecmd
("$GIT init repo_a", # {{{
137 if (!ok
(-d
"repo_a/.git", "repo_a/.git exists")) { # {{{
138 ok
(chdir(".."), "chdir .. before bailout");
139 ok
(rmdir($Tmptop), "rmdir [Tmptop] before bailout");
140 BAIL_OUT
("repo_a wasn't created properly, aborting");
144 likecmd
("$GIT init repo_b", # {{{
152 ok
(-d
"repo_b/.git", "repo_b/.git exists");
153 ok
(chdir("repo_a"), "chdir repo_a");
154 create_remote
("repo_b", "../repo_b");
155 likecmd
("$GIT commit --allow-empty -m 'Initial empty commit'", # {{{
159 "Create initial commit in repo_a",
163 is
(`$GIT log --format="%T %s"`, # {{{
164 "4b825dc642cb6eb9a060e54bf8d69288fbee4904 Initial empty commit\n",
165 "Initial commit in repo_a was created",
169 create_branch
("branch_a");
170 create_branch
("branch_b");
171 create_branch
("oldbranch");
172 create_branch
("with/slash");
173 ok
(chdir("../repo_b"), "chdir ../repo_b");
174 create_remote
("repo_a", "../repo_a");
175 likecmd
("$GIT fetch repo_a", # {{{
178 'From \.\.\/repo_a\n' .
180 '\[new branch\].+repo_a\/branch_a\n' .
182 '\[new branch\].+repo_a\/branch_b\n' .
184 '\[new branch\].+repo_a\/master\n' .
186 '\[new branch\].+repo_a\/oldbranch\n' .
188 '\[new branch\].+repo_a\/with\/slash\n' .
195 check_branches
(<<END, "after initial fetch"); # {{{
196 remotes/repo_a/branch_a
197 remotes/repo_a/branch_b
198 remotes/repo_a/master
199 remotes/repo_a/oldbranch
200 remotes/repo_a/with/slash
205 diag
("Start of git-dbr tests");
206 testcmd
("$CMD", # {{{
214 create_branch
("oldbranch", "repo_a/oldbranch");
215 check_branches
(<<END, "after oldbranch was created"); # {{{
217 remotes/repo_a/branch_a
218 remotes/repo_a/branch_b
219 remotes/repo_a/master
220 remotes/repo_a/oldbranch
221 remotes/repo_a/with/slash
225 likecmd
("$CMD oldbranch", # {{{
226 '/^Deleted branch oldbranch \(was [0-9a-f]+\)\.\n$/s',
227 '/^git-dbr: Executing \'git branch -D oldbranch\'\.\.\.\n$/s',
229 "Delete local branch 'oldbranch'",
233 create_branch
("oldbranch2", "repo_a/oldbranch");
234 likecmd
("$CMD oldbranch2 repo_a/oldbranch", # {{{
235 '/^Deleted branch oldbranch2 \(was [0-9a-f]+\)\.\n$/s',
237 'git-dbr: Executing \'git branch -D oldbranch2\'\.\.\.\n' .
238 'git-dbr: Executing \'git push repo_a :oldbranch\'\.\.\.\n' .
239 'To \.\.\/repo_a\n' .
241 '\[deleted\]\s+oldbranch\n' .
244 "Delete local branch 'oldbranch2' " .
245 "and remote branch 'repo_a/oldbranch'",
249 fetch
("repo_a", "after deletion of oldbranch2 and repo_a/oldbranch");
250 check_branches
(<<END, "after oldbranch2 and repo_a/oldbranch were deleted"); # {{{
251 remotes/repo_a/branch_a
252 remotes/repo_a/branch_b
253 remotes/repo_a/master
254 remotes/repo_a/with/slash
258 test_branch
("slash/branch_a");
259 test_branch
("ab/cd/ef");
260 test_branch
("remotes/abc");
261 test_branch
("remotes/repo_a/abc");
262 test_branch
("repo_a/abc");
264 test_branch
("abc,,,,,");
265 test_branch
("has++plus+signs");
266 test_branch
("repo_a/abc,/,/,,,");
267 test_branch
("slash/branch_a,");
268 test_branch
("ab/cd/ef,");
269 test_branch
("remotes/abc,");
270 test_branch
("remotes/repo_a/abc,");
271 test_branch
("repo_a/abc,");
272 test_branch
("heads/master");
273 test_branch
("refs/heads/master");
274 diag
("branch name is identical to remote name");
275 create_branch
("remotes/repo_a/master", "repo_a/master");
276 check_branches
(<<END, "even with same name as remote");
277 remotes/repo_a/master
278 remotes/repo_a/branch_a
279 remotes/repo_a/branch_b
280 remotes/repo_a/master
281 remotes/repo_a/with/slash
283 likecmd
("$CMD remotes/repo_a/master", # {{{
284 '/^Deleted branch remotes/repo_a/master \(was [0-9a-f]+\)\.\n$/s',
285 '/^git-dbr: Executing \'git branch -D ' .
286 'remotes/repo_a/master\'\.\.\.\n$/s',
288 "Delete local branch 'remotes/repo_a/master'",
292 check_branches
(<<END, "after 'remotes/repo_a/master' was deleted"); # {{{
293 remotes/repo_a/branch_a
294 remotes/repo_a/branch_b
295 remotes/repo_a/master
296 remotes/repo_a/with/slash
300 likecmd
("$CMD remotes/repo_a/with/slash", # {{{
303 'git-dbr: Executing \'git push repo_a :with\/slash\'\.\.\.\n' .
304 'To \.\.\/repo_a\n' .
306 '\[deleted\]\s+with\/slash\n' .
309 "Delete remote branch 'repo_a/with/slash'",
311 check_branches
(<<END, "after local 'remotes/repo_a/master' was deleted");
312 remotes/repo_a/branch_a
313 remotes/repo_a/branch_b
314 remotes/repo_a/master
318 create_branch
("branch_a", "repo_a/branch_a");
319 likecmd
("$GIT branch -a | grep branch_a | xargs $CMD", # {{{
320 '/^Deleted branch branch_a \(was [0-9a-f]+\)\.\n$/s',
322 'git-dbr: Executing \'git branch -D branch_a\'\.\.\.\n' .
323 'git-dbr: Executing \'git push repo_a :branch_a\'\.\.\.\n' .
324 'To \.\.\/repo_a\n' .
326 '\[deleted\]\s+branch_a\n' .
329 "Delete all 'branch_a' branches with xargs",
333 fetch
("repo_a", "after all 'branch_a' branches were deleted");
334 check_branches
(<<END, "after all 'branch_a' branches were deleted"); # {{{
335 remotes/repo_a/branch_b
336 remotes/repo_a/master
340 likecmd
("$CMD repo_a/branch_b,", # {{{
343 'git-dbr: Executing \'git push repo_a :branch_b\'\.\.\.\n' .
344 'To \.\.\/repo_a\n' .
346 '\[deleted\]\s+branch_b\n' .
349 "Delete local branch 'repo_a/branch_b' and strip trailing comma",
353 ok
(chdir(".."), "chdir ..");
354 diag
("Delete temporary test directories");
355 ok
(-d
"repo_a", "repo_a exists");
356 testcmd
("rm -rf repo_a", # {{{
364 ok
(!-e
"repo_a", "repo_a is gone");
365 ok
(-d
"repo_b", "repo_b exists");
366 testcmd
("rm -rf repo_b", # {{{
374 ok
(!-e
"repo_b", "repo_b is gone");
375 ok
(chdir(".."), "chdir ..");
376 ok
(rmdir($Tmptop), "rmdir [Tmptop]");
381 if ($Opt{'all'} || $Opt{'todo'}) {
382 diag
('Running TODO tests...'); # {{{
387 # Insert TODO tests here.
393 diag
('Testing finished.');
400 my ($should_be, $desc) = @_;
401 is
(`$GIT branch -a`, $should_be, "Branches are ok $desc");
408 my ($branch, $remote_branch) = @_;
409 defined($remote_branch) || ($remote_branch = '');
410 likecmd
("$GIT branch $branch $remote_branch",
414 "Create '$branch' branch" .
415 (length($remote_branch) ?
" from $remote_branch" : ""),
423 my ($name, $url) = @_;
424 testcmd
("$GIT remote add $name $url",
428 "Create remote '$name'",
435 # Create and delete local branch. Check retval, but ignore output. {{{
437 system("$GIT branch \"$branch\" repo_a/branch_a >/dev/null 2>/dev/null");
438 like
(`$GIT branch -a`,
440 ' ' . quotemeta($branch) . '\n' .
442 "Branch '$branch' exists",
444 my $exit_val = system("$CMD \"$branch\" >/dev/null 2>/dev/null");
445 $exit_val = $exit_val >> 8;
446 is
($exit_val, 0, "Delete '$branch', retval ok");
447 unlike
(`$GIT branch -a`,
449 ' ' . $branch . '\n' .
451 "Branch '$branch' is gone",
459 my ($remote, $desc) = @_;
460 testcmd
("$GIT fetch --prune $remote",
464 "Fetch from $remote ($desc)",
472 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
473 defined($descriptions{$Desc}) &&
474 BAIL_OUT
("testcmd(): '$Desc' description is used twice");
475 $descriptions{$Desc} = 1;
477 my $cmd_outp_str = $Opt{'verbose'} >= 1 ?
"\"$Cmd\" - " : '';
478 my $Txt = join('', $cmd_outp_str, defined($Desc) ?
$Desc : '');
479 my $TMP_STDERR = "$CMD_BASENAME-stderr.tmp";
482 if (defined($Exp_stderr)) {
483 $stderr_cmd = " 2>$TMP_STDERR";
485 $retval &= is
(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
487 if (defined($Exp_stderr)) {
488 $retval &= is
(file_data
($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
491 diag
("Warning: stderr not defined for '$Txt'");
493 $retval &= is
($ret_val >> 8, $Exp_retval, "$Txt (retval)");
501 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
502 defined($descriptions{$Desc}) &&
503 BAIL_OUT
("likecmd(): '$Desc' description is used twice");
504 $descriptions{$Desc} = 1;
506 my $cmd_outp_str = $Opt{'verbose'} >= 1 ?
"\"$Cmd\" - " : '';
507 my $Txt = join('', $cmd_outp_str, defined($Desc) ?
$Desc : '');
508 my $TMP_STDERR = "$CMD_BASENAME-stderr.tmp";
511 if (defined($Exp_stderr)) {
512 $stderr_cmd = " 2>$TMP_STDERR";
514 $retval &= like
(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
516 if (defined($Exp_stderr)) {
517 $retval &= like
(file_data
($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
520 diag
("Warning: stderr not defined for '$Txt'");
522 $retval &= is
($ret_val >> 8, $Exp_retval, "$Txt (retval)");
529 # Return file content as a string {{{
533 open(my $fp, '<', $File) or return undef;
542 # Print program version {{{
543 print("$progname $VERSION\n");
549 # Send the help message to stdout {{{
552 if ($Opt{'verbose'}) {
558 Usage: $progname [options]
560 Contains tests for the $CMD_BASENAME(1) program.
565 Run all tests, also TODOs.
567 Specify alternative git executable to use. Used to execute the tests
568 with different git versions. This can also be set with the
569 GIT_DBR_GIT environment variable.
573 Be more quiet. Can be repeated to increase silence.
575 Run only the TODO tests.
577 Increase level of verbosity. Can be repeated.
579 Print version information.
587 # Print a status message to stderr based on verbosity level {{{
588 my ($verbose_level, $Txt) = @_;
590 $verbose_level > $Opt{'verbose'} && return;
591 print(STDERR
"$progname: $Txt\n");
598 # This program is free software; you can redistribute it and/or modify
599 # it under the terms of the GNU General Public License as published by
600 # the Free Software Foundation; either version 2 of the License, or (at
601 # your option) any later version.
603 # This program is distributed in the hope that it will be useful, but
604 # WITHOUT ANY WARRANTY; without even the implied warranty of
605 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
606 # See the GNU General Public License for more details.
608 # You should have received a copy of the GNU General Public License
609 # along with this program.
610 # If not, see L<http://www.gnu.org/licenses/>.
612 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :