Blame installcheck/ambsdtar.pl

Packit Service 392537
# Copyright (c) 2009-2012 Zmanda, Inc.  All Rights Reserved.
Packit Service 392537
# Copyright (c) 2013-2016 Carbonite, Inc.  All Rights Reserved.
Packit Service 392537
#
Packit Service 392537
# This program is free software; you can redistribute it and/or
Packit Service 392537
# modify it under the terms of the GNU General Public License
Packit Service 392537
# as published by the Free Software Foundation; either version 2
Packit Service 392537
# of the License, or (at your option) any later version.
Packit Service 392537
#
Packit Service 392537
# This program is distributed in the hope that it will be useful, but
Packit Service 392537
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 392537
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit Service 392537
# for more details.
Packit Service 392537
#
Packit Service 392537
# You should have received a copy of the GNU General Public License along
Packit Service 392537
# with this program; if not, write to the Free Software Foundation, Inc.,
Packit Service 392537
# 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
Packit Service 392537
#
Packit Service 392537
# Contact information: Carbonite Inc., 756 N Pastoria Ave
Packit Service 392537
# Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
Packit Service 392537
Packit Service 392537
use Test::More tests => 36;
Packit Service 392537
Packit Service 392537
use lib "@amperldir@";
Packit Service 392537
use strict;
Packit Service 392537
use warnings;
Packit Service 392537
use Installcheck;
Packit Service 392537
use Amanda::Constants;
Packit Service 392537
use Amanda::Paths;
Packit Service 392537
use File::Path;
Packit Service 392537
use Installcheck::Application;
Packit Service 392537
use IO::File;
Packit Service 392537
use Data::Dumper;
Packit Service 392537
use Amanda::Debug;
Packit Service 392537
Packit Service 392537
unless ($Amanda::Constants::BSDTAR and -x $Amanda::Constants::BSDTAR) {
Packit Service 392537
    SKIP: {
Packit Service 392537
        skip("BSDtar is not available", Test::More->builder->expected_tests);
Packit Service 392537
    }
Packit Service 392537
    exit 0;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
Amanda::Debug::dbopen("installcheck");
Packit Service 392537
Installcheck::log_test_output();
Packit Service 392537
Packit Service 392537
my $app = Installcheck::Application->new('ambsdtar');
Packit Service 392537
Packit Service 392537
my $support = $app->support();
Packit Service 392537
is($support->{'INDEX-LINE'}, 'YES', "supports indexing");
Packit Service 392537
is($support->{'MESSAGE-LINE'}, 'YES', "supports messages");
Packit Service 392537
is($support->{'CALCSIZE'}, 'YES', "supports calcsize");
Packit Service 392537
Packit Service 392537
my $root_dir = "$Installcheck::TMP/installcheck-ambsdtar";
Packit Service 392537
my $back_dir = "$root_dir/to_backup";
Packit Service 392537
my $rest_dir = "$root_dir/restore";
Packit Service 392537
my $list_dir = "$root_dir/list";
Packit Service 392537
Packit Service 392537
mkpath("$Amanda::Paths::amdatadir/bsdtar");
Packit Service 392537
Packit Service 392537
sub ok_foreach {
Packit Service 392537
    my $code = shift @_;
Packit Service 392537
    my $stringify = shift @_;
Packit Service 392537
    my $name = shift @_;
Packit Service 392537
    my @list = @_;
Packit Service 392537
Packit Service 392537
    my @errors;
Packit Service 392537
    foreach my $elm (@list) {
Packit Service 392537
        my $elm_str = $stringify? $stringify->($elm) : "$elm";
Packit Service 392537
        push @errors, "on element $elm_str: $@" unless eval {$code->($elm); 1;};
Packit Service 392537
    }
Packit Service 392537
    unless (ok(!@errors, $name)) {
Packit Service 392537
        foreach my $err (@errors) {
Packit Service 392537
            diag($err);
Packit Service 392537
        }
Packit Service 392537
    }
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
ok_foreach(
Packit Service 392537
    sub {
Packit Service 392537
        my $dir = shift @_;
Packit Service 392537
        rmtree($dir);
Packit Service 392537
    },
Packit Service 392537
    undef,
Packit Service 392537
    "emptied directories",
Packit Service 392537
    $back_dir, $rest_dir, $list_dir);
Packit Service 392537
Packit Service 392537
ok_foreach(
Packit Service 392537
    sub {
Packit Service 392537
        my $dir = shift @_;
Packit Service 392537
        mkpath($dir);
Packit Service 392537
    },
Packit Service 392537
    undef,
Packit Service 392537
    "create directories",
Packit Service 392537
    $back_dir, $rest_dir, $list_dir);
Packit Service 392537
Packit Service 392537
Packit Service 392537
my @dir_struct = (
Packit Service 392537
    {'type' => 'f', 'name' => 'foo'},
Packit Service 392537
    {'type' => 'd', 'name' => 'bar/baz/bat/'},
Packit Service 392537
    {'type' => 'h', 'name' => 'hard', 'to' => 'foo'},
Packit Service 392537
    {'type' => 's', 'name' => 'sym', 'to' => 'bar'},
Packit Service 392537
    {'type' => 's', 'name' => 'a', 'to' => 'b'},
Packit Service 392537
    {'type' => 's', 'name' => 'b', 'to' => 'a'},
Packit Service 392537
);
Packit Service 392537
Packit Service 392537
ok_foreach(
Packit Service 392537
    sub {
Packit Service 392537
        my $obj = shift @_;
Packit Service 392537
Packit Service 392537
        if ($obj->{'type'} eq 'f') {
Packit Service 392537
            my $fh = new IO::File("$back_dir/$obj->{'name'}", '>');
Packit Service 392537
            ok($fh, "created file $obj->{'name'}");
Packit Service 392537
            undef $fh;
Packit Service 392537
        } elsif ($obj->{'type'} eq 'd') {
Packit Service 392537
            mkpath("$back_dir/$obj->{'name'}");
Packit Service 392537
        } elsif ($obj->{'type'} eq 'h') {
Packit Service 392537
            link("$back_dir/$obj->{'to'}", "$back_dir/$obj->{'name'}") or die "$!";
Packit Service 392537
        } elsif ($obj->{'type'} eq 's') {
Packit Service 392537
            symlink("$obj->{'to'}", "$back_dir/$obj->{'name'}") or die "$!";
Packit Service 392537
        } else {
Packit Service 392537
            die "unknown object type $obj->{'type'} for $obj->{'name'}";
Packit Service 392537
        }
Packit Service 392537
    },
Packit Service 392537
    sub {shift(@_)->{'name'}},
Packit Service 392537
    "create directory structure",
Packit Service 392537
    @dir_struct);
Packit Service 392537
Packit Service 392537
my $selfcheck = $app->selfcheck_message('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($selfcheck->{'exit_status'}, 0, "error status ok");
Packit Service 392537
ok(!@{$selfcheck->{'errors'}}, "no errors during selfcheck");
Packit Service 392537
Packit Service 392537
my $backup = $app->backup('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($backup->{'exit_status'}, 0, "error status ok");
Packit Service 392537
ok(!@{$backup->{'errors'}}, "no errors during backup")
Packit Service 392537
    or diag(@{$backup->{'errors'}});
Packit Service 392537
Packit Service 392537
is(length($backup->{'data'}), $backup->{'size'}, "reported and actual size match");
Packit Service 392537
Packit Service 392537
ok(@{$backup->{'index'}}, "index is not empty");
Packit Service 392537
ok_foreach(
Packit Service 392537
    sub {
Packit Service 392537
        my $obj = shift @_;
Packit Service 392537
        my $name = $obj->{'name'};
Packit Service 392537
        die "missing $name" unless
Packit Service 392537
            grep {"/$name" eq $_} @{$backup->{'index'}};
Packit Service 392537
    },
Packit Service 392537
    sub {shift(@_)->{'name'}},
Packit Service 392537
    "index contains all names/paths",
Packit Service 392537
    @dir_struct);
Packit Service 392537
Packit Service 392537
my $orig_cur_dir = POSIX::getcwd();
Packit Service 392537
ok($orig_cur_dir, "got current directory");
Packit Service 392537
Packit Service 392537
ok(chdir($rest_dir), "changed working directory (for restore)");
Packit Service 392537
Packit Service 392537
my $restore = $app->restore('objects' => ['./hard', './foo', './bar'], 'data' => $backup->{'data'});
Packit Service 392537
is($restore->{'exit_status'}, 0, "error status ok");
Packit Service 392537
Packit Service 392537
ok(chdir($orig_cur_dir), "changed working directory (back to original)");
Packit Service 392537
Packit Service 392537
ok(-f "$rest_dir/hard", "hard restored");
Packit Service 392537
ok(-f "$rest_dir/foo", "foo restored");
Packit Service 392537
ok(-d "$rest_dir/bar", "bar/ restored");
Packit Service 392537
ok(-d "$rest_dir/bar", "bar/baz/bat/ restored");
Packit Service 392537
Packit Service 392537
$app->add_property('BSDTAR-PATH' => '/do/not/exists');
Packit Service 392537
$restore = $app->restore('objects' => ['./hard', './foo', './bar'], 'data' => $backup->{'data'});
Packit Service 392537
is($restore->{'exit_status'}, 256, "error status of 1 if BSDTAR-PATH does not exists");
Packit Service 392537
chomp $restore->{'errs'};
Packit Service 392537
if ($Amanda::Constants::SINGLE_USERID) {
Packit Service 392537
    ok($restore->{'errs'} =~ /ambsdtar: error \[exec \/do\/not\/exists: No such file or directory\]\nerror \[\/do\/not\/exists exited with status 1: see .*/, "correct error for No such file or directory")
Packit Service 392537
	or diag($restore->{'errs'});
Packit Service 392537
} else {
Packit Service 392537
    ok($restore->{'errs'} eq "Can't find real path for '/do/not/exists': No such file or directory", "correct error for No such file or directory")
Packit Service 392537
	or diag($restore->{'errs'});
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
my $pwd = `pwd`;
Packit Service 392537
my $bad_bsdtar = "$Installcheck::TMP/bad-bsdtar";
Packit Service 392537
open TOTO, ">$bad_bsdtar";
Packit Service 392537
close TOTO;
Packit Service 392537
$app->add_property('BSDTAR-PATH', "$bad_bsdtar");
Packit Service 392537
Packit Service 392537
$selfcheck = $app->selfcheck_message('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($selfcheck->{'exit_status'}, 0, "error status ok");
Packit Service 392537
if ($Amanda::Constants::SINGLE_USERID) {
Packit Service 392537
    ok($selfcheck->{'errors'}[0]->{code} eq '3600063' &&
Packit Service 392537
       $selfcheck->{'errors'}[0]->{errnocode} eq 'EACCES', "good error selfcheck ")
Packit Service 392537
	or diag(Data::Dumper::Dumper(\@{$selfcheck->{'errors'}}));
Packit Service 392537
} else {
Packit Service 392537
    ok($selfcheck->{'errors'}[0]->{code} eq '3600096' &&
Packit Service 392537
       $selfcheck->{'errors'}[0]->{security_file} eq $Amanda::Paths::SECURITY_FILE &&
Packit Service 392537
       $selfcheck->{'errors'}[0]->{prefix} eq "ambsdtar:bsdtar_path" &&
Packit Service 392537
       $selfcheck->{'errors'}[0]->{prefix} eq 'ambsdtar:bsdtar_path', "good error selfcheck ")
Packit Service 392537
	or diag(Data::Dumper::Dumper(\@{$selfcheck->{'errors'}}));
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
my $estimate = $app->estimate('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($estimate->{'exit_status'}, 256, "error status ok");
Packit Service 392537
if ($Amanda::Constants::SINGLE_USERID) {
Packit Service 392537
    ok($estimate->{'errors'}[0] =~ /no size line match in $bad_bsdtar output$bad_bsdtar exited with status 1: see .*/, "good error estimate")
Packit Service 392537
	or diag(Data::Dumper::Dumper(\@{$estimate->{'errors'}}));
Packit Service 392537
} else {
Packit Service 392537
    is($estimate->{'errors'}[0], "security file '$SECURITY_FILE' do not allow to run '$bad_bsdtar' as root for 'ambsdtar:bsdtar_path'", "good error estimate")
Packit Service 392537
	or diag(Data::Dumper::Dumper(\@{$estimate->{'errors'}}));
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
$backup = $app->backup('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($backup->{'exit_status'}, 256, "error status ok");
Packit Service 392537
if ($Amanda::Constants::SINGLE_USERID) {
Packit Service 392537
    is($backup->{'errors'}[0], "ambsdtar: error [exec $bad_bsdtar: Permission denied]", "good error backup")
Packit Service 392537
	or diag(Data::Dumper::Dumper(\@{$backup->{'errors'}}));
Packit Service 392537
} else {
Packit Service 392537
    is($backup->{'errors'}[0], "security file '$SECURITY_FILE' do not allow to run '$bad_bsdtar' as root for 'ambsdtar:bsdtar_path'", "good error backup")
Packit Service 392537
	or diag(Data::Dumper::Dumper(\@{$backup->{'errors'}}));
Packit Service 392537
}
Packit Service 392537
$app->delete_property('BSDTAR-PATH');
Packit Service 392537
unlink "$bad_bsdtar";
Packit Service 392537
Packit Service 392537
my $state_dir = "$Installcheck::TMP/ambsdtar-state_dir";
Packit Service 392537
open XX, ">$state_dir";
Packit Service 392537
close XX;
Packit Service 392537
chmod(0000, $state_dir);
Packit Service 392537
$app->add_property('STATE-DIR', $state_dir);
Packit Service 392537
$selfcheck = $app->selfcheck_message('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($selfcheck->{'exit_status'}, 0, "error status ok");
Packit Service 392537
ok($selfcheck->{'errors'}[0]->{code} eq '3600061' &&
Packit Service 392537
   $selfcheck->{'errors'}[0]->{message} eq "$state_dir is not a directory", "good error selfcheck ")
Packit Service 392537
    or diag(Data::Dumper::Dumper(\@{$selfcheck->{'errors'}}));
Packit Service 392537
Packit Service 392537
$estimate = $app->estimate('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($estimate->{'exit_status'}, 256, "error status ok");
Packit Service 392537
is($estimate->{'errors'}[0], "$state_dir is not a directory", "good error estimate")
Packit Service 392537
    or diag(Data::Dumper::Dumper(\@{$estimate->{'errors'}}));
Packit Service 392537
Packit Service 392537
$backup = $app->backup('device' => $back_dir, 'level' => 0, 'index' => 'line');
Packit Service 392537
is($backup->{'exit_status'}, 256, "error status ok");
Packit Service 392537
is($backup->{'errors'}[0], "$state_dir is not a directory", "good error backup")
Packit Service 392537
    or diag(Data::Dumper::Dumper(\@{$backup->{'errors'}}));
Packit Service 392537
unlink $state_dir;
Packit Service 392537
Packit Service 392537
# cleanup
Packit Service 392537
rmtree($root_dir);