1# Copyright (c) 2007-2013 Zmanda, Inc. All Rights Reserved. 2# 3# This program is free software; you can redistribute it and/or 4# modify it under the terms of the GNU General Public License 5# as published by the Free Software Foundation; either version 2 6# of the License, or (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, but 9# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 10# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11# for more details. 12# 13# You should have received a copy of the GNU General Public License along 14# with this program; if not, write to the Free Software Foundation, Inc., 15# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16# 17# Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300 18# Sunnyvale, CA 94086, USA, or: http://www.zmanda.com 19 20use Test::More tests => 54; 21use strict; 22use warnings; 23 24use lib "@amperldir@"; 25use Amanda::Paths; 26use Amanda::Cmdline qw( header_matches_dumpspecs ); 27use Amanda::Header; 28 29my @specs; 30my $hdr; 31 32# convert a dumpspec_t object to an array, for easy is_deeply() comparisons 33sub ds2av { 34 my ($ds) = @_; 35 return ( 36 $ds->{'host'}, 37 $ds->{'disk'}, 38 $ds->{'datestamp'}, 39 $ds->{'level'}, 40 $ds->{'write_timestamp'}, 41 ); 42} 43 44# test dumpspec_t objects 45 46is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", "di", "ds", "l", undef)) ], 47 [ "h", "di", "ds", "l", undef ], 48 "dumpspec_t constructor returns a valid dumpspec"); 49 50is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", "di", "ds", undef, undef)) ], 51 [ "h", "di", "ds", undef, undef ], 52 "dumpspec_t constructor returns a valid dumpspec with only 3 args"); 53 54is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", "di", undef, undef, undef)) ], 55 [ "h", "di", undef, undef, undef ], 56 "dumpspec_t constructor returns a valid dumpspec with only 2 args"); 57 58is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", undef, undef, undef, undef)) ], 59 [ "h", undef, undef, undef, undef ], 60 "dumpspec_t constructor returns a valid dumpspec with only 1 arg"); 61 62is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new(undef, undef, undef, undef, "wt")) ], 63 [ undef, undef, undef, undef, "wt" ], 64 "dumpspec_t constructor returns a valid dumpspec with only write_timestamp arg"); 65 66@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "h2", "d2"], 0); 67is(@specs, 2, "parse of four elements with no flags yields 2 specs"); 68is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", undef, undef, undef ], "..first spec is correct"); 69is_deeply([ ds2av($specs[1]) ], [ "h2", "d2", undef, undef, undef ], "..second spec is correct"); 70 71@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "h2", "d2"], $Amanda::Cmdline::CMDLINE_EXACT_MATCH); 72is(@specs, 2, "parse of four elements with CMDLINE_EXACT_MATCH yields 2 specs"); 73is_deeply([ ds2av($specs[0]) ], [ "=h1", "=d1", undef, undef, undef ], "..first spec is correct"); 74is_deeply([ ds2av($specs[1]) ], [ "=h2", "=d2", undef, undef, undef ], "..second spec is correct"); 75 76@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "h2", "d2", "ds2" ], $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP); 77is(@specs, 2, "parse of six elements with CMDLINE_PARSE_DATESTAMP yields 2 specs"); 78is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", undef, undef ], "..first spec is correct"); 79is_deeply([ ds2av($specs[1]) ], [ "h2", "d2", "ds2", undef, undef ], "..second spec is correct"); 80 81@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "h2", "d2", "ds2" ], $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_EXACT_MATCH); 82is(@specs, 2, "parse of six elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_EXACT_MATCH yields 2 specs"); 83is_deeply([ ds2av($specs[0]) ], [ "=h1", "=d1", "=ds1", undef, undef ], "..first spec is correct"); 84is_deeply([ ds2av($specs[1]) ], [ "=h2", "=d2", "=ds2", undef, undef ], "..second spec is correct"); 85 86@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "lv1", "h2", "d2", "ds2", "lv2" ], 87 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); 88is(@specs, 2, "parse of eight elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields 2 specs"); 89is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", "lv1", undef ], "..first spec is correct"); 90is_deeply([ ds2av($specs[1]) ], [ "h2", "d2", "ds2", "lv2", undef ], "..second spec is correct"); 91 92@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "lv1", "h2", "d2", "ds2", "lv2" ], 93 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL | $Amanda::Cmdline::CMDLINE_EXACT_MATCH); 94is(@specs, 2, "parse of eight elements with CMDLINE_PARSE_DATESTAMP, CMDLINE_PARSE_LEVEL and CMDLINE_EXACT_MATCH yields 2 specs"); 95is_deeply([ ds2av($specs[0]) ], [ "=h1", "=d1", "=ds1", "=lv1", undef ], "..first spec is correct"); 96is_deeply([ ds2av($specs[1]) ], [ "=h2", "=d2", "=ds2", "=lv2", undef ], "..second spec is correct"); 97 98@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "lv1" ], 99 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); 100is(@specs, 1, "parse of four elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); 101is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", "lv1", undef ], "..which is correct"); 102 103@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "lv1" ], 104 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL | $Amanda::Cmdline::CMDLINE_EXACT_MATCH); 105is(@specs, 1, "parse of four elements with CMDLINE_PARSE_DATESTAMP, CMDLINE_PARSE_LEVEL and CMDLINE_EXACT_MATCH yields one spec"); 106is_deeply([ ds2av($specs[0]) ], [ "=h1", "=d1", "=ds1", "=lv1", undef ], "..which is correct"); 107 108@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1" ], 109 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); 110is(@specs, 1, "parse of three elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); 111is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", undef, undef ], "..which is correct"); 112 113@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1" ], 114 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); 115is(@specs, 1, "parse of two elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); 116is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", undef, undef, undef ], "..which is correct"); 117 118@specs = Amanda::Cmdline::parse_dumpspecs(["h1" ], 119 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); 120is(@specs, 1, "parse of one element with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); 121is_deeply([ ds2av($specs[0]) ], [ "h1", undef, undef, undef, undef ], "..which is correct"); 122 123@specs = Amanda::Cmdline::parse_dumpspecs([], 124 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); 125is(@specs, 0, "parse of no elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields no specs"); 126 127@specs = Amanda::Cmdline::parse_dumpspecs([], 128 $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL 129 | $Amanda::Cmdline::CMDLINE_EMPTY_TO_WILDCARD); 130is(@specs, 1, "parse of no elements with CMDLINE_EMPTY_TO_WILDCARD yields one spec"); 131 132# test format_dumpspec_components 133 134is(Amanda::Cmdline::format_dumpspec_components("h", "di", "ds", "l"), 135 "h di ds l", 136 "format_dumpspec_components works ok"); 137 138# test matching 139$hdr = Amanda::Header->new(); 140$hdr->{'name'} = 'foo.bar.baz'; 141$hdr->{'disk'} = '/foo/bar/baz'; 142$hdr->{'datestamp'} = '20090102030405'; 143$hdr->{'dumplevel'} = 31; 144$hdr->{'type'} = $Amanda::Header::F_DUMPFILE; 145 146ok(!header_matches_dumpspecs($hdr, []), "header doesn't match empty list of dumpspecs"); 147 148ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new('foo.bar.baz', undef, undef, undef, undef)]), 149 'header matches exact host dumpspec'); 150ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new('foo', undef, undef, undef, undef)]), 151 'header matches partial host dumpspec'); 152ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new('?a*', undef, undef, undef, undef)]), 153 'header matches host pattern dumpspec'); 154 155ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, '/foo/bar/baz', undef, undef, undef)]), 156 'header matches exact disk dumpspec'); 157ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, 'bar', undef, undef, undef)]), 158 'header matches partial disk dumpspec'); 159ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, '*a?', undef, undef, undef)]), 160 'header matches disk pattern dumpspec'); 161 162ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, '20090102030405', undef, undef)]), 163 'header matches exact datestamp dumpspec'); 164ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, '2009', undef, undef)]), 165 'header matches partial datestamp dumpspec'); 166ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, '20090102030404-20090102030406', undef, undef)]), 167 'header matches datestamp range dumpspec'); 168ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, '2009-2010', undef, undef)]), 169 'header matches datestamp year-only range dumpspec'); 170ok(!header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, '20090102030406-20090102030407', undef, undef)]), 171 "header doesn't match datestamp range dumpspec that it's outside of"); 172 173ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, undef, '31', undef)]), 174 'header matches exact level dumpspec'); 175ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, undef, '30-32', undef)]), 176 'header matches small level range dumpspec'); 177ok(header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, undef, '4-50', undef)]), 178 'header matches large level range dumpspec'); 179ok(!header_matches_dumpspecs($hdr, [Amanda::Cmdline::dumpspec_t->new(undef, undef, undef, '32-50', undef)]), 180 "header doesn't match level range it's outside of"); 181 182ok(header_matches_dumpspecs($hdr, [ 183 Amanda::Cmdline::dumpspec_t->new('foo.bar.baz', undef, undef, undef, undef), 184 Amanda::Cmdline::dumpspec_t->new(undef, '/foo/bar/baz', undef, undef, undef), 185 ]), 186 'header matches when two dumpspecs are possible matches'); 187ok(!header_matches_dumpspecs($hdr, [ 188 Amanda::Cmdline::dumpspec_t->new(undef, undef, '20090102030406-20090102030407', undef, undef), 189 Amanda::Cmdline::dumpspec_t->new(undef, undef, undef, '32-50', undef), 190 ]), 191 'header matches when two dumpspecs are given and neither should match'); 192