1 # Copyright (c) 2005-2008 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 Mathlida Ave, Suite 300
17 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19 use Test::More tests => 17;
24 use lib "@amperldir@";
25 use Installcheck::Config;
26 use Installcheck::Run;
31 use Amanda::Config qw( :init :getconf config_dir_relative );
34 # set up debugging so debug output doesn't interfere with test results
35 Amanda::Debug::dbopen("installcheck");
37 # and disable Debug's die() and warn() overrides
38 Amanda::Debug::disable_die_override();
40 my $changer_filename = "$AMANDA_TMPDIR/chg-test";
42 # Set up a 'test' changer; several of these are defined below.
44 my ($changer_script) = @_;
46 open my $chg_test, ">", $changer_filename or die("Could not create test changer");
48 $changer_script =~ s/\$AMANDA_TMPDIR/$AMANDA_TMPDIR/g;
50 print $chg_test "#! /bin/sh\n";
51 print $chg_test $changer_script;
54 chmod 0755, $changer_filename;
57 # Functions to invoke the changer and later verify the result
65 Amanda::MainLoop::quit();
68 if (defined($expected_err_re)) {
69 like($err, $expected_err_re, $msg);
72 debug("Unexpected error: $err");
75 if (defined($expected_dev)) {
76 is($res->{'device_name'}, $expected_dev, $msg);
79 diag("Unexpected reservation");
84 sub check_finished_cb {
86 Amanda::MainLoop::quit();
89 if (defined($expected_err_re)) {
90 like($err, $expected_err_re, $msg);
93 diag("Unexpected error: $err");
96 if (!defined($expected_err_re)) {
100 diag("Unexpected success");
105 sub try_run_changer {
107 ($sub, $expected_err_re, $expected_dev, $msg) = @_;
109 Amanda::MainLoop::call_later($sub);
110 Amanda::MainLoop::run();
114 # OK, let's get started with some simple stuff
115 setup_changer <<'EOC';
119 1) echo "1 fake:1"; exit 0;;
120 2) echo "<ignored> slot 2 is empty"; exit 1;;
121 3) echo "1"; exit 0;; # test missing 'device' portion
123 -reset) echo "reset ignored";;
124 -eject) echo "eject ignored";;
125 -clean) echo "clean ignored";;
128 foo?bar) echo "1 ok"; exit 0;;
129 *) echo "<error> bad label"; exit 1;;
131 -info) echo "7 10 1 1"; exit 0;;
134 TAPE?01) echo "5 fakedev"; exit 0;;
135 *) echo "<error> not found"; exit 1;;
140 # set up a config for this changer, implicitly using Amanda::Changer::Compat
142 $testconf = Installcheck::Config->new();
143 $testconf->add_param("tpchanger", "\"$changer_filename\"");
146 my $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
147 if ($cfg_result != $CFGERR_OK) {
148 my ($level, @errors) = Amanda::Config::config_errors();
149 die(join "\n", @errors);
152 my $chg = Amanda::Changer->new();
154 sub { $chg->load(label => 'TAPE-01', res_cb => \&check_res_cb); },
155 undef, "fakedev", "search by label");
158 sub { $chg->load(label => 'TAPE-99', res_cb => \&check_res_cb); },
159 qr/^not found$/, undef, "search by label; nonexistent tape");
162 sub { $chg->load(slot => '1', res_cb => \&check_res_cb); },
163 undef, "fake:1", "search by slot");
166 sub { $chg->load(slot => '2', res_cb => \&check_res_cb); },
167 qr/^slot 2 is empty$/, undef, "search by slot; empty slot");
169 # TODO: what *should* happen here?
171 # sub { $chg->load(slot => '3', res_cb => \&check_res_cb); },
172 # undef, undef, "search by slot; invalid response");
175 sub { $chg->reset(finished_cb => \&check_finished_cb); },
176 undef, undef, "reset doesn't fail");
179 sub { $chg->clean(finished_cb => \&check_finished_cb); },
180 undef, undef, "clean doesn't fail");
184 # make sure only one reservation can be held at once
188 my ($load_1, $load_2, $check_load_2, $check_eject);
191 $chg->load(slot => 1, res_cb => $load_2);
195 my ($err, $res) = @_;
198 # keep this in scope through the next load
201 $chg->load(slot => 2, res_cb => $check_load_2);
204 $check_load_2 = sub {
205 my ($err, $res) = @_;
207 like($err, qr/Changer is already reserved/,
208 "mulitple simultaneous reservations not alowed");
210 $first_res->release(eject => 1, finished_cb => $check_eject);
216 ok(!defined $err, "release with eject succeeds");
218 Amanda::MainLoop::quit();
221 Amanda::MainLoop::call_later($load_1);
222 Amanda::MainLoop::run();
227 # Installcheck::Run sets up the whole chg-disk thing for us
228 $testconf = Installcheck::Run->setup();
231 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
232 if ($cfg_result != $CFGERR_OK) {
233 my ($level, @errors) = Amanda::Config::config_errors();
234 die(join "\n", @errors);
237 $chg = Amanda::Changer->new();
240 my ($get_info, $load_current, $label_current, $load_next,
241 $release_next, $load_by_label, $check_by_label);
244 $chg->info(info_cb => $load_current, info => [ 'num_slots' ]);
247 $load_current = sub {
250 die($err) if defined($err);
252 is($results{'num_slots'}, 15, "info() returns the correct num_slots");
254 $chg->load(slot => "1", res_cb => $label_current);
257 $label_current = sub {
258 my ($err, $res) = @_;
261 pass("seek to current slot succeeded");
263 my $dev = Amanda::Device->new($res->{'device_name'});
264 $dev->start($Amanda::Device::ACCESS_WRITE, "TESTCONF18", undef)
265 or die $dev->error_or_status();
267 or die $dev->error_or_status();
269 is($res->{'this_slot'}, "1", "this slot is '1'");
270 is($res->{'next_slot'}, "next", "next slot is 'next'");
271 $res->set_label(label => "TESTCONF18", finished_cb => $load_next);
278 pass("set_label succeeded");
280 $chg->load(slot => "next", res_cb => $release_next);
283 $release_next = sub {
284 my ($err, $res) = @_;
287 pass("load 'next' succeeded");
289 $res->release(finished_cb => $load_by_label);
292 $load_by_label = sub {
296 pass("release loaded");
298 $chg->load(label => "TESTCONF18", res_cb => $check_by_label);
301 $check_by_label = sub {
302 my ($err, $res) = @_;
305 pass("load by label succeeded");
307 my $dev = Amanda::Device->new($res->{'device_name'});
308 $dev->read_label() == 0
309 or die $dev->error_or_status();
311 is($dev->volume_label(), "TESTCONF18",
312 "..and finds the right volume");
314 Amanda::MainLoop::quit();
317 Amanda::MainLoop::call_later($get_info);
318 Amanda::MainLoop::run();