1 # Copyright (c) 2009-2012 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. Mathilda Ave., Suite 300
17 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19 use Test::More tests => 29;
25 use lib "@amperldir@";
26 use Installcheck::Config;
27 use Amanda::Config qw( :init );
29 use Amanda::Device qw( :constants );
33 use Amanda::Taper::Scribe qw( get_splitting_args_from_config );
36 # and disable Debug's die() and warn() overrides
37 Amanda::Debug::disable_die_override();
39 # put the debug messages somewhere
40 Amanda::Debug::dbopen("installcheck");
41 Installcheck::log_test_output();
43 # use some very small vtapes
44 my $volume_length = 512*1024;
47 $testconf = Installcheck::Config->new();
48 $testconf->add_tapetype("TEST-TAPE", [
49 "length" => ($volume_length / 1024) . " k",
53 my $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
54 if ($cfg_result != $CFGERR_OK) {
55 my ($level, @errors) = Amanda::Config::config_errors();
56 die(join "\n", @errors);
59 my $taperoot = "$Installcheck::TMP/Amanda_Taper_Scribe";
69 for my $slot (1 .. $nslots) {
70 mkdir("$taperoot/slot$slot")
71 or die("Could not mkdir: $!");
75 # an accumulator for the sequence of events that transpire during a run
88 Math::BigInt->new($_[0]);
91 # and similarly an Amanda::Changer::Error
93 Amanda::Changer::Error->new(@_);
97 ## Mock classes for the scribe
100 package Mock::Taperscan;
101 use Amanda::Device qw( :constants );
102 use Amanda::MainLoop;
107 my @slots = @{ $params{'slots'} || [] };
108 my $chg = $params{'changer'};
110 # wedge in an extra device property to disable LEOM support, if requested
111 if ($params{'disable_leom'}) {
112 $chg->{'config'}->{'device_properties'}->{'leom'}->{'values'} = [ 0 ];
114 $chg->{'config'}->{'device_properties'}->{'leom'}->{'values'} = [ 1 ];
120 next_or_current => "current",
128 sub make_new_tape_label {
135 my $result_cb = $params{'result_cb'};
139 my @slotarg = (@{$self->{'slots'}})?
140 (slot => shift @{$self->{'slots'}})
141 : (relative_slot => $self->{'next_or_current'});
142 $self->{'next_or_current'} = 'next';
144 my $res_cb = make_cb('res_cb' => sub {
145 my ($err, $res) = @_;
147 my $slot = $res? $res->{'this_slot'} : "none";
148 main::event("scan-finished", main::undef_or_str($err), "slot: $slot");
153 $result_cb->(undef, $res, 'FAKELABEL', $ACCESS_WRITE);
157 # delay this load call a little bit -- just enough so that the
158 # request_volume_permission event reliably occurs first
159 Amanda::MainLoop::call_after(50, sub {
160 $self->{'chg'}->load(@slotarg, set_current => 1, res_cb => $res_cb);
164 package Mock::Feedback;
165 use base qw( Amanda::Taper::Scribe::Feedback );
168 use Installcheck::Config;
174 rq_answers => [ @rq_answers ],
178 sub request_volume_permission {
181 my $answer = shift @{$self->{'rq_answers'}};
182 main::event("request_volume_permission", "answer:", $answer);
183 $main::scribe->start_scan();
184 $params{'perm_cb'}->(%{$answer});
187 sub scribe_notif_new_tape {
191 main::event("scribe_notif_new_tape",
192 main::undef_or_str($params{'error'}), $params{'volume_label'});
195 sub scribe_notif_part_done {
199 # this omits $duration, as it's not constant
200 main::event("scribe_notif_part_done",
201 $params{'partnum'}, $params{'fileno'},
202 $params{'successful'}, $params{'size'});
205 sub scribe_notif_tape_done {
209 main::event("scribe_notif_tape_done",
210 $params{'volume_label'}, $params{'num_files'},
212 $params{'finished_cb'}->();
224 # utility fn to stringify changer errors (earlier perls' Test::More's
225 # fail to do this automatically)
226 sub undef_or_str { (defined $_[0])? "".$_[0] : undef; }
229 my ($nruns, $taperscan, $feedback) = @_;
233 reset_taperoot($nruns);
234 $main::scribe = Amanda::Taper::Scribe->new(
235 taperscan => $taperscan,
236 feedback => $feedback);
237 $devh = $main::scribe->{'devhandling'};
239 my ($start, $get_volume, $got_volume, $quit);
241 $start = make_cb(start => sub {
245 # give start() time to get the scan going before
246 # calling get_volume -- this wouldn't ordinarily be
247 # necessary, but we want to make sure that start() is
248 # really kicking off the scan.
253 $get_volume = make_cb(get_volume => sub {
254 if (++$runcount > $nruns) {
260 $devh->get_volume(volume_cb => $got_volume);
263 $got_volume = make_cb(got_volume => sub {
264 my ($scan_error, $config_denial_message, $error_denial_message,
265 $reservation, $volume_label, $access_mode) = @_;
268 undef_or_str($scan_error),
269 $config_denial_message, $error_denial_message,
270 $reservation? ("slot: ".$reservation->{'this_slot'}) : undef);
272 if ($scan_error or $config_denial_message or $error_denial_message) {
277 $reservation->release(finished_cb => sub {
279 event("release", $error);
288 $quit = make_cb(quit => sub {
290 Amanda::MainLoop::quit();
294 Amanda::MainLoop::run();
298 my $chg = Amanda::Changer->new("chg-disk:$taperoot");
299 run_devh(3, Mock::Taperscan->new(changer => $chg), Mock::Feedback->new({allow => 1}, {allow => 1}, {allow => 1}));
300 is_deeply([ @events ], [
302 [ 'scan' ], # scan starts *before* get_volume
305 [ 'request_volume_permission', 'answer:', { allow => 1 }, ],
306 [ 'scan-finished', undef, "slot: 1" ],
307 [ 'got_volume', undef, undef, undef, "slot: 1" ],
308 [ 'release', undef ],
311 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
312 [ 'scan' ], # scan starts *after* request_volume_permission
313 [ 'scan-finished', undef, "slot: 2" ],
314 [ 'got_volume', undef, undef, undef, "slot: 2" ],
315 [ 'release', undef ],
318 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
320 [ 'scan-finished', undef, "slot: 3" ],
321 [ 'got_volume', undef, undef, undef, "slot: 3" ],
322 [ 'release', undef ],
325 ], "correct event sequence for basic run of DevHandling")
326 or diag(Dumper([@events]));
328 run_devh(1, Mock::Taperscan->new(changer => $chg), Mock::Feedback->new({cause => 'config', message => 'no-can-do'}));
329 is_deeply([ @events ], [
334 [ 'request_volume_permission', 'answer:', { cause => 'config', message => 'no-can-do' } ],
335 [ 'scan-finished', undef, "slot: 1" ],
336 [ 'got_volume', undef, 'no-can-do', undef, undef ],
339 ], "correct event sequence for a run without permission")
340 or diag(Dumper([@events]));
342 run_devh(1, Mock::Taperscan->new(slots => ["bogus"], changer => $chg), Mock::Feedback->new({allow => 1}));
343 is_deeply([ @events ], [
348 [ 'request_volume_permission', 'answer:', { allow => 1} ],
349 [ 'scan-finished', "Slot bogus not found", "slot: none" ],
350 [ 'got_volume', 'Slot bogus not found', undef, undef, undef ],
353 ], "correct event sequence for a run with a changer error")
354 or diag(Dumper([@events]));
356 run_devh(1, Mock::Taperscan->new(slots => ["bogus"], changer => $chg),
357 Mock::Feedback->new({cause => 'config', message => "not this time"}));
358 is_deeply([ @events ], [
363 [ 'request_volume_permission', 'answer:', {cause => 'config', message =>'not this time'} ],
364 [ 'scan-finished', "Slot bogus not found", "slot: none" ],
365 [ 'got_volume', 'Slot bogus not found', 'not this time', undef, undef ],
368 ], "correct event sequence for a run with no permission AND a changer config denial")
369 or diag(Dumper([@events]));
371 run_devh(1, Mock::Taperscan->new(slots => ["bogus"], changer => $chg), Mock::Feedback->new({cause => 'error', message => "frobnicator exploded!"}));
372 is_deeply([ @events ], [
377 [ 'request_volume_permission', 'answer:', {cause => 'error', message => "frobnicator exploded!"} ],
378 [ 'scan-finished', "Slot bogus not found", "slot: none" ],
379 [ 'got_volume', 'Slot bogus not found', undef, "frobnicator exploded!", undef ],
382 ], "correct event sequence for a run with no permission AND a changer error")
383 or diag(Dumper([@events]));
389 sub run_scribe_xfer_async {
390 my ($data_length, $scribe, %params) = @_;
393 my $finished_cb = $params{'finished_cb'};
394 my $steps = define_steps
395 cb_ref => \$finished_cb;
397 step start_scribe => sub {
398 if ($params{'start_scribe'}) {
399 $scribe->start(%{ $params{'start_scribe'} },
400 finished_cb => $steps->{'get_xdt'});
402 $steps->{'get_xdt'}->();
406 step get_xdt => sub {
411 my $xdt = $scribe->get_xfer_dest(
413 max_memory => 1024 * 64,
414 part_size => (defined $params{'part_size'})? $params{'part_size'} : (1024 * 128),
415 part_cache_type => $params{'part_cache_type'} || 'memory',
416 disk_cache_dirname => undef);
420 my $hdr = Amanda::Header->new();
421 $hdr->{type} = $Amanda::Header::F_DUMPFILE;
422 $hdr->{datestamp} = "20010203040506";
423 $hdr->{dumplevel} = 0;
424 $hdr->{compressed} = 1;
425 $hdr->{name} = "localhost";
426 $hdr->{disk} = "/home";
427 $hdr->{program} = "INSTALLCHECK";
429 $xfer = Amanda::Xfer->new([
430 Amanda::Xfer::Source::Random->new($data_length, 0x5EED5),
435 $scribe->handle_xmsg(@_);
441 dump_cb => $steps->{'dump_cb'});
444 step dump_cb => sub {
447 main::event("dump_cb",
449 [ map { "$_" } @{$params{'device_errors'}} ],
450 $params{'config_denial_message'},
457 sub run_scribe_xfer {
458 my ($data_length, $scribe, %params) = @_;
459 $params{'finished_cb'} = \&Amanda::MainLoop::quit;
460 run_scribe_xfer_async($data_length, $scribe, %params);
461 Amanda::MainLoop::run();
467 my $finished_cb = make_cb(finished_cb => sub {
469 die "$error" if $error;
471 Amanda::MainLoop::quit();
474 $scribe->quit(finished_cb => $finished_cb);
476 Amanda::MainLoop::run();
481 # write less than a tape full, without LEOM
484 $main::scribe = Amanda::Taper::Scribe->new(
485 taperscan => Mock::Taperscan->new(disable_leom => 1, changer => $chg),
486 feedback => Mock::Feedback->new({allow => 1}));
489 run_scribe_xfer(1024*200, $main::scribe,
490 part_size => 96*1024,
491 start_scribe => { write_timestamp => "20010203040506" });
493 is_deeply([ @events ], [
495 [ 'scan-finished', undef, 'slot: 1' ],
496 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
497 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
498 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(98304) ],
499 [ 'scribe_notif_part_done', bi(2), bi(2), 1, bi(98304) ],
500 [ 'scribe_notif_part_done', bi(3), bi(3), 1, bi(8192) ],
501 [ 'dump_cb', 'DONE', [], undef, bi(204800) ],
502 ], "correct event sequence for a multipart scribe of less than a whole volume, without LEOM")
503 or diag(Dumper([@events]));
505 # pick up where we left off, writing just a tiny bit more, and then quit
507 run_scribe_xfer(1024*30, $main::scribe);
509 quit_scribe($main::scribe);
511 is_deeply([ @events ], [
512 [ 'scribe_notif_part_done', bi(1), bi(4), 1, bi(30720) ],
513 [ 'dump_cb', 'DONE', [], undef, bi(30720) ],
514 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(4), bi(235520) ],
515 ], "correct event sequence for a subsequent single-part scribe, still on the same volume")
516 or diag(Dumper([@events]));
518 # write less than a tape full, *with* LEOM (should look the same as above)
521 $main::scribe = Amanda::Taper::Scribe->new(
522 taperscan => Mock::Taperscan->new(changer => $chg),
523 feedback => Mock::Feedback->new({ allow => 1 }));
526 run_scribe_xfer(1024*200, $main::scribe,
527 part_size => 96*1024,
528 start_scribe => { write_timestamp => "20010203040506" });
530 quit_scribe($main::scribe);
532 is_deeply([ @events ], [
534 [ 'scan-finished', undef, 'slot: 1' ],
535 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
536 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
537 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(98304) ],
538 [ 'scribe_notif_part_done', bi(2), bi(2), 1, bi(98304) ],
539 [ 'scribe_notif_part_done', bi(3), bi(3), 1, bi(8192) ],
540 [ 'dump_cb', 'DONE', [], undef, bi(204800) ],
541 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(3), bi(204800) ],
542 ], "correct event sequence for a multipart scribe of less than a whole volume, with LEOM")
543 or diag(Dumper([@events]));
545 # start over again and try a multivolume write
547 # NOTE: the part size and volume size are such that the VFS driver produces
548 # ENOSPC while writing the fourth file header, rather than while writing
549 # data. This is a much less common error path, so it's good to test it.
552 $main::scribe = Amanda::Taper::Scribe->new(
553 taperscan => Mock::Taperscan->new(disable_leom => 1, changer => $chg),
554 feedback => Mock::Feedback->new({ allow => 1 }, { allow => 1 }));
557 run_scribe_xfer($volume_length + $volume_length / 4, $main::scribe,
558 start_scribe => { write_timestamp => "20010203040506" });
560 quit_scribe($main::scribe);
562 is_deeply([ @events ], [
564 [ 'scan-finished', undef, 'slot: 1' ],
565 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
566 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
568 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(131072) ],
569 [ 'scribe_notif_part_done', bi(2), bi(2), 1, bi(131072) ],
570 [ 'scribe_notif_part_done', bi(3), bi(3), 1, bi(131072) ],
571 [ 'scribe_notif_part_done', bi(4), bi(0), 0, bi(0) ],
573 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(3), bi(393216) ],
574 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
576 [ 'scan-finished', undef, 'slot: 2' ],
577 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
579 [ 'scribe_notif_part_done', bi(4), bi(1), 1, bi(131072) ],
580 [ 'scribe_notif_part_done', bi(5), bi(2), 1, bi(131072) ],
581 # empty part is written but not notified, although it is counted
582 # in scribe_notif_tape_done
584 [ 'dump_cb', 'DONE', [], undef, bi(655360) ],
585 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(3), bi(262144) ],
586 ], "correct event sequence for a multipart scribe of more than a whole volume, without LEOM" . Data::Dumper::Dumper(@events))
587 or print (Dumper([@events]));
589 # same test, but with LEOM support
592 $main::scribe = Amanda::Taper::Scribe->new(
593 taperscan => Mock::Taperscan->new(changer => $chg),
594 feedback => Mock::Feedback->new({ allow => 1 },{ allow => 1 }));
597 run_scribe_xfer(1024*520, $main::scribe,
598 start_scribe => { write_timestamp => "20010203040506" });
600 quit_scribe($main::scribe);
602 is_deeply([ @events ], [
604 [ 'scan-finished', undef, 'slot: 1' ],
605 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
606 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
608 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(131072) ],
609 [ 'scribe_notif_part_done', bi(2), bi(2), 1, bi(131072) ],
610 [ 'scribe_notif_part_done', bi(3), bi(3), 1, bi(32768) ], # LEOM comes earlier than PEOM did
612 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(3), bi(294912) ],
613 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
615 [ 'scan-finished', undef, 'slot: 2' ],
616 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
618 [ 'scribe_notif_part_done', bi(4), bi(1), 1, bi(131072) ],
619 [ 'scribe_notif_part_done', bi(5), bi(2), 1, bi(106496) ],
621 [ 'dump_cb', 'DONE', [], undef, bi(532480) ],
622 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(2), bi(237568) ],
623 ], "correct event sequence for a multipart scribe of more than a whole volume, with LEOM")
624 or print (Dumper([@events]));
626 # now a multivolume write where the second volume gives a changer error
629 $main::scribe = Amanda::Taper::Scribe->new(
630 taperscan => Mock::Taperscan->new(slots => ["1", "bogus"], disable_leom => 1, changer => $chg),
631 feedback => Mock::Feedback->new({ allow => 1 },{ allow => 1 }));
634 run_scribe_xfer($volume_length + $volume_length / 4, $main::scribe,
635 start_scribe => { write_timestamp => "20010203040507" });
637 quit_scribe($main::scribe);
639 $experr = 'Slot bogus not found';
640 is_deeply([ @events ], [
642 [ 'scan-finished', undef, 'slot: 1' ],
643 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
644 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
646 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(131072) ],
647 [ 'scribe_notif_part_done', bi(2), bi(2), 1, bi(131072) ],
648 [ 'scribe_notif_part_done', bi(3), bi(3), 1, bi(131072) ],
649 [ 'scribe_notif_part_done', bi(4), bi(0), 0, bi(0) ],
651 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(3), bi(393216) ],
652 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
654 [ 'scan-finished', $experr, 'slot: none' ],
655 [ 'scribe_notif_new_tape', $experr, undef ],
657 [ 'dump_cb', 'PARTIAL', [$experr], undef, bi(393216) ],
658 # (no scribe_notif_tape_done)
659 ], "correct event sequence for a multivolume scribe with no second vol, without LEOM")
660 or print (Dumper([@events]));
663 $main::scribe = Amanda::Taper::Scribe->new(
664 taperscan => Mock::Taperscan->new(slots => ["1", "bogus"], changer => $chg),
665 feedback => Mock::Feedback->new({ allow => 1 }, { allow => 1 }));
668 run_scribe_xfer($volume_length + $volume_length / 4, $main::scribe,
669 start_scribe => { write_timestamp => "20010203040507" });
671 quit_scribe($main::scribe);
673 $experr = 'Slot bogus not found';
674 is_deeply([ @events ], [
676 [ 'scan-finished', undef, 'slot: 1' ],
677 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
678 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
680 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(131072) ],
681 [ 'scribe_notif_part_done', bi(2), bi(2), 1, bi(131072) ],
682 [ 'scribe_notif_part_done', bi(3), bi(3), 1, bi(32768) ], # LEOM comes long before PEOM
684 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(3), bi(294912) ],
685 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
687 [ 'scan-finished', $experr, 'slot: none' ],
688 [ 'scribe_notif_new_tape', $experr, undef ],
690 [ 'dump_cb', 'PARTIAL', [$experr], undef, bi(294912) ],
691 # (no scribe_notif_tape_done)
692 ], "correct event sequence for a multivolume scribe with no second vol, with LEOM")
693 or print (Dumper([@events]));
695 # now a multivolume write where the second volume does not have permission
698 $main::scribe = Amanda::Taper::Scribe->new(
699 taperscan => Mock::Taperscan->new(changer => $chg),
700 feedback => Mock::Feedback->new({ allow => 1 }, { cause => 'config', message => "sorry!" }));
703 run_scribe_xfer($volume_length + $volume_length / 4, $main::scribe,
704 start_scribe => { write_timestamp => "20010203040507" });
706 quit_scribe($main::scribe);
708 is_deeply([ @events ], [
710 [ 'scan-finished', undef, 'slot: 1' ],
711 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
712 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
714 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(131072) ],
715 [ 'scribe_notif_part_done', bi(2), bi(2), 1, bi(131072) ],
716 [ 'scribe_notif_part_done', bi(3), bi(3), 1, bi(32768) ],
718 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(3), bi(294912) ],
719 [ 'request_volume_permission', 'answer:', { cause => 'config', message => "sorry!" } ],
721 [ 'scan-finished', undef, 'slot: 2' ],
723 [ 'dump_cb', 'PARTIAL', [], "sorry!", bi(294912) ],
724 ], "correct event sequence for a multivolume scribe with next vol denied")
725 or print (Dumper([@events]));
727 # a non-splitting xfer on a single volume
730 $main::scribe = Amanda::Taper::Scribe->new(
731 taperscan => Mock::Taperscan->new(disable_leom => 1, changer => $chg),
732 feedback => Mock::Feedback->new({ allow => 1 }));
735 run_scribe_xfer(1024*300, $main::scribe, part_size => 0, part_cache_type => 'none',
736 start_scribe => { write_timestamp => "20010203040506" });
738 quit_scribe($main::scribe);
740 is_deeply([ @events ], [
742 [ 'scan-finished', undef, 'slot: 1' ],
743 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
744 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
745 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(307200) ],
746 [ 'dump_cb', 'DONE', [], undef, bi(307200) ],
747 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(1), bi(307200) ],
748 ], "correct event sequence for a non-splitting scribe of less than a whole volume, without LEOM")
749 or diag(Dumper([@events]));
752 $main::scribe = Amanda::Taper::Scribe->new(
753 taperscan => Mock::Taperscan->new(changer => $chg),
754 feedback => Mock::Feedback->new({ allow => 1 }));
755 $Amanda::Config::debug_taper = 9;
757 run_scribe_xfer(1024*300, $main::scribe, part_size => 0, part_cache_type => 'none',
758 start_scribe => { write_timestamp => "20010203040506" });
760 quit_scribe($main::scribe);
762 is_deeply([ @events ], [
764 [ 'scan-finished', undef, 'slot: 1' ],
765 [ 'request_volume_permission', 'answer:', { allow => 1 } ],
766 [ 'scribe_notif_new_tape', undef, 'FAKELABEL' ],
767 [ 'scribe_notif_part_done', bi(1), bi(1), 1, bi(307200) ],
768 [ 'dump_cb', 'DONE', [], undef, bi(307200) ],
769 [ 'scribe_notif_tape_done', 'FAKELABEL', bi(1), bi(307200) ],
770 ], "correct event sequence for a non-splitting scribe of less than a whole volume, with LEOM")
771 or diag(Dumper([@events]));
773 # DirectTCP support is tested through the taper installcheck
775 # test get_splitting_args_from_config thoroughly
776 my $maxint64 = Math::BigInt->new("9223372036854775808");
779 { get_splitting_args_from_config(
781 { allow_split => 0 },
782 "default is only allow_split set to 0");
785 { get_splitting_args_from_config(
786 dle_tape_splitsize => 0,
787 dle_split_diskbuffer => $Installcheck::TMP,
788 dle_fallback_splitsize => 100,
790 { allow_split => 0, part_size => 0, part_cache_type => 'none' },
791 "tape_splitsize = 0 indicates no splitting");
794 { get_splitting_args_from_config(
795 dle_allow_split => 0,
797 part_cache_dir => "/tmp",
799 { allow_split => 0 },
800 "default if dle_allow_split is false, no splitting");
803 { get_splitting_args_from_config(
804 dle_tape_splitsize => 200,
805 dle_fallback_splitsize => 150,
807 { allow_split => 1,part_cache_type => 'memory', part_size => 200, part_cache_max_size => 150 },
808 "when cache_inform is available, tape_splitsize is used, not fallback");
811 { get_splitting_args_from_config(
812 dle_tape_splitsize => 200,
814 { allow_split => 1, part_size => 200, part_cache_type => 'memory', part_cache_max_size => 1024*1024*10, },
815 "no split_diskbuffer and no fallback_splitsize, fall back to default (10M)");
818 { get_splitting_args_from_config(
819 dle_tape_splitsize => 200,
820 dle_split_diskbuffer => "$Installcheck::TMP/does!not!exist!",
821 dle_fallback_splitsize => 150,
823 { allow_split => 1, part_size => 200, part_cache_type => 'memory', part_cache_max_size => 150 },
824 "invalid split_diskbuffer => fall back (silently)");
827 { get_splitting_args_from_config(
828 dle_tape_splitsize => 200,
829 dle_split_diskbuffer => "$Installcheck::TMP/does!not!exist!",
831 { allow_split => 1, part_size => 200, part_cache_type => 'memory', part_cache_max_size => 1024*1024*10 },
832 ".. even to the default fallback (10M)");
835 { get_splitting_args_from_config(
836 dle_tape_splitsize => $maxint64,
837 dle_split_diskbuffer => "$Installcheck::TMP",
838 dle_fallback_splitsize => 250,
840 { allow_split => 1, part_size => $maxint64, part_cache_type => 'memory', part_cache_max_size => 250,
841 warning => "falling back to memory buffer for splitting: " .
842 "insufficient space in disk cache directory" },
843 "not enough space in split_diskbuffer => fall back (with warning)");
846 { get_splitting_args_from_config(
847 can_cache_inform => 0,
848 dle_tape_splitsize => 200,
849 dle_split_diskbuffer => "$Installcheck::TMP",
850 dle_fallback_splitsize => 150,
852 { allow_split => 1, part_size => 200, part_cache_type => 'disk', part_cache_dir => "$Installcheck::TMP" },
853 "if split_diskbuffer exists and splitsize is nonzero, use it");
856 { get_splitting_args_from_config(
857 dle_tape_splitsize => 0,
858 dle_split_diskbuffer => "$Installcheck::TMP",
859 dle_fallback_splitsize => 250,
861 { allow_split => 0, part_size => 0, part_cache_type => 'none' },
862 ".. but if splitsize is zero, no splitting");
865 { get_splitting_args_from_config(
866 dle_split_diskbuffer => "$Installcheck::TMP",
867 dle_fallback_splitsize => 250,
869 { allow_split => 0, part_size => 0, part_cache_type => 'none' },
870 ".. and if splitsize is missing, no splitting");
873 { get_splitting_args_from_config(
875 part_cache_type => 'none',
877 { allow_split => 1, part_size => 300, part_cache_type => 'none' },
878 "part_* parameters handled correctly when missing");
881 { get_splitting_args_from_config(
883 part_cache_type => 'disk',
884 part_cache_dir => $Installcheck::TMP,
885 part_cache_max_size => 250,
887 { allow_split => 1, part_size => 300, part_cache_type => 'disk',
888 part_cache_dir => $Installcheck::TMP, part_cache_max_size => 250, },
889 "part_* parameters handled correctly when specified");
892 { get_splitting_args_from_config(
894 part_cache_type => 'disk',
895 part_cache_dir => "$Installcheck::TMP/does!not!exist!",
896 part_cache_max_size => 250,
898 { allow_split => 1, part_size => 300, part_cache_type => 'none',
899 part_cache_max_size => 250,
900 warning => "part-cache-dir '$Installcheck::TMP/does!not!exist! does not exist; "
901 . "using part cache type 'none'"},
902 "part_* parameters handled correctly when specified");