1 # Copyright (c) 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License version 2 as published
5 # by the Free Software Foundation.
7 # This program is distributed in the hope that it will be useful, but
8 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 # You should have received a copy of the GNU General Public License along
13 # with this program; if not, write to the Free Software Foundation, Inc.,
14 # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
17 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19 use Test::More tests => 33;
21 use lib "@amperldir@";
23 use Installcheck::Config;
24 use Installcheck::Run qw(run run_get run_err $diskname);
25 use Installcheck::Dumpcache;
26 use File::Path qw(rmtree mkpath);
35 unless ($Installcheck::Run::have_expect) {
37 skip("Expect.pm not available", Test::More->builder->expected_tests);
44 # Not all features of amfetchdump can be tested without a lot of extra work:
45 # --header-fd: Expect doesn't pass through nonstandard fd's
46 # -p: Expect would have to deal with the dumpfile data, which it won't like
56 my $testdir = "$Installcheck::TMP/amfetchdump-installcheck/files";
63 Amanda::Debug::dbopen("installcheck");
64 Installcheck::log_test_output();
67 for my $filename (<$testdir/*>) {
73 my ($count, $msg) = @_;
76 my @filenames = <localhost.*>;
78 # check for .tmp files and empty files
79 for my $fn (@filenames) {
80 if ($fn =~ /\.tmp$/ || -z "$testdir/$fn") {
85 if (scalar @filenames != $count) {
86 diag("expected $count files");
90 # capture file size if there's only one file
91 if (@filenames == 1) {
92 $last_file_size = -s $filenames[0];
95 ok($ok, $msg) or diag(`ls -l $testdir`);
98 Installcheck::Dumpcache::load("basic");
100 like(run_err('amfetchdump', 'TESTCONF'),
102 "'amfetchdump TESTCONF' gives usage message on stderr");
104 like(run_err('amfetchdump', '-b', '65536', 'TESTCONF', 'localhost'),
105 qr{ERROR: The -b option is no longer},
106 "-b option gives a warning stderr");
113 $exp = Installcheck::Run::run_expect('amfetchdump', 'TESTCONF', 'localhost');
118 [ qr{1 (tape|volume)\(s\) needed for restoration}, sub {
119 push @results, "tape-count";
122 [ qr{The following (tapes|volumes) are needed: TESTCONF01}, sub {
123 push @results, "tapes-needed";
126 [ qr{amfetchdump: 1: restoring split dumpfile: date [[:digit:]]+ host localhost disk .*},
128 push @results, "restoring";
131 [ 'Press enter when ready', sub {
132 push @results, "press-enter";
137 push @results, "eof";
140 is_deeply([ @results ], [ "tape-count", "tapes-needed", "press-enter", "restoring", "eof" ],
141 "simple restore follows the correct steps");
143 got_files(1, "..and restored file is present in testdir");
150 ok(run('amfetchdump', '-a', '-l', 'TESTCONF', 'localhost'),
151 "run with -a and -l successful");
153 got_files(1, "..and restored file is present in testdir ($last_file_size bytes)");
154 my $uncomp_size = $last_file_size;
157 # -C (should make output file smaller)
161 ok(run('amfetchdump', '-a', '-C', 'TESTCONF', 'localhost'),
162 "run with -a and -C successful");
164 got_files(1, "..and restored file is present in testdir");
166 ok($last_file_size < $uncomp_size,
167 "..and is smaller than previous run ($last_file_size bytes)");
173 chdir($Installcheck::TMP);
175 $exp = Installcheck::Run::run_expect('amfetchdump', '-O', $testdir, 'TESTCONF', 'localhost');
180 [ qr{1 (tape|volume)\(s\) needed for restoration}, sub {
181 push @results, "tape-count";
184 [ qr{The following (tapes|volumes) are needed: TESTCONF01}, sub {
185 push @results, "tapes-needed";
188 [ qr{amfetchdump: 1: restoring split dumpfile: date [[:digit:]]+ host localhost disk .*},
190 push @results, "restoring";
193 [ 'Press enter when ready', sub {
194 push @results, "press-enter";
199 push @results, "eof";
202 is_deeply([ @results ], [ "tape-count", "tapes-needed", "press-enter", "restoring", "eof" ],
203 "restore with -O follows the correct steps");
206 got_files(1, "..and restored file is present in testdir");
213 $exp = Installcheck::Run::run_expect('amfetchdump', '-h', 'TESTCONF', 'localhost');
218 [ qr{1 (tape|volume)\(s\) needed for restoration}, sub {
219 push @results, "tape-count";
222 [ qr{The following (tapes|volumes) are needed: TESTCONF01}, sub {
223 push @results, "tapes-needed";
226 [ qr{amfetchdump: 1: restoring split dumpfile: date [[:digit:]]+ host localhost disk .*},
228 push @results, "restoring";
231 [ 'Press enter when ready', sub {
232 push @results, "press-enter";
237 push @results, "eof";
240 is_deeply([ @results ], [ "tape-count", "tapes-needed", "press-enter", "restoring", "eof" ],
241 "restore with -h follows the correct steps");
243 $fok = got_files(1, "..and restored file is present in testdir");
245 # check that it starts with a header
247 my @filenames = <localhost.*>;
248 open(my $fh, "<", $filenames[0]) or die "error opening: $!";
249 sysread($fh, my $hdr_dat, 32768) or die "error reading: $!";
251 my $hdr = Amanda::Header->from_string($hdr_dat);
252 is($hdr->{type}+0, $Amanda::Header::F_SPLIT_DUMPFILE,
253 "..dumpfile begins with a split dumpfile header");
263 $exp = Installcheck::Run::run_expect('amfetchdump', '--header-file', 'hdr',
264 'TESTCONF', 'localhost');
269 [ qr{1 (tape|volume)\(s\) needed for restoration}, sub {
270 push @results, "tape-count";
273 [ qr{The following (tapes|volumes) are needed: TESTCONF01}, sub {
274 push @results, "tapes-needed";
277 [ qr{amfetchdump: 1: restoring split dumpfile: date [[:digit:]]+ host localhost disk .*},
279 push @results, "restoring";
282 [ 'Press enter when ready', sub {
283 push @results, "press-enter";
288 push @results, "eof";
291 is_deeply([ @results ], [ "tape-count", "tapes-needed", "press-enter", "restoring", "eof" ],
292 "restore with --header-file follows the correct steps");
294 $fok = got_files(1, "..and restored file is present in testdir");
296 # check that it starts with a header
298 my @filenames = <localhost.*>;
299 open(my $fh, "<", "$testdir/hdr") or die "error opening: $!";
300 sysread($fh, my $hdr_dat, 32768) or die "error reading: $!";
302 my $hdr = Amanda::Header->from_string($hdr_dat);
303 is($hdr->{type}+0, $Amanda::Header::F_SPLIT_DUMPFILE,
304 "..and the header file contains the right header");
310 # -d and prompting for volumes one at a time
314 my $vfsdev = 'file:' . Installcheck::Run::vtape_dir();
315 Installcheck::Run::load_vtape(3); # wrong vtape
316 $exp = Installcheck::Run::run_expect('amfetchdump', '-d', $vfsdev,
317 'TESTCONF', 'localhost');
322 [ qr{1 (tape|volume)\(s\) needed for restoration}, sub {
323 push @results, "tape-count";
326 [ qr{The following (tapes|volumes) are needed: TESTCONF01}, sub {
327 push @results, "tapes-needed";
330 [ 'Press enter when ready', sub {
331 push @results, "press-enter";
335 [ qr{Insert (tape|volume) labeled '?TESTCONF01'? in .*\n.*to abort}, sub {
336 push @results, "insert-tape";
337 Installcheck::Run::load_vtape(1); # right vtape
341 [ qr{amfetchdump: 1: restoring split dumpfile: date [[:digit:]]+ host localhost disk .*},
343 push @results, "restoring";
347 push @results, "eof";
350 is_deeply([ @results ], [ "tape-count", "tapes-needed", "press-enter",
351 "insert-tape", "restoring", "eof" ],
352 "restore with an explicit device follows the correct steps, prompting for each");
354 got_files(1, "..and restored file is present in testdir");
357 # -n (using a multipart dump)
359 Installcheck::Dumpcache::load("parts");
362 $exp = Installcheck::Run::run_expect('amfetchdump', '-n', 'TESTCONF', 'localhost');
367 [ qr{1 (tape|volume)\(s\) needed for restoration}, sub {
368 push @results, "tape-count";
371 [ qr{The following (tapes|volumes) are needed: TESTCONF01}, sub {
372 push @results, "tapes-needed";
375 [ qr{amfetchdump: (\d+): restoring split dumpfile: date [[:digit:]]+ host localhost disk .*},
377 push @results, "restoring";
380 [ 'Press enter when ready', sub {
381 push @results, "press-enter";
386 push @results, "eof";
389 is_deeply([ @results ], [ "tape-count", "tapes-needed", "press-enter",
390 ("restoring",)x9, "eof" ],
391 "restore with -n follows the correct steps");
393 got_files(9, "..and restored file is present in testdir");
396 # -l, no options, and -c for compressed dumps
398 Installcheck::Dumpcache::load("compress");
401 ok(run('amfetchdump', '-a', 'TESTCONF', 'localhost'),
402 "run with -a successful (should uncompress)");
404 got_files(1, "..and restored file is present in testdir ($last_file_size bytes)");
405 $uncomp_size = $last_file_size;
409 ok(run('amfetchdump', '-a', '-l', 'TESTCONF', 'localhost'),
410 "run with -a and -l successful (should not uncompress)");
412 got_files(1, "..and restored file is present in testdir");
414 ok($last_file_size < $uncomp_size,
415 "..and is smaller than previous run ($last_file_size bytes)");
419 ok(run('amfetchdump', '-a', '-c', 'TESTCONF', 'localhost'),
420 "run with -a and -c successful (should not uncompress)");
422 got_files(1, "..and restored file is present in testdir");
424 ok($last_file_size < $uncomp_size,
425 "..and is smaller than previous run ($last_file_size bytes)");
427 Installcheck::Dumpcache::load("multi");
430 $exp = Installcheck::Run::run_expect('amfetchdump', 'TESTCONF', 'localhost');
435 [ qr{2 (tape|volume)\(s\) needed for restoration}, sub {
436 push @results, "tape-count";
439 [ qr{The following (tapes|volumes) are needed: TESTCONF01 TESTCONF02.*}, sub {
440 push @results, "tapes-needed";
443 [ qr{2 holding file\(s\) needed for restoration}, sub {
444 push @results, "holding-count";
447 [ qr{Reading .*\nFILE: date [[:digit:]]+ host localhost disk .*},
449 push @results, "reading";
452 [ 'Press enter when ready', sub {
453 push @results, "press-enter";
458 push @results, "eof";
461 is_deeply([ @results ], [ "tape-count", "tapes-needed", "holding-count",
462 "press-enter", "reading", "reading", "eof" ],
463 "restore from holding follows the correct steps");
465 got_files(6, "..and all restored files are present in testdir");
469 skip "Expect not installed or not built with ndmp and server", 2 unless
470 Amanda::Util::built_with_component("ndmp") and
471 Amanda::Util::built_with_component("server") and
472 $Installcheck::Run::have_expect;
475 Installcheck::Dumpcache::load("ndmp");
476 my $ndmp = Installcheck::Mock::NdmpServer->new(no_reset => 1);
477 $ndmp->edit_config();
481 $exp = Installcheck::Run::run_expect('amfetchdump', 'TESTCONF', 'localhost');
486 [ qr{1 (tape|volume)\(s\) needed for restoration}, sub {
487 push @results, "tape-count";
490 [ qr{The following (tapes|volumes) are needed: TESTCONF01}, sub {
491 push @results, "tapes-needed";
494 [ qr{amfetchdump: 1: restoring split dumpfile: date [[:digit:]]+ host localhost disk .*},
496 push @results, "restoring";
499 [ 'Press enter when ready', sub {
500 push @results, "press-enter";
505 push @results, "eof";
508 is_deeply([ @results ], [ "tape-count", "tapes-needed", "press-enter", "restoring", "eof" ],
509 "ndmp restore follows the correct steps");
511 got_files(1, "..and restored file is present in testdir");
514 chdir("$testdir/..");