1 # Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
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.
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
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
17 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
20 use Test::More tests => 541;
21 use File::Path qw( mkpath rmtree );
27 use lib "@amperldir@";
29 use Installcheck::Mock;
30 use Installcheck::Config;
32 use Amanda::Device qw( :constants );
33 use Amanda::Config qw( :getconf :init );
34 use Amanda::Xfer qw( :constants );
35 use Amanda::Header qw( :constants );
37 use Amanda::Constants;
44 my ($vtape1, $vtape2);
45 my ($input_filename, $output_filename) =
46 ( "$Installcheck::TMP/input.tmp", "$Installcheck::TMP/output.tmp" );
47 my $taperoot = "$Installcheck::TMP/Amanda_Device_test_tapes";
50 # we'll need some vtapes..
54 my $mytape = "$taperoot/$num";
55 if (-d $mytape) { rmtree($mytape); }
56 mkpath("$mytape/data");
61 # make up a fake dumpfile_t to write with
62 my $dumpfile = Amanda::Header->new();
63 $dumpfile->{type} = $Amanda::Header::F_DUMPFILE;
64 $dumpfile->{datestamp} = "20070102030405";
65 $dumpfile->{dumplevel} = 0;
66 $dumpfile->{compressed} = 1;
67 $dumpfile->{name} = "localhost";
68 $dumpfile->{disk} = "/home";
69 $dumpfile->{program} = "INSTALLCHECK";
71 my $write_file_count = 5;
73 my ($seed, $length, $filenum) = @_;
75 $dumpfile->{'datestamp'} = "2000010101010$filenum";
77 ok($dev->start_file($dumpfile),
78 "start file $filenum")
79 or diag($dev->error_or_status());
81 is($dev->file(), $filenum,
82 "Device has correct filenum");
84 croak ("selected file size $length is *way* too big")
85 unless ($length < 1024*1024*10);
86 ok(Amanda::Device::write_random_to_device($seed, $length, $dev),
89 if(ok($dev->in_file(),
91 ok($dev->finish_file(),
93 or diag($dev->error_or_status());
95 pass("not in file, so not calling finish_file");
99 my $verify_file_count = 4;
101 my ($seed, $length, $filenum) = @_;
103 ok(my $read_dumpfile = $dev->seek_file($filenum),
104 "seek to file $filenum")
105 or diag($dev->error_or_status());
106 is($dev->file(), $filenum,
107 "device is really at file $filenum");
108 ok(header_for($read_dumpfile, $filenum),
110 or diag($dev->error_or_status());
111 ok(Amanda::Device::verify_random_from_device($seed, $length, $dev),
112 "verified file contents");
116 my ($hdr, $filenum) = @_;
117 return ($hdr and $hdr->{'datestamp'} eq "2000010101010$filenum");
122 my @common_properties = (
128 'medium_access_type',
135 sub properties_include {
136 my ($got, $should_include, $msg) = @_;
137 my %got = map { $_->{'name'}, 1 } @$got;
138 my @missing = grep { !defined($got{$_}) } @$should_include;
141 diag(" Expected properties: " . join(", ", @$should_include));
142 diag(" Got properties: " . join(", ", @$got));
143 diag(" Missing properties: " . join(", ", @missing));
152 $testconf = Installcheck::Config->new();
154 config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF') == $CFGERR_OK
155 or die("Could not load configuration");
157 # put the debug messages somewhere
158 Amanda::Debug::dbopen("installcheck");
159 Installcheck::log_test_output();
162 ## Test errors a little bit
164 $dev = Amanda::Device->new("foobar:");
165 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
166 "creation of a bogus 'foobar:' device fails");
168 $dev = Amanda::Device->new("rait:{{");
169 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
170 "creation of a bogus 'rait:{{' device fails");
172 $dev = Amanda::Device->new("rait:{a,b");
173 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
174 "creation of a bogus 'rait:{a,b' device fails");
177 ## first, test out the 'null' device.
181 $dev = Amanda::Device->new($dev_name);
182 is($dev->status(), $DEVICE_STATUS_SUCCESS,
183 "create null device")
184 or diag $dev->error_or_status();
185 ok($dev->start($ACCESS_WRITE, "NULL1", "19780615010203"),
186 "start null device in write mode")
187 or diag $dev->error_or_status();
190 properties_include([ $dev->property_list() ], [ @common_properties ],
191 "necessary properties listed on null device");
192 is($dev->property_get("canonical_name"), "null:",
193 "property_get(canonical_name) on null device");
194 is($dev->property_get("caNONical-name"), "null:",
195 "property_get(caNONical-name) on null device (case, dash-insensitivity)");
196 is_deeply([ $dev->property_get("canonical_name") ],
197 [ "null:", $PROPERTY_SURETY_GOOD, $PROPERTY_SOURCE_DEFAULT ],
198 "extended property_get returns correct surety/source");
199 for my $prop ($dev->property_list()) {
200 next unless $prop->{'name'} eq 'canonical_name';
201 is($prop->{'description'},
202 "The most reliable device name to use to refer to this device.",
203 "property info for canonical name is correct");
205 ok(!$dev->property_get("full_deletion"),
206 "property_get(full_deletion) on null device");
207 is($dev->property_get("comment"), undef,
208 "no comment by default");
209 ok($dev->property_set("comment", "well, that was silly"),
210 "set comment property");
211 is($dev->property_get("comment"), "well, that was silly",
212 "comment correctly stored");
214 # and write a file to it
215 write_file(0xabcde, 1024*256, 1);
217 # (don't finish the device, testing the finalize method's cleanup)
220 ## Now some full device tests
224 $vtape1 = mkvtape(1);
225 $dev_name = "file:$vtape1";
227 $dev = Amanda::Device->new($dev_name);
228 is($dev->status(), $DEVICE_STATUS_SUCCESS,
229 "$dev_name: create successful")
230 or diag($dev->error_or_status());
232 properties_include([ $dev->property_list() ],
233 [ @common_properties, 'max_volume_usage' ],
234 "necessary properties listed on vfs device");
236 # play with properties a little bit
237 ok($dev->property_set("comment", 16),
238 "set an string property to an integer");
240 ok($dev->property_set("comment", 16.0),
241 "set an string property to a float");
243 ok($dev->property_set("comment", "hi mom"),
244 "set an string property to a string");
246 ok($dev->property_set("comment", "32768"),
247 "set an integer property to a simple string");
249 ok($dev->property_set("comment", "32k"),
250 "set an integer property to a string with a unit");
252 ok($dev->property_set("block_size", 32768),
253 "set an integer property to an integer");
255 ok(!($dev->property_set("invalid-property-name", 32768)),
256 "set an invalid-property-name");
259 ok($dev->status() & $DEVICE_STATUS_VOLUME_UNLABELED,
260 "initially unlabeled")
261 or diag($dev->error_or_status());
263 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
264 "start in write mode")
265 or diag($dev->error_or_status());
267 ok(!($dev->status() & $DEVICE_STATUS_VOLUME_UNLABELED),
268 "not unlabeled anymore")
269 or diag($dev->error_or_status());
271 for (my $i = 1; $i <= 3; $i++) {
272 write_file(0x2FACE, $dev->block_size()*10+17, $i);
276 "finish device after write")
277 or diag($dev->error_or_status());
280 ok(!($dev->status()),
281 "no error, at all, from read_label")
282 or diag($dev->error_or_status());
284 # append one more copy, to test ACCESS_APPEND
286 ok($dev->start($ACCESS_APPEND, undef, undef),
287 "start in append mode")
288 or diag($dev->error_or_status());
290 write_file(0xD0ED0E, $dev->block_size()*4, 4);
293 "finish device after append")
294 or diag($dev->error_or_status());
296 # try reading the third file back, creating a new device
297 # object first, and skipping the read-label step.
300 $dev = Amanda::Device->new($dev_name);
301 is($dev->status(), $DEVICE_STATUS_SUCCESS,
302 "$dev_name: re-create successful")
303 or diag($dev->error_or_status());
305 ok($dev->start($ACCESS_READ, undef, undef),
306 "start in read mode")
307 or diag($dev->error_or_status());
309 verify_file(0x2FACE, $dev->block_size()*10+17, 3);
312 # try two seek_file's in a row
313 my $hdr = $dev->seek_file(3);
314 is($hdr? $hdr->{'type'} : -1, $Amanda::Header::F_DUMPFILE, "seek_file the first time");
315 $hdr = $dev->seek_file(3);
316 is($hdr? $hdr->{'type'} : -1, $Amanda::Header::F_DUMPFILE, "seek_file the second time");
320 "finish device after read")
321 or diag($dev->error_or_status());
326 or diag($dev->error_or_status());
329 "erase device (again)")
330 or diag($dev->error_or_status());
333 "finish device after erase")
334 or diag($dev->error_or_status());
336 # test monitor_free_space property (testing the monitoring would require a
337 # dedicated partition for the tests - it's not worth it)
339 ok($dev->property_get("monitor_free_space"),
340 "monitor_free_space property is set by default");
342 ok($dev->property_set("monitor_free_space", 0),
343 "monitor_free_space property can be set to false");
345 ok(!$dev->property_get("monitor_free_space"),
346 "monitor_free_space property value 'sticks'");
348 # test the LEOM functionality
351 $dev = Amanda::Device->new($dev_name);
352 is($dev->status(), $DEVICE_STATUS_SUCCESS,
353 "$dev_name: re-create successful")
354 or diag($dev->error_or_status());
355 ok($dev->property_set("MAX_VOLUME_USAGE", "512k"),
356 "set MAX_VOLUME_USAGE to test LEOM");
357 ok($dev->property_set("LEOM", 1),
359 ok($dev->property_set("ENFORCE_MAX_VOLUME_USAGE", 0),
360 "set ENFORCE_MAX_VOLUME_USAGE");
362 ok($dev->start($ACCESS_WRITE, 'TESTCONF23', undef),
363 "start in write mode")
364 or diag($dev->error_or_status());
366 ok($dev->start_file($dumpfile),
368 or diag($dev->error_or_status());
370 ok(Amanda::Device::write_random_to_device(0xCAFE, 440*1024, $dev),
371 "write random data into the early-warning zone");
374 "device does not indicates LEOM after writing when ENFORCE_MAX_VOLUME_USAGE is FALSE");
376 ok($dev->finish_file(),
377 "..but a finish_file is allowed to complete")
378 or diag($dev->error_or_status());
381 "finish device after LEOM test")
382 or diag($dev->error_or_status());
385 $dev = Amanda::Device->new($dev_name);
386 is($dev->status(), $DEVICE_STATUS_SUCCESS,
387 "$dev_name: re-create successful")
388 or diag($dev->error_or_status());
389 ok($dev->property_set("MAX_VOLUME_USAGE", "512k"),
390 "set MAX_VOLUME_USAGE to test LEOM");
391 ok($dev->property_set("LEOM", 1),
393 ok($dev->property_set("ENFORCE_MAX_VOLUME_USAGE", 1),
394 "set ENFORCE_MAX_VOLUME_USAGE");
396 ok($dev->start($ACCESS_WRITE, 'TESTCONF23', undef),
397 "start in write mode")
398 or diag($dev->error_or_status());
400 ok($dev->start_file($dumpfile),
402 or diag($dev->error_or_status());
405 "device does not indicate LEOM before writing");
407 ok(Amanda::Device::write_random_to_device(0xCAFE, 440*1024, $dev),
408 "write random data into the early-warning zone");
411 "device indicates LEOM after writing");
413 ok($dev->finish_file(),
414 "..but a finish_file is allowed to complete")
415 or diag($dev->error_or_status());
418 "finish device after LEOM test")
419 or diag($dev->error_or_status());
422 $dev = Amanda::Device->new($dev_name);
423 is($dev->status(), $DEVICE_STATUS_SUCCESS,
424 "$dev_name: re-create successful")
425 or diag($dev->error_or_status());
426 ok($dev->property_set("MAX_VOLUME_USAGE", "512k"),
427 "set MAX_VOLUME_USAGE to test LEOM");
428 ok($dev->property_set("LEOM", 1),
431 ok($dev->start($ACCESS_WRITE, 'TESTCONF23', undef),
432 "start in write mode")
433 or diag($dev->error_or_status());
435 ok($dev->start_file($dumpfile),
437 or diag($dev->error_or_status());
440 "device does not indicate LEOM before writing");
442 ok(Amanda::Device::write_random_to_device(0xCAFE, 440*1024, $dev),
443 "write random data into the early-warning zone");
446 "device indicates LEOM after writing as default value of ENFORCE_MAX_VOLUME_USAGE is true for vfs device");
448 ok($dev->finish_file(),
449 "..but a finish_file is allowed to complete")
450 or diag($dev->error_or_status());
453 "finish device after LEOM test")
454 or diag($dev->error_or_status());
457 $dev = Amanda::Device->new($dev_name);
458 is($dev->status(), $DEVICE_STATUS_SUCCESS,
459 "$dev_name: re-create successful")
460 or diag($dev->error_or_status());
461 ok($dev->property_set("MAX_VOLUME_USAGE", "160k"),
462 "set MAX_VOLUME_USAGE to test LEOM while writing the first header");
463 ok($dev->property_set("LEOM", 1),
466 ok($dev->start($ACCESS_WRITE, 'TESTCONF23', undef),
467 "start in write mode")
468 or diag($dev->error_or_status());
470 ok($dev->start_file($dumpfile),
472 or diag($dev->error_or_status());
475 "device indicates LEOM after writing first header");
477 ok($dev->finish_file(),
478 "..but a finish_file is allowed to complete")
479 or diag($dev->error_or_status());
482 "finish device after LEOM test")
483 or diag($dev->error_or_status());
486 ## Test a RAIT device of two vfs devices.
488 ($vtape1, $vtape2) = (mkvtape(1), mkvtape(2));
489 $dev_name = "rait:file:{$vtape1,$vtape2}";
491 $dev = Amanda::Device->new($dev_name);
492 is($dev->status(), $DEVICE_STATUS_SUCCESS,
493 "$dev_name: create successful")
494 or diag($dev->error_or_status());
496 ok($dev->configure(1), "configure device");
498 properties_include([ $dev->property_list() ], [ @common_properties ],
499 "necessary properties listed on rait device");
501 is($dev->property_get("block_size"), 32768, # (RAIT default)
502 "rait device calculates a default block size correctly");
504 ok($dev->property_set("block_size", 32768*16),
505 "rait device accepts an explicit block size");
507 is($dev->property_get("block_size"), 32768*16,
508 "..and remembers it");
510 ok($dev->property_set("max_volume_usage", 32768*1000),
511 "rait device accepts property MAX_VOLUME_USAGE");
513 is($dev->property_get("max_volume_usage"), 32768*1000,
514 "..and remembers it");
517 ok($dev->status() & $DEVICE_STATUS_VOLUME_UNLABELED,
518 "initially unlabeled")
519 or diag($dev->error_or_status());
521 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
522 "start in write mode")
523 or diag($dev->error_or_status());
525 ok(!($dev->status() & $DEVICE_STATUS_VOLUME_UNLABELED),
526 "not unlabeled anymore")
527 or diag($dev->error_or_status());
529 for (my $i = 1; $i <= 3; $i++) {
530 write_file(0x2FACE, $dev->block_size()*10+17, $i);
534 "finish device after write")
535 or diag($dev->error_or_status());
538 ok(!($dev->status()),
539 "no error, at all, from read_label")
540 or diag($dev->error_or_status());
542 # append one more copy, to test ACCESS_APPEND
544 ok($dev->start($ACCESS_APPEND, undef, undef),
545 "start in append mode")
546 or diag($dev->error_or_status());
548 write_file(0xD0ED0E, $dev->block_size()*4, 4);
551 "finish device after append")
552 or diag($dev->error_or_status());
554 # try reading the third file back, creating a new device
555 # object first, and skipping the read-label step.
558 $dev = Amanda::Device->new($dev_name);
559 is($dev->status(), $DEVICE_STATUS_SUCCESS,
560 "$dev_name: re-create successful")
561 or diag($dev->error_or_status());
563 ok($dev->start($ACCESS_READ, undef, undef),
564 "start in read mode")
565 or diag($dev->error_or_status());
567 verify_file(0x2FACE, $dev->block_size()*10+17, 3);
570 "finish device after read")
571 or diag($dev->error_or_status());
573 ok($dev->start($ACCESS_READ, undef, undef),
574 "start in read mode after missing volume")
575 or diag($dev->error_or_status());
577 # corrupt the device somehow and hope it keeps working
578 rmtree("$taperoot/1");
580 verify_file(0x2FACE, $dev->block_size()*10+17, 3);
581 verify_file(0xD0ED0E, $dev->block_size()*4, 4);
582 verify_file(0x2FACE, $dev->block_size()*10+17, 2);
585 "finish device read after missing volume")
586 or diag($dev->error_or_status());
588 ok(!($dev->start($ACCESS_WRITE, "TESTCONF29", undef)),
589 "start in write mode fails with missing volume")
590 or diag($dev->error_or_status());
594 $dev_name = "rait:{file:$vtape2,MISSING}";
595 $dev = Amanda::Device->new($dev_name);
597 ok($dev->start($ACCESS_READ, undef, undef),
598 "start in read mode with MISSING")
599 or diag($dev->error_or_status());
601 verify_file(0x2FACE, $dev->block_size()*10+17, 3);
602 verify_file(0xD0ED0E, $dev->block_size()*4, 4);
603 verify_file(0x2FACE, $dev->block_size()*10+17, 2);
606 "finish device read with MISSING")
607 or diag($dev->error_or_status());
609 ok(!($dev->start($ACCESS_WRITE, "TESTCONF29", undef)),
610 "start in write mode fails with MISSING")
611 or diag($dev->error_or_status());
615 $dev = Amanda::Device->new_rait_from_children(
616 Amanda::Device->new("file:$vtape2"), undef);
618 ok(!($dev->start($ACCESS_WRITE, "TESTCONF29", undef)),
619 "start a RAIT device in write mode fails, when created with 'undef'")
620 or diag($dev->error_or_status());
622 # Make two devices with different labels, should get a
623 # message accordingly.
624 ($vtape1, $vtape2) = (mkvtape(1), mkvtape(2));
627 for $dev_name ("file:$vtape1", "file:$vtape2") {
628 my $dev = Amanda::Device->new($dev_name);
629 is($dev->status(), $DEVICE_STATUS_SUCCESS,
630 "$dev_name: Open successful")
631 or diag($dev->error_or_status());
632 ok($dev->start($ACCESS_WRITE, "TESTCONF$n", undef),
633 "wrote label 'TESTCONF$n'");
634 ok($dev->finish(), "finished device");
638 $dev = Amanda::Device->new_rait_from_children(
639 Amanda::Device->new("file:$vtape1"),
640 Amanda::Device->new("file:$vtape2"));
641 is($dev->status(), $DEVICE_STATUS_SUCCESS,
642 "new_rait_from_children: Open successful")
643 or diag($dev->error_or_status());
646 ok($dev->status() & $DEVICE_STATUS_VOLUME_ERROR,
647 "Label mismatch error handled correctly")
648 or diag($dev->error_or_status());
650 # Use some config to set a block size on a child device
651 ($vtape1, $vtape2) = (mkvtape(1), mkvtape(2));
652 $dev_name = "rait:{file:$vtape1,mytape2}";
654 $testconf = Installcheck::Config->new();
655 $testconf->add_device("mytape2", [
656 "tapedev" => "\"file:$vtape2\"",
657 "device_property" => "\"BLOCK_SIZE\" \"64k\""
660 config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF') == $CFGERR_OK
661 or die("Could not load configuration");
663 $dev = Amanda::Device->new($dev_name);
664 is($dev->status(), $DEVICE_STATUS_SUCCESS,
665 "$dev_name: create successful")
666 or diag($dev->error_or_status());
668 ok($dev->configure(1), "configure device");
670 is($dev->property_get("block_size"), 65536,
671 "rait device calculates a block size from its children correctly");
673 # Test an S3 device if the proper environment variables are set
674 my $S3_SECRET_KEY = $ENV{'INSTALLCHECK_S3_SECRET_KEY'};
675 my $S3_ACCESS_KEY = $ENV{'INSTALLCHECK_S3_ACCESS_KEY'};
676 my $DEVPAY_SECRET_KEY = $ENV{'INSTALLCHECK_DEVPAY_SECRET_KEY'};
677 my $DEVPAY_ACCESS_KEY = $ENV{'INSTALLCHECK_DEVPAY_ACCESS_KEY'};
678 my $DEVPAY_USER_TOKEN = $ENV{'INSTALLCHECK_DEVPAY_USER_TOKEN'};
680 my $run_s3_tests = defined $S3_SECRET_KEY && defined $S3_ACCESS_KEY;
681 my $run_devpay_tests = defined $DEVPAY_SECRET_KEY &&
682 defined $DEVPAY_ACCESS_KEY && $DEVPAY_USER_TOKEN;
684 my $s3_make_device_count = 7;
685 sub s3_make_device($$) {
686 my ($dev_name, $kind) = @_;
687 $dev = Amanda::Device->new($dev_name);
688 is($dev->status(), $DEVICE_STATUS_SUCCESS,
689 "$dev_name: create successful")
690 or diag($dev->error_or_status());
692 my @s3_props = ( 's3_access_key', 's3_secret_key' );
693 push @s3_props, 's3_user_token' if ($kind eq "devpay");
694 properties_include([ $dev->property_list() ], [ @common_properties, @s3_props ],
695 "necessary properties listed on s3 device");
697 ok($dev->property_set('BLOCK_SIZE', 32768*2),
699 or diag($dev->error_or_status());
701 # might as well save a few cents while testing this property..
702 ok($dev->property_set('S3_STORAGE_CLASS', 'REDUCED_REDUNDANCY'),
704 or diag($dev->error_or_status());
707 # use regular S3 credentials
708 ok($dev->property_set('S3_ACCESS_KEY', $S3_ACCESS_KEY),
710 or diag($dev->error_or_status());
712 ok($dev->property_set('S3_SECRET_KEY', $S3_SECRET_KEY),
714 or diag($dev->error_or_status());
716 pass("(placeholder)");
717 } elsif ($kind eq "devpay") {
718 # use devpay credentials
719 ok($dev->property_set('S3_ACCESS_KEY', $DEVPAY_ACCESS_KEY),
720 "set devpay access key")
721 or diag($dev->error_or_status());
723 ok($dev->property_set('S3_SECRET_KEY', $DEVPAY_SECRET_KEY),
724 "set devpay secret key")
725 or diag($dev->error_or_status());
727 ok($dev->property_set('S3_USER_TOKEN', $DEVPAY_USER_TOKEN),
728 "set devpay user token")
729 or diag($dev->error_or_status());
731 croak("didn't recognize the device kind, so no credentials were set");
739 skip "define \$INSTALLCHECK_S3_{SECRET,ACCESS}_KEY to run S3 tests",
741 1 * $verify_file_count +
742 7 * $write_file_count +
743 13 * $s3_make_device_count
744 unless $run_s3_tests;
747 $dev = Amanda::Device->new($dev_name);
748 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
749 "creating $dev_name fails miserably");
751 $dev_name = "s3:foo";
752 $dev = Amanda::Device->new($dev_name);
754 ok($dev->property_get("full_deletion"),
755 "property_get(full_deletion) on s3 device");
757 ok($dev->property_get("leom"),
758 "property_get(leom) on s3 device");
760 # test parsing of boolean values
761 # (s3 is the only device driver that has a writable boolean property at the
765 {'val' => '1', 'true' => 1},
766 {'val' => '0', 'true' => 0},
767 {'val' => 't', 'true' => 1},
768 {'val' => 'true', 'true' => 1},
769 {'val' => 'f', 'true' => 0},
770 {'val' => 'false', 'true' => 0},
771 {'val' => 'y', 'true' => 1},
772 {'val' => 'yes', 'true' => 1},
773 {'val' => 'n', 'true' => 0},
774 {'val' => 'no', 'true' => 0},
775 {'val' => 'on', 'true' => 1},
776 {'val' => 'off', 'true' => 0},
777 {'val' => 'oFf', 'true' => 0},
780 foreach my $v (@verbose_vals) {
781 $dev_name = "s3:foo";
782 $dev = Amanda::Device->new($dev_name);
784 $testconf = Installcheck::Config->new();
785 $testconf->add_param("device_property", "\"verbose\" \"$v->{'val'}\"");
787 config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF') == $CFGERR_OK
788 or die("Could not load configuration");
790 ok($dev->configure(1),
791 "configured device with verbose set to $v->{'val'}")
792 or diag($dev->error_or_status());
794 my $get_val = $dev->property_get('verbose');
795 # see if truth-iness matches
796 my $expec = $v->{'true'}? "true" : "false";
797 is(!!$dev->property_get('verbose'), !!$v->{'true'},
798 "device_property 'VERBOSE' '$v->{'val'}' => property_get(verbose) returning $expec");
801 # test unparsable property
802 $dev_name = "s3:foo";
803 $dev = Amanda::Device->new($dev_name);
805 $testconf = Installcheck::Config->new();
806 $testconf->add_param("device_property", "\"verbose\" \"foo\"");
808 config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF') == $CFGERR_OK
809 or die("Could not load configuration");
811 ok(!$dev->configure(1),
812 "failed to configure device with verbose set to foo");
814 like($dev->error_or_status(), qr/'verbose'/,
815 "error message mentions property name");
817 like($dev->error_or_status(), qr/'foo'/,
818 "error message mentions property value");
820 like($dev->error_or_status(), qr/gboolean/,
821 "error message mentions property type");
823 my $hostname = hostname();
824 $hostname =~ s/\./-/g;
825 $base_name = "$S3_ACCESS_KEY-installcheck-$hostname";
826 $dev_name = "s3:$base_name-s3";
827 $dev = s3_make_device($dev_name, "s3");
829 my $status = $dev->status();
830 # this test appears very liberal, but catches the case where setup_handle fails without
831 # giving false positives
832 ok(($status == $DEVICE_STATUS_SUCCESS) || (($status & $DEVICE_STATUS_VOLUME_UNLABELED) != 0),
833 "status is either OK or possibly unlabeled")
834 or diag($dev->error_or_status());
836 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
837 "start in write mode")
838 or diag($dev->error_or_status());
840 ok(!($dev->status() & $DEVICE_STATUS_VOLUME_UNLABELED),
842 or diag($dev->error_or_status());
844 for (my $i = 1; $i <= 3; $i++) {
845 write_file(0x2FACE, $dev->block_size()*10, $i);
849 "finish device after write")
850 or diag($dev->error_or_status());
853 ok(!($dev->status()),
854 "no error, at all, from read_label")
855 or diag($dev->error_or_status());
857 # append one more copy, to test ACCESS_APPEND
859 ok($dev->start($ACCESS_APPEND, undef, undef),
860 "start in append mode")
861 or diag($dev->error_or_status());
863 write_file(0xD0ED0E, $dev->block_size()*10, 4);
866 "finish device after append")
867 or diag($dev->error_or_status());
869 # try reading the third file back
871 ok($dev->start($ACCESS_READ, undef, undef),
872 "start in read mode")
873 or diag($dev->error_or_status());
875 verify_file(0x2FACE, $dev->block_size()*10, 3);
877 # test EOT indications on reading
878 my $hdr = $dev->seek_file(4);
879 is($hdr->{'type'}, $Amanda::Header::F_DUMPFILE,
880 "file 4 has correct type F_DUMPFILE");
882 $hdr = $dev->seek_file(5);
883 is($hdr->{'type'}, $Amanda::Header::F_TAPEEND,
884 "file 5 has correct type F_TAPEEND");
886 $hdr = $dev->seek_file(6);
887 is($hdr, undef, "seek_file returns undef for file 6");
890 "finish device after read")
891 or diag($dev->error_or_status()); # (note: we don't use write_max_size here,
892 # as the maximum for S3 is very large)
896 or diag($dev->error_or_status());
899 "erase device (again)")
900 or diag($dev->error_or_status());
903 "finish device after erase")
904 or diag($dev->error_or_status());
907 $status = $dev->status();
908 ok($status & $DEVICE_STATUS_VOLUME_UNLABELED,
909 "status is unlabeled after an erase")
910 or diag($dev->error_or_status());
912 $dev = s3_make_device($dev_name, "s3");
915 "erase device right after creation")
916 or diag($dev->error_or_status());
918 $dev = s3_make_device($dev_name, "s3");
920 # set MAX_VOLUME_USAGE, LEOM=true, ENFORCE_MAX_VOLUME_USAGE=false
921 ok($dev->property_set('MAX_VOLUME_USAGE', "512k"),
922 "set MAX_VOLUME_USAGE to test LEOM");
924 ok($dev->property_set("LEOM", 1),
927 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
928 "start in write mode")
929 or diag($dev->error_or_status());
931 write_file(0x2FACE, 440*1024, 1);
934 "device does not indicate LEOM after writing as property ENFORCE_MAX_VOLUME_USAGE not set and its default value is false");
937 "finish device after LEOM test")
938 or diag($dev->error_or_status());
942 or diag($dev->error_or_status());
944 $dev = s3_make_device($dev_name, "s3");
946 # set MAX_VOLUME_USAGE, LEOM=true, ENFORCE_MAX_VOLUME_USAGE=true
947 ok($dev->property_set('MAX_VOLUME_USAGE', "512k"),
948 "set MAX_VOLUME_USAGE to test LEOM");
950 ok($dev->property_set('ENFORCE_MAX_VOLUME_USAGE', 1 ),
951 "set ENFORCE_MAX_VOLUME_USAGE");
953 ok($dev->property_set("LEOM", 1),
956 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
957 "start in write mode")
958 or diag($dev->error_or_status());
960 write_file(0x2FACE, 440*1024, 1);
963 "device indicates LEOM after writing, when property ENFORCE_MAX_VOLUME_USAGE set to true");
966 "finish device after LEOM test")
967 or diag($dev->error_or_status());
971 or diag($dev->error_or_status());
973 $dev = s3_make_device($dev_name, "s3");
975 # set MAX_VOLUME_USAGE, LEOM=true, ENFORCE_MAX_VOLUME_USAGE=false
976 ok($dev->property_set('MAX_VOLUME_USAGE', "512k"),
977 "set MAX_VOLUME_USAGE to test LEOM");
979 ok($dev->property_set('ENFORCE_MAX_VOLUME_USAGE', 0 ),
980 "set ENFORCE_MAX_VOLUME_USAGE");
982 ok($dev->property_set("LEOM", 1),
985 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
986 "start in write mode")
987 or diag($dev->error_or_status());
989 write_file(0x2FACE, 440*1024, 1);
992 "device does not indicate LEOM after writing, when property ENFORCE_MAX_VOLUME_USAGE set to false");
995 "finish device after LEOM test")
996 or diag($dev->error_or_status());
1000 or diag($dev->error_or_status());
1002 # try with empty user token
1003 $dev_name = lc("s3:$base_name-s3");
1004 $dev = s3_make_device($dev_name, "s3");
1005 ok($dev->property_set('S3_USER_TOKEN', ''),
1006 "set devpay user token")
1007 or diag($dev->error_or_status());
1010 $status = $dev->status();
1011 ok(($status == $DEVICE_STATUS_SUCCESS) || (($status & $DEVICE_STATUS_VOLUME_UNLABELED) != 0),
1012 "status is either OK or possibly unlabeled")
1013 or diag($dev->error_or_status());
1019 or diag($dev->error_or_status());
1021 # try a eu-constrained bucket
1022 $dev_name = lc("s3:$base_name-s3-eu");
1023 $dev = s3_make_device($dev_name, "s3");
1024 ok($dev->property_set('S3_BUCKET_LOCATION', 'EU'),
1025 "set S3 bucket location to 'EU'")
1026 or diag($dev->error_or_status());
1028 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
1029 "start in write mode")
1030 or diag($dev->error_or_status());
1032 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1034 or diag($dev->error_or_status());
1040 or diag($dev->error_or_status());
1042 # try a wildcard-constrained bucket
1043 $dev_name = lc("s3:$base_name-s3-wild");
1044 $dev = s3_make_device($dev_name, "s3");
1045 ok($dev->property_set('S3_BUCKET_LOCATION', '*'),
1046 "set S3 bucket location to ''")
1047 or diag($dev->error_or_status());
1049 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
1050 "start in write mode")
1051 or diag($dev->error_or_status());
1053 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1055 or diag($dev->error_or_status());
1059 # test again with invalid ca_info
1060 $dev = s3_make_device($dev_name, "s3");
1062 skip "SSL not supported; can't check SSL_CA_INFO", 2
1063 unless $dev->property_get('S3_SSL');
1065 ok($dev->property_set('SSL_CA_INFO', '/dev/null'),
1066 "set invalid SSL/TLS CA certificate")
1067 or diag($dev->error_or_status());
1069 ok(!$dev->start($ACCESS_WRITE, "TESTCONF13", undef),
1070 "start in write mode")
1071 or diag($dev->error_or_status());
1073 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
1075 or diag($dev->error_or_status());
1080 # test again with our own CA bundle
1081 $dev = s3_make_device($dev_name, "s3");
1083 skip "SSL not supported; can't check SSL_CA_INFO", 4
1084 unless $dev->property_get('S3_SSL');
1085 ok($dev->property_set('SSL_CA_INFO', "$srcdir/data/aws-bundle.crt"),
1086 "set our own SSL/TLS CA certificate bundle")
1087 or diag($dev->error_or_status());
1091 or diag($dev->error_or_status());
1093 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
1094 "start in write mode")
1095 or diag($dev->error_or_status());
1097 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1099 or diag($dev->error_or_status());
1106 or diag($dev->error_or_status());
1108 # bucket names incompatible with location constraint
1109 $dev_name = "s3:-$base_name-s3-eu";
1110 $dev = s3_make_device($dev_name, "s3");
1112 ok($dev->property_set('S3_BUCKET_LOCATION', ''),
1113 "should be able to set an empty S3 bucket location with an incompatible name")
1114 or diag($dev->error_or_status());
1116 $dev_name = "s3:$base_name-s3.eu";
1117 $dev = s3_make_device($dev_name, "s3");
1119 ok($dev->property_set('S3_BUCKET_LOCATION', ''),
1120 "should be able to set an empty S3 bucket location with an incompatible name")
1121 or diag($dev->error_or_status());
1123 $dev_name = "s3:-$base_name-s3-eu";
1124 $dev = s3_make_device($dev_name, "s3");
1126 ok(!$dev->property_set('S3_BUCKET_LOCATION', 'EU'),
1127 "should not be able to set S3 bucket location with an incompatible name")
1128 or diag($dev->error_or_status());
1130 $dev_name = lc("s3:$base_name-s3-eu");
1131 $dev = s3_make_device($dev_name, "s3");
1132 ok($dev->property_set('S3_BUCKET_LOCATION', 'XYZ'),
1133 "should be able to set S3 bucket location with a compatible name")
1134 or diag($dev->error_or_status());
1136 $status = $dev->status();
1137 ok(($status == $DEVICE_STATUS_DEVICE_ERROR),
1138 "status is DEVICE_STATUS_DEVICE_ERROR")
1139 or diag($dev->error_or_status());
1140 my $error_msg = $dev->error_or_status();
1141 ok(($dev->error_or_status() == "While creating new S3 bucket: The specified location-constraint is not valid (Unknown) (HTTP 400)"),
1142 "invalid location-constraint")
1143 or diag("bad error: " . $dev->error_or_status());
1148 # in this case, most of our code has already been exercised
1149 # just make sure that authentication works as a basic sanity check
1150 skip "skipping abbreviated devpay tests", $s3_make_device_count + 1
1151 unless $run_devpay_tests;
1152 $dev_name = "s3:$base_name-devpay";
1153 $dev = s3_make_device($dev_name, "devpay");
1155 my $status = $dev->status();
1156 # this test appears very liberal, but catches the case where setup_handle fails without
1157 # giving false positives
1158 ok(($status == 0) || (($status & $DEVICE_STATUS_VOLUME_UNLABELED) != 0),
1159 "status is either OK or possibly unlabeled")
1160 or diag($dev->error_or_status());
1163 # Test a tape device if the proper environment variables are set
1164 my $TAPE_DEVICE = $ENV{'INSTALLCHECK_TAPE_DEVICE'};
1165 my $run_tape_tests = defined $TAPE_DEVICE;
1167 skip "define \$INSTALLCHECK_TAPE_DEVICE to run tape tests",
1169 7 * $verify_file_count +
1170 5 * $write_file_count
1171 unless $run_tape_tests;
1173 $dev_name = "tape:$TAPE_DEVICE";
1174 $dev = Amanda::Device->new($dev_name);
1175 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1176 "$dev_name: create successful")
1177 or diag($dev->error_or_status());
1179 my $status = $dev->read_label();
1180 ok(($status == $DEVICE_STATUS_SUCCESS) || (($status & $DEVICE_STATUS_VOLUME_UNLABELED) != 0),
1181 "status is either OK or possibly unlabeled")
1182 or diag($dev->error_or_status());
1184 ok($dev->start($ACCESS_WRITE, "TESTCONF13", undef),
1185 "start in write mode")
1186 or diag($dev->error_or_status());
1188 ok(!($dev->status() & $DEVICE_STATUS_VOLUME_UNLABELED),
1189 "not unlabeled anymore")
1190 or diag($dev->error_or_status());
1192 for (my $i = 1; $i <= 4; $i++) {
1193 write_file(0x2FACE+$i, $dev->block_size()*10+17, $i);
1197 "finish device after write")
1198 or diag($dev->error_or_status());
1201 ok(!($dev->status()),
1202 "no error, at all, from read_label")
1203 or diag($dev->error_or_status());
1205 is($dev->volume_label(), "TESTCONF13",
1206 "read_label reads the correct label")
1207 or diag($dev->error_or_status());
1209 # append one more copy, to test ACCESS_APPEND
1211 # if final_filemarks is 1, then the tape device will use F_NOOP,
1212 # inserting an extra file, and we'll be appending at file number 6.
1213 my $append_fileno = ($dev->property_get("FINAL_FILEMARKS") == 2)? 5:6;
1216 skip "APPEND not supported", $write_file_count + 2
1217 unless $dev->property_get("APPENDABLE");
1219 ok($dev->start($ACCESS_APPEND, undef, undef),
1220 "start in append mode")
1221 or diag($dev->error_or_status());
1223 write_file(0xD0ED0E, $dev->block_size()*4, $append_fileno);
1226 "finish device after append")
1227 or diag($dev->error_or_status());
1230 # try reading the second and third files back, creating a new
1231 # device object first, and skipping the read-label step.
1234 $dev = Amanda::Device->new($dev_name);
1235 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1236 "$dev_name: re-create successful")
1237 or diag($dev->error_or_status());
1239 # use a big read_block_size, checking that it's also settable
1240 # via read_buffer_size
1241 ok($dev->property_set("read_buffer_size", 256*1024),
1242 "can set read_buffer_size");
1243 is($dev->property_get("read_block_size"), 256*1024,
1244 "and its value is reflected in read_block_size");
1245 ok($dev->property_set("read_block_size", 32*1024),
1246 "can set read_block_size");
1248 ok($dev->start($ACCESS_READ, undef, undef),
1249 "start in read mode")
1250 or diag($dev->error_or_status());
1252 # now verify those files in a particular order to trigger all of the
1253 # seeking edge cases
1255 verify_file(0x2FACE+1, $dev->block_size()*10+17, 1);
1256 verify_file(0x2FACE+2, $dev->block_size()*10+17, 2);
1257 verify_file(0x2FACE+4, $dev->block_size()*10+17, 4);
1258 verify_file(0x2FACE+3, $dev->block_size()*10+17, 3);
1259 verify_file(0x2FACE+1, $dev->block_size()*10+17, 1);
1261 # try re-seeking to the same file
1262 ok(header_for($dev->seek_file(2), 2), "seek to file 2 the first time");
1263 verify_file(0x2FACE+2, $dev->block_size()*10+17, 2);
1264 ok(header_for($dev->seek_file(2), 2), "seek to file 2 the third time");
1266 # and seek through the same pattern *without* reading to EOF
1267 ok(header_for($dev->seek_file(1), 1), "seek to file 1");
1268 ok(header_for($dev->seek_file(2), 2), "seek to file 2");
1269 ok(header_for($dev->seek_file(4), 4), "seek to file 4");
1270 ok(header_for($dev->seek_file(3), 3), "seek to file 3");
1271 ok(header_for($dev->seek_file(1), 1), "seek to file 1");
1274 skip "APPEND not supported", $verify_file_count
1275 unless $dev->property_get("APPENDABLE");
1276 verify_file(0xD0ED0E, $dev->block_size()*4, $append_fileno);
1280 "finish device after read")
1281 or diag($dev->error_or_status());
1283 # tickle a regression in improperly closing fd's
1285 "finish device again after read")
1286 or diag($dev->error_or_status());
1288 ok($dev->read_label() == $DEVICE_STATUS_SUCCESS,
1289 "read_label after second finish (used to fail)")
1290 or diag($dev->error_or_status());
1292 # finally, run the device with FSF and BSF set to "no", to test the
1293 # fallback schemes for this condition
1296 $dev = Amanda::Device->new($dev_name);
1297 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1298 "$dev_name: re-create successful")
1299 or diag($dev->error_or_status());
1300 $dev->property_set("fsf", "no");
1301 $dev->property_set("bsf", "no");
1303 ok($dev->start($ACCESS_READ, undef, undef),
1304 "start in read mode")
1305 or diag($dev->error_or_status());
1307 ok(header_for($dev->seek_file(1), 1), "seek to file 1");
1308 ok(header_for($dev->seek_file(4), 4), "seek to file 4");
1309 ok(header_for($dev->seek_file(2), 2), "seek to file 2");
1312 "finish device after read")
1313 or diag($dev->error_or_status());
1317 skip "not built with ndmp and server", 26 unless
1318 Amanda::Util::built_with_component("ndmp") and
1319 Amanda::Util::built_with_component("server");
1322 my $testconf = Installcheck::Config->new();
1325 my $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
1326 if ($cfg_result != $CFGERR_OK) {
1327 my ($level, @errors) = Amanda::Config::config_errors();
1328 die(join "\n", @errors);
1331 my $ndmp = Installcheck::Mock::NdmpServer->new();
1332 my $ndmp_port = $ndmp->{'port'};
1333 my $drive = $ndmp->{'drive'};
1334 pass("started ndmjob in daemon mode");
1336 # set up a header for use below
1337 my $hdr = Amanda::Header->new();
1338 $hdr->{type} = $Amanda::Header::F_DUMPFILE;
1339 $hdr->{datestamp} = "20070102030405";
1340 $hdr->{dumplevel} = 0;
1341 $hdr->{compressed} = 1;
1342 $hdr->{name} = "localhost";
1343 $hdr->{disk} = "/home";
1344 $hdr->{program} = "INSTALLCHECK";
1346 $dev = Amanda::Device->new("ndmp:127.0.0.1:9i1\@foo");
1347 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
1348 "creation of an ndmp device fails with invalid port");
1350 $dev = Amanda::Device->new("ndmp:127.0.0.1:90000\@foo");
1351 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
1352 "creation of an ndmp device fails with too-large port");
1354 $dev = Amanda::Device->new("ndmp:127.0.0.1:$ndmp_port");
1355 isnt($dev->status(), $DEVICE_STATUS_SUCCESS,
1356 "creation of an ndmp device fails without ..\@device_name");
1358 $dev = Amanda::Device->new("ndmp:127.0.0.1:$ndmp_port\@$drive");
1359 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1360 "creation of an ndmp device succeeds with correct syntax");
1362 ok($dev->property_set("ndmp_username", "foo"),
1363 "set ndmp_username property");
1364 is($dev->property_get("ndmp_username"), "foo",
1365 "..and get the value back");
1366 ok($dev->property_set("ndmp_password", "bar"),
1367 "set ndmp_password property");
1368 is($dev->property_get("ndmp_password"), "bar",
1369 "..and get the value back");
1371 ok($dev->property_set("verbose", 1),
1374 # set 'em back to the defaults
1375 $dev->property_set("ndmp_username", "ndmp");
1376 $dev->property_set("ndmp_password", "ndmp");
1378 # use a big read_block_size, checking that it's also settable
1379 # via read_buffer_size
1380 ok($dev->property_set("read_block_size", 256*1024),
1381 "can set read_block_size");
1382 is($dev->property_get("read_block_size"), 256*1024,
1383 "and its value is reflected");
1384 ok($dev->property_set("read_block_size", 64*1024),
1385 "set read_block_size back to something smaller");
1387 # ok, let's fire the thing up
1388 ok($dev->start($ACCESS_WRITE, "TEST1", "20090915000000"),
1389 "start device in write mode")
1390 or diag $dev->error_or_status();
1392 ok($dev->start_file($hdr),
1395 { # write to the file
1396 my $xfer = Amanda::Xfer->new([
1397 Amanda::Xfer::Source::Random->new(32768*21, 0xBEEFEE00),
1398 Amanda::Xfer::Dest::Device->new($dev, 0) ]);
1399 $xfer->start(make_cb(xmsg_cb => sub {
1400 my ($src, $msg, $xfer) = @_;
1401 if ($msg->{'type'} == $XMSG_ERROR) {
1402 die $msg->{'elt'} . " failed: " . $msg->{'message'};
1403 } elsif ($msg->{'type'} == $XMSG_DONE) {
1404 Amanda::MainLoop::quit();
1408 Amanda::MainLoop::run();
1409 pass("wrote 21 blocks");
1414 or diag $dev->error_or_status();
1416 is($dev->read_label(), $DEVICE_STATUS_SUCCESS,
1417 "read label from (same) device")
1418 or diag $dev->error_or_status();
1420 is($dev->volume_label, "TEST1",
1421 "volume label read back correctly");
1423 ## label a device and check the label, but open a new device in between
1426 $dev = Amanda::Device->new("ndmp:127.0.0.1:$ndmp_port\@$drive");
1427 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1428 "creation of an ndmp device succeeds with correct syntax");
1429 $dev->property_set("ndmp_username", "ndmp");
1430 $dev->property_set("ndmp_password", "ndmp");
1431 $dev->property_set("verbose", 1);
1434 ok($dev->start($ACCESS_WRITE, "TEST2", "20090915000000"),
1435 "start device in write mode")
1436 or diag $dev->error_or_status();
1439 or diag $dev->error_or_status();
1441 # Read the label with a new device.
1442 $dev = Amanda::Device->new("ndmp:127.0.0.1:$ndmp_port\@$drive");
1443 is($dev->status(), $DEVICE_STATUS_SUCCESS,
1444 "creation of an ndmp device succeeds with correct syntax");
1445 $dev->property_set("ndmp_username", "ndmp");
1446 $dev->property_set("ndmp_password", "ndmp");
1447 $dev->property_set("verbose", 1);
1450 is($dev->read_label(), $DEVICE_STATUS_SUCCESS,
1451 "read label from device")
1452 or diag $dev->error_or_status();
1453 is($dev->volume_label, "TEST2",
1454 "volume label read back correctly");
1457 or diag $dev->error_or_status();
1462 unlink($input_filename);
1463 unlink($output_filename);