installed_progs.t: Python checks stdout too, 150 ok
[sunny256-utils.git] / tests / mktar.t
blob5783f8880bed1b6bcdba60b25a310f5565d77432
1 #!/usr/bin/env perl
3 #==============================================================================
4 # mktar.t
5 # File ID: dd9b31a6-457a-11e8-96de-f74d993421b0
7 # Test suite for mktar(1).
9 # Character set: UTF-8
10 # ©opyleft 2018– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License version 2 or later, see end of file for
12 # legal stuff.
13 #==============================================================================
15 use strict;
16 use warnings;
18 use File::Basename;
20 BEGIN {
21 use Test::More qw{no_plan};
22 # use_ok() goes here
25 use Getopt::Long;
27 local $| = 1;
29 our $CMDB = "mktar";
30 our $CMD = "../$CMDB";
31 my $Lh = "[0-9a-fA-F]";
32 my $v1_templ = "$Lh\{8}-$Lh\{4}-1$Lh\{3}-$Lh\{4}-$Lh\{12}";
34 our %Opt = (
36 'all' => 0,
37 'help' => 0,
38 'quiet' => 0,
39 'todo' => 0,
40 'verbose' => 0,
41 'version' => 0,
45 our $progname = $0;
46 $progname =~ s/^.*\/(.*?)$/$1/;
47 our $VERSION = '0.0.0';
49 my %descriptions = ();
51 Getopt::Long::Configure('bundling');
52 GetOptions(
54 'all|a' => \$Opt{'all'},
55 'help|h' => \$Opt{'help'},
56 'quiet|q+' => \$Opt{'quiet'},
57 'todo|t' => \$Opt{'todo'},
58 'verbose|v+' => \$Opt{'verbose'},
59 'version' => \$Opt{'version'},
61 ) || die("$progname: Option error. Use -h for help.\n");
63 $Opt{'verbose'} -= $Opt{'quiet'};
64 $Opt{'help'} && usage(0);
65 if ($Opt{'version'}) {
66 print_version();
67 exit(0);
70 exit(main());
72 sub main {
73 my $Retval = 0;
74 my $logdir = "logdir.tmp";
76 $ENV{'SUUID_LOGDIR'} = $logdir;
78 diag(sprintf('========== Executing %s v%s ==========',
79 $progname, $VERSION));
81 if ($Opt{'todo'} && !$Opt{'all'}) {
82 goto todo_section;
85 test_standard_options();
87 ok(chdir("mktar-files"), "chdir mktar-files") or
88 BAIL_OUT("Cannot chdir");
89 $CMD = "../$CMD";
91 if (-e $logdir) {
92 diag("NOTICE: $logdir exists, deleting it");
93 system("rm -rf \"$logdir\"");
95 ok(mkdir("$logdir"), "mkdir $logdir");
97 test_numeric_owner_option($CMD, $CMDB, $logdir);
98 test_output_dir_option($CMD, $CMDB, $logdir);
99 test_prefix_option($CMD, $CMDB, $logdir);
100 test_random_mac_option($CMD, $CMDB, $logdir);
101 test_remove_files_option($CMD, $CMDB, $logdir);
102 test_stdout_option($CMD, $CMDB, $logdir);
103 test_no_uuid_option($CMD, $CMDB, $logdir);
104 # FIXME: Add more tests, cover all options
105 diag("Clean up");
106 testcmd("rm -rf \"$logdir\"", "", "", 0,
107 "Delete $logdir/ before exit");
109 todo_section:
112 if ($Opt{'all'} || $Opt{'todo'}) {
113 diag('Running TODO tests...');
114 TODO: {
115 local $TODO = '';
116 # Insert TODO tests here.
120 diag('Testing finished.');
122 return $Retval;
125 sub test_standard_options {
126 diag('Testing -h (--help) option...');
127 likecmd("$CMD -h",
128 '/ Show this help/i',
129 '/^$/',
131 'Option -h prints help screen');
133 diag('Testing -v (--verbose) option...');
134 likecmd("$CMD -hv",
135 '/^\n\S+ \d+\.\d+\.\d+/s',
136 '/^$/',
138 'Option -v with -h returns version number and help screen');
140 diag('Testing --version option...');
141 likecmd("$CMD --version",
142 '/^\S+ \d+\.\d+\.\d+/',
143 '/^$/',
145 'Option --version returns version number');
146 return;
149 sub test_numeric_owner_option {
150 my ($CMD, $CMDB, $logdir) = @_;
152 diag("Test --numeric-owner option");
153 SKIP: {
154 skip("Running tests as root", 14) unless ($<);
156 extract_tar_file("d.tar");
157 testcmd("mv d has-numeric", "", "", 0, "mv d has-numeric");
158 unlink("has-numeric.tar") if -e "has-numeric.tar";
159 likecmd("$CMD -r --numeric-owner has-numeric",
160 '/^$/',
161 '/^' . join('',
162 '.*',
163 'mktar: Packing has-numeric\.\.\.\n',
164 $v1_templ, '\n',
165 'mktar: tar cf has-numeric\.tar ' .
166 '--remove-files --force-local ' .
167 '--sort=name --sparse ' .
168 '--numeric-owner --xattrs ' .
169 "--label=$v1_templ " .
170 'has-numeric',
171 '.*',
172 'has-numeric\.tar',
173 ) . '$/s',
175 "Use --numeric-owner",
178 my $uid = $>;
179 my $gid = $);
180 $gid =~ s/^(\d+)\b.*/$1/;
181 likecmd("tar tvf has-numeric.tar",
182 '/' . " $uid\\/$gid .+" x 8 . '/s',
183 '/^$/',
185 'has-numeric.tar contains numeric UID/GID',
188 ok(unlink("has-numeric.tar"), "Delete has-numeric.tar");
192 sub test_output_dir_option {
193 my ($CMD, $CMDB, $logdir) = @_;
194 my $pref = "output-dir";
195 my $outd = "outd.tmp";
197 diag("Test -o/--output-dir option");
198 if (-e $pref) {
199 diag("NOTICE: $pref exists, deleting it");
200 system("rm -rf $pref")
202 extract_tar_file("d.tar");
203 testcmd("mv d $pref", "", "", 0, "mv d $pref");
204 unlink("$pref.tar") if -e "$pref.tar";
205 if (-e $outd) {
206 diag("NOTICE: $outd exists, deleting it");
207 system("rm -rf $outd")
210 for my $p ("--output-dir", "-o") {
211 ok(mkdir($outd), "mkdir $outd");
212 likecmd("$CMD $p $outd $pref",
213 '/^$/',
214 '/^' . join('', '\n',
215 "mktar: Packing $pref\\.\\.\\.\\n",
216 $v1_templ, '\n',
217 "mktar: tar cf $outd\\/$pref\\.tar " .
218 '--force-local ' .
219 '--sort=name --sparse ' .
220 "--xattrs --label=$v1_templ $pref\\n" .
221 '.+',
222 "$pref\\.tar\\n",
223 ) . '$/s',
225 "Use $p",
227 ok(-f "$outd/$pref.tar", "$outd/$pref.tar exists");
228 ok(unlink("$outd/$pref.tar"), "Delete $outd/$pref.tar");
229 testcmd("rm -rf $outd", "", "", 0, "rm -rf $outd after $p");
231 testcmd("rm -rf $pref", "", "", 0, "rm -rf $pref");
234 sub test_prefix_option {
235 my ($CMD, $CMDB, $logdir) = @_;
237 extract_tar_file("d.tar");
238 for my $p ("-P", "--prefix") {
239 likecmd("$CMD $p tmp d",
240 '/^$/',
241 '/mktar: tar cf tmp\.d\.tar ' .
242 '--force-local --sort=name --sparse --xattrs ' .
243 "--label=$v1_templ " .
244 'd\\n/s',
246 "Use \"tmp\" prefix with $p");
247 ok(-f "tmp.d.tar", "tmp.d.tar exists");
248 testcmd("tar df tmp.d.tar", "", "", 0,
249 "Contents of the tar file is identical to d/ " .
250 "after $p");
251 ok(unlink("tmp.d.tar"), "Delete tmp.d.tar");
253 testcmd("rm -rf d", "", "", 0, "Delete d/ after -P/--prefix");
256 sub test_random_mac_option {
257 my ($CMD, $CMDB, $logdir) = @_;
259 diag("Test -m/--random-mac option");
260 extract_tar_file("d.tar");
261 testcmd("mv d use-random-mac", "", "", 0, "mv d use-random-mac");
262 unlink("use-random-mac.tar") if -e "use-random-mac.tar";
263 likecmd("$CMD -rf --random-mac use-random-mac",
264 '/^$/',
265 '/^' . join('',
266 '\n',
267 'mktar: Packing use-random-mac\.\.\.\n',
268 $v1_templ, '\n',
269 'mktar: tar cf use-random-mac\.tar ' .
270 '--remove-files --force-local ' .
271 '--sort=name --sparse ' .
272 '--xattrs ' .
273 "--label=$v1_templ " .
274 'use-random-mac',
275 '.*',
276 'use-random-mac\.tar',
277 ) . '$/s',
279 "Use --random-mac",
281 ok(unlink("use-random-mac.tar"), "Delete use-random-mac.tar");
284 sub test_remove_files_option {
285 my ($CMD, $CMDB, $logdir) = @_;
287 diag("Test -r/--remove-files option");
288 for my $opt ("-r", "--remove-files") {
289 extract_tar_file("d.tar");
290 if (-e "dir1") {
291 diag("NOTICE: dir1 exists, deleting it");
292 system("rm -rf dir1");
294 testcmd("mv d dir1", "", "", 0, "mv d dir1 ($opt)");
295 if (-e "dir1.tar") {
296 diag("NOTICE: dir1.tar exists, deleting it");
297 unlink("dir1.tar");
299 likecmd("$CMD $opt dir1",
300 '/^$/',
301 '/^'
302 . join('',
303 '\n',
304 'mktar: Packing dir1\.\.\.\n',
305 $v1_templ,
306 '\n',
307 'mktar: tar cf dir1\.tar '
308 . '--remove-files --force-local '
309 . '--sort=name --sparse '
310 . '--xattrs '
311 . "--label=$v1_templ "
312 . 'dir1',
313 '.*',
314 'dir1\.tar',
316 . '$/s',
318 "Use $opt",
320 ok(-f "dir1.tar", "dir1.tar exists after $opt");
321 ok(!-e "dir1", "dir1 is gone after $opt");
322 likecmd("tar tf dir1.tar",
323 '/^'
324 . $v1_templ . '\n'
325 . 'dir1\/\n'
326 . 'dir1\/brokenlink\.txt\n'
327 . 'dir1\/d\/\n'
328 . 'dir1\/d\/subfile\.txt\n'
329 . 'dir1\/emptydir\/\n'
330 . 'dir1\/file\.txt\n'
331 . 'dir1\/sublink\.txt\n'
332 . 'dir1\/symlink\.txt\n'
333 . '$/',
334 '/^$/',
336 "Filenames in dir1.tar are ok after $opt",
338 ok(unlink("dir1.tar"), "Delete dir1.tar");
342 sub test_stdout_option {
343 my ($CMD, $CMDB, $logdir) = @_;
345 diag("Test -O/--stdout option");
346 if (-e "d") {
347 diag("NOTICE: 'd' exists, deleting it");
348 system("rm -rf d");
350 extract_tar_file("d.tar");
351 for my $opt ("-O", "--stdout") {
352 testcmd("($CMD $opt --no-uuid d | tar t)",
353 "d/\n"
354 . "d/brokenlink.txt\n"
355 . "d/d/\n"
356 . "d/d/subfile.txt\n"
357 . "d/emptydir/\n"
358 . "d/file.txt\n"
359 . "d/sublink.txt\n"
360 . "d/symlink.txt\n",
361 "\nmktar: Packing d...\n"
362 . "mktar: Sending to stdout\n"
363 . "mktar: tar c --force-local --sort=name --sparse "
364 . "--xattrs d\n",
366 "Filenames in stdout look splendid with $opt",
369 testcmd('rm -r d', '', '', 0, 'Delete d/ after -O/--stdout');
372 sub test_no_uuid_option {
373 my ($CMD, $CMDB, $logdir) = @_;
375 diag("Test --no-uuid option");
376 extract_tar_file("d.tar");
377 testcmd("mv d no-uuid", "", "", 0, "mv d no-uuid");
378 unlink("no-uuid.tar") if -e "no-uuid.tar";
379 likecmd("$CMD -r --no-uuid no-uuid",
380 '/^$/',
381 '/^' . join('',
382 '\n',
383 'mktar: Packing no-uuid\.\.\.\n',
384 'mktar: tar cf no-uuid\.tar ' .
385 '--remove-files --force-local ' .
386 '--sort=name --sparse ' .
387 '--xattrs no-uuid',
388 '.*',
389 'no-uuid\.tar',
390 ) . '$/s',
392 "Use --no-uuid",
394 testcmd("tar tf no-uuid.tar",
395 join("\n",
396 "no-uuid/",
397 "no-uuid/brokenlink.txt",
398 "no-uuid/d/",
399 "no-uuid/d/subfile.txt",
400 "no-uuid/emptydir/",
401 "no-uuid/file.txt",
402 "no-uuid/sublink.txt",
403 "no-uuid/symlink.txt",
408 "no-uuid.tar doesn't contain UUID label",
410 ok(unlink("no-uuid.tar"), "Delete no-uuid.tar");
413 sub extract_tar_file {
414 my $file = shift;
416 testcmd("tar xf \"$file\"", "", "", 0, "Extract $file");
417 undef $descriptions{"Extract $file"};
418 my $base = basename($file, ".tar");
419 ok(-d $base, "$base/ exists and is a directory");
422 sub testcmd {
423 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
424 defined($descriptions{$Desc}) &&
425 BAIL_OUT("testcmd(): '$Desc' description is used twice");
426 $descriptions{$Desc} = 1;
427 my $stderr_cmd = '';
428 my $cmd_outp_str = $Opt{'verbose'} >= 1 ? "\"$Cmd\" - " : '';
429 my $Txt = join('', $cmd_outp_str, defined($Desc) ? $Desc : '');
430 my $TMP_STDERR = "$CMDB-stderr.tmp";
431 my $retval = 1;
433 if (defined($Exp_stderr)) {
434 $stderr_cmd = " 2>$TMP_STDERR";
436 $retval &= is(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
437 my $ret_val = $?;
438 if (defined($Exp_stderr)) {
439 $retval &= is(file_data($TMP_STDERR),
440 $Exp_stderr, "$Txt (stderr)");
441 unlink($TMP_STDERR);
442 } else {
443 diag("Warning: stderr not defined for '$Txt'");
445 $retval &= is($ret_val >> 8, $Exp_retval, "$Txt (retval)");
447 return $retval;
450 sub likecmd {
451 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
452 defined($descriptions{$Desc}) &&
453 BAIL_OUT("likecmd(): '$Desc' description is used twice");
454 $descriptions{$Desc} = 1;
455 my $stderr_cmd = '';
456 my $cmd_outp_str = $Opt{'verbose'} >= 1 ? "\"$Cmd\" - " : '';
457 my $Txt = join('', $cmd_outp_str, defined($Desc) ? $Desc : '');
458 my $TMP_STDERR = "$CMDB-stderr.tmp";
459 my $retval = 1;
461 if (defined($Exp_stderr)) {
462 $stderr_cmd = " 2>$TMP_STDERR";
464 $retval &= like(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
465 my $ret_val = $?;
466 if (defined($Exp_stderr)) {
467 $retval &= like(file_data($TMP_STDERR),
468 $Exp_stderr, "$Txt (stderr)");
469 unlink($TMP_STDERR);
470 } else {
471 diag("Warning: stderr not defined for '$Txt'");
473 $retval &= is($ret_val >> 8, $Exp_retval, "$Txt (retval)");
475 return $retval;
478 sub file_data {
479 # Return file content as a string
480 my $File = shift;
481 my $Txt;
483 open(my $fp, '<', $File) or return undef;
484 local $/ = undef;
485 $Txt = <$fp>;
486 close($fp);
487 return $Txt;
490 sub create_file {
491 # Create new file and fill it with data
492 my ($file, $text) = @_;
493 my $retval = 0;
495 open(my $fp, ">$file") or return 0;
496 print($fp $text);
497 close($fp);
498 $retval = is(file_data($file), $text,
499 "$file was successfully created");
501 return $retval; # 0 if error, 1 if ok
504 sub print_version {
505 # Print program version
506 print("$progname $VERSION\n");
507 return;
510 sub usage {
511 # Send the help message to stdout
512 my $Retval = shift;
514 if ($Opt{'verbose'}) {
515 print("\n");
516 print_version();
518 print(<<"END");
520 Usage: $progname [options]
522 Contains tests for the $CMDB(1) program.
524 Options:
526 -a, --all
527 Run all tests, also TODOs.
528 -h, --help
529 Show this help.
530 -q, --quiet
531 Be more quiet. Can be repeated to increase silence.
532 -t, --todo
533 Run only the TODO tests.
534 -v, --verbose
535 Increase level of verbosity. Can be repeated.
536 --version
537 Print version information.
540 exit($Retval);
543 sub msg {
544 # Print a status message to stderr based on verbosity level
545 my ($verbose_level, $Txt) = @_;
547 $verbose_level > $Opt{'verbose'} && return;
548 print(STDERR "$progname: $Txt\n");
549 return;
552 __END__
554 # This program is free software; you can redistribute it and/or modify it under
555 # the terms of the GNU General Public License as published by the Free Software
556 # Foundation; either version 2 of the License, or (at your option) any later
557 # version.
559 # This program is distributed in the hope that it will be useful, but WITHOUT
560 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
561 # FOR A PARTICULAR PURPOSE.
562 # See the GNU General Public License for more details.
564 # You should have received a copy of the GNU General Public License along with
565 # this program.
566 # If not, see L<http://www.gnu.org/licenses/>.
568 # vim: set ts=8 sw=8 sts=8 noet fo+=w tw=79 fenc=UTF-8 :