1 # Copyright (c) 2006 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, 505 N Mathlida Ave, Suite 120
17 # Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19 use Test::More qw(no_plan);
24 use lib "@amperldir@";
28 use Amanda::Config qw( :init :getconf config_dir_relative );
31 # set up debugging so debug output doesn't interfere with test results
32 Amanda::Debug::dbopen("installcheck");
34 my $changer_filename = "$AMANDA_TMPDIR/chg-test";
37 my ($changer_script) = @_;
39 open my $chg_test, ">", $changer_filename or die("Could not create test changer");
41 $changer_script =~ s/\$AMANDA_TMPDIR/$AMANDA_TMPDIR/g;
43 print $chg_test "#! /bin/sh\n";
44 print $chg_test $changer_script;
47 chmod 0755, $changer_filename;
50 # set up and load a simple config with a tpchanger
51 my $testconf = Amconfig->new();
52 $testconf->add_param('tpchanger', "\"$changer_filename\"");
54 config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF') or die("Could not load test config");
56 # some variables we'll need
57 my ($error, $slot, $device);
59 # OK, let's get started with some simple stuff
60 setup_changer <<'EOC';
64 1) echo "1 fake:1"; exit 0;;
65 2) echo "<ignored> slot 2 is empty"; exit 1;;
66 3) echo "<error> oh noes!"; exit 2;;
67 4) echo "1"; exit 0;; # test missing 'device' portion
69 -reset) echo "reset ignored";;
70 -eject) echo "eject ignored";;
71 -clean) echo "clean ignored";;
74 foo?bar) echo "1 ok"; exit 0;;
75 *) echo "<error> bad label"; exit 1;;
77 -info) echo "7 10 1 1"; exit 0;;
80 TAPE?01) echo "5 fakedev"; exit 0;;
81 *) echo "<error> not found"; exit 2;;
86 is_deeply([ Amanda::Changer::loadslot(1) ], [0, "1", "fake:1"],
87 "A successful loadslot() returns the right stuff");
89 ($error, $slot, $device) = Amanda::Changer::loadslot(2);
90 is($error, "slot 2 is empty", "A loadslot() with a benign error returns the right stuff");
92 eval { Amanda::Changer::loadslot(3); };
93 like($@, qr/.*oh noes!.*/, "A loadslot() with a serious error croaks");
95 is_deeply([ Amanda::Changer::loadslot(4) ], [0, "1", undef],
96 "a response without a device string returns undef");
98 is_deeply([ Amanda::Changer::reset() ], [ 0, "reset" ],
99 "reset() calls tapechanger -reset");
100 is_deeply([ Amanda::Changer::eject() ], [ 0, "eject" ],
101 "eject() calls tapechanger -eject");
102 is_deeply([ Amanda::Changer::clean() ], [ 0, "clean" ],
103 "clean() calls tapechanger -clean");
105 is_deeply([ Amanda::Changer::label("foo bar") ], [ 0 ],
106 "label('foo bar') calls tapechanger -label 'foo bar' (note spaces)");
108 is_deeply([ Amanda::Changer::query() ], [ 0, 7, 10, 1, 1 ],
109 "query() returns the correct values for a 4-value changer script");
111 is_deeply([ Amanda::Changer::find("TAPE 01") ], [ 0, "5", "fakedev" ],
112 "find on a searchable changer invokes -search");
114 eval { Amanda::Changer::find("TAPE 02") };
115 ok($@, "A searchable changer croaks when the label can't be found");
117 # Now a simple changer that returns three values for -info
118 setup_changer <<'EOC';
120 -info) echo "11 13 0"; exit 0;;
124 is_deeply([ Amanda::Changer::query() ], [ 0, 11, 13, 0, 0 ],
125 "query() returns the correct values for a 4-value changer script");
128 for (my $i = 0; $i < 5; $i++) {
129 my $vtapedir = "$AMANDA_TMPDIR/chg-test-tapes/$i/data";
132 or die("Could not remove '$vtapedir'");
135 or die("Could not create '$vtapedir'");
138 # label three of them (slot 2 is empty; slot 4 is unlabeled)
139 for (my $i = 0; $i < 5; $i++) {
140 next if $i == 2 || $i == 4;
141 my $dev = Amanda::Device->new("file:$AMANDA_TMPDIR/chg-test-tapes/$i")
142 or die("Could not open device");
143 $dev->start($Amanda::Device::ACCESS_WRITE, "TAPE$i", "19780615010203")
144 or die("Could not write label");
148 # And finally a "stateful" changer that can support "scan" and "find"
149 setup_changer <<'EOC';
150 STATEFILE="$AMANDA_TMPDIR/chg-test-state"
152 [ -f "$STATEFILE" ] && . "$STATEFILE"
158 0|1|2|3|4|5) SLOT="${2}";;
159 next|advance) SLOT=`expr $SLOT + 1`;;
160 prev) SLOT=`expr $SLOT - 1`;;
165 # normalize 0 <= $SLOT < 5
166 while [ "$SLOT" -ge 5 ]; do SLOT=`expr $SLOT - 5`; done
167 while [ "$SLOT" -lt 0 ]; do SLOT=`expr $SLOT + 5`; done
169 # signal an empty slot for slot 2
170 if [ "$SLOT" = 2 ]; then
171 echo "$SLOT slot $SLOT is empty"
174 echo "$SLOT" "file:$AMANDA_TMPDIR/chg-test-tapes/$SLOT"
177 -info) echo "$SLOT 5 1 0";;
180 echo SLOT=$SLOT > $STATEFILE
184 ($error, $slot, $device) = Amanda::Changer::loadslot(0);
185 if ($error) { die("Error loading slot 0: $error"); }
186 is_deeply([ Amanda::Changer::find("TAPE3") ], [0, "3", "file:$AMANDA_TMPDIR/chg-test-tapes/3"],
187 "Finds a tape after skipping an empty slot");
189 ($error, $slot, $device) = Amanda::Changer::loadslot(3);
190 if ($error) { die("Error loading slot 3: $error"); }
191 is_deeply([ Amanda::Changer::find("TAPE1") ], [0, "1", "file:$AMANDA_TMPDIR/chg-test-tapes/1"],
192 "Finds a tape after skipping an unlabeled but filled slot");
196 fail("called too many times") if (!@scanresults);
197 my $expected = shift @scanresults;
198 my $descr = pop @$expected;
199 my $done = pop @$expected;
200 is_deeply([ @_ ], $expected, $descr);
204 # scan the whole changer
205 ($error, $slot, $device) = Amanda::Changer::loadslot(0);
206 if ($error) { die("Error loading slot 0: $error"); }
208 [ "0", "file:$AMANDA_TMPDIR/chg-test-tapes/0", 0, 0, "scan starts with slot 0" ],
209 [ "1", "file:$AMANDA_TMPDIR/chg-test-tapes/1", 0, 0, "next in slot 1" ],
210 [ undef, undef, "slot 2 is empty", 0, "slot 2 is empty" ],
211 [ "3", "file:$AMANDA_TMPDIR/chg-test-tapes/3", 0, 0, "next in slot 3" ],
212 [ "4", "file:$AMANDA_TMPDIR/chg-test-tapes/4", 0, 0, "next in slot 4" ],
214 Amanda::Changer::scan(\&cb);
216 # make sure it stops when "done"
217 ($error, $slot, $device) = Amanda::Changer::loadslot(0);
218 if ($error) { die("Error loading slot 0: $error"); }
220 [ "0", "file:$AMANDA_TMPDIR/chg-test-tapes/0", 0, 1, "scan starts with slot 0" ],
222 Amanda::Changer::scan(\&cb);
225 unlink("$AMANDA_TMPDIR/chg-test");
226 unlink("$AMANDA_TMPDIR/chg-test-state");
227 rmtree("$AMANDA_TMPDIR/chg-test-tapes");