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 => 12;
23 use lib "@amperldir@";
24 use Installcheck::Run;
25 use Amanda::Xfer qw( :constants );
26 use Amanda::Device qw( :constants );
33 # set up debugging so debug output doesn't interfere with test results
34 Amanda::Debug::dbopen("installcheck");
36 # and disable Debug's die() and warn() overrides
37 Amanda::Debug::disable_die_override();
39 # initialize configuration for the device API
40 Amanda::Config::config_init(0, undef);
43 my $RANDOM_SEED = 0xD00D;
45 my $xfer = Amanda::Xfer->new([
46 Amanda::Xfer::Source::Random->new(1024*1024, $RANDOM_SEED),
47 Amanda::Xfer::Filter::Xor->new(0), # key of 0 -> no change, so random seeds match
48 Amanda::Xfer::Dest::Null->new($RANDOM_SEED),
51 pass("Creating a transfer doesn't crash"); # hey, it's a start..
53 my $got_msg = "(not received)";
54 $xfer->get_source()->set_callback(sub {
55 my ($src, $msg, $xfer) = @_;
56 if ($msg->{type} == $XMSG_ERROR) {
57 die $msg->{elt} . " failed: " . $msg->{message};
59 if ($msg->{type} == $XMSG_INFO) {
60 $got_msg = $msg->{message};
62 elsif ($xfer->get_status() == $Amanda::Xfer::XFER_DONE) {
64 Amanda::MainLoop::quit();
68 Amanda::MainLoop::run();
69 pass("A simple transfer runs to completion");
70 is($got_msg, "Is this thing on?",
71 "XMSG_INFO from Amanda::Xfer::Dest::Null has correct message");
75 my $RANDOM_SEED = 0xDEADBEEF;
77 my $xfer1 = Amanda::Xfer->new([
78 Amanda::Xfer::Source::Random->new(1024*1024, $RANDOM_SEED),
79 Amanda::Xfer::Dest::Null->new($RANDOM_SEED),
81 my $xfer2 = Amanda::Xfer->new([
82 Amanda::Xfer::Source::Random->new(1024*1024*3, $RANDOM_SEED),
83 Amanda::Xfer::Filter::Xor->new(0xf0),
84 Amanda::Xfer::Filter::Xor->new(0xf0),
85 Amanda::Xfer::Dest::Null->new($RANDOM_SEED),
89 my ($src, $msg, $xfer) = @_;
90 if ($msg->{type} == $XMSG_ERROR) {
91 die $msg->{elt} . " failed: " . $msg->{message};
93 if ($xfer1->get_status() == $Amanda::Xfer::XFER_DONE
94 and $xfer2->get_status() == $Amanda::Xfer::XFER_DONE) {
95 $xfer1->get_source()->remove();
96 $xfer2->get_source()->remove();
97 Amanda::MainLoop::quit();
101 $xfer1->get_source()->set_callback($cb);
102 $xfer2->get_source()->set_callback($cb);
107 # let the already-started transfers go out of scope before they
108 # complete, as a memory management test..
109 Amanda::MainLoop::run();
110 pass("Two simultaneous transfers run to completion");
113 my $RANDOM_SEED = 0xD0DEEDAA;
116 # note that, because the Xor filter is flexible, assembling
117 # long pipelines can take an exponentially long time. A 10-elt
118 # pipeline exercises the linking algorithm without wasting
119 # too many CPU cycles
121 push @elts, Amanda::Xfer::Source::Random->new(1024*1024, $RANDOM_SEED);
123 push @elts, Amanda::Xfer::Filter::Xor->new($i);
124 push @elts, Amanda::Xfer::Filter::Xor->new($i);
126 push @elts, Amanda::Xfer::Dest::Null->new($RANDOM_SEED);
127 my $xfer = Amanda::Xfer->new(\@elts);
130 my ($src, $msg, $xfer) = @_;
131 if ($msg->{type} == $XMSG_ERROR) {
132 die $msg->{elt} . " failed: " . $msg->{message};
134 if ($xfer->get_status() == $Amanda::Xfer::XFER_DONE) {
135 $xfer->get_source()->remove();
136 Amanda::MainLoop::quit();
140 $xfer->get_source()->set_callback($cb);
143 Amanda::MainLoop::run();
144 pass("One 10-element transfer runs to completion");
149 my $read_filename = "$Amanda::Paths::AMANDA_TMPDIR/xfer-junk-src.tmp";
150 my $write_filename = "$Amanda::Paths::AMANDA_TMPDIR/xfer-junk-dest.tmp";
153 mkdir($Amanda::Paths::AMANDA_TMPDIR) unless (-e $Amanda::Paths::AMANDA_TMPDIR);
155 # fill the file with some stuff
156 open($wfh, ">", $read_filename) or die("Could not open '$read_filename' for writing");
157 for my $i (1 .. 100) { print $wfh "line $i\n"; }
160 open($rfh, "<", $read_filename) or die("Could not open '$read_filename' for reading");
161 open($wfh, ">", "$write_filename") or die("Could not open '$write_filename' for writing");
163 # now run a transfer out of it
164 my $xfer = Amanda::Xfer->new([
165 Amanda::Xfer::Source::Fd->new(fileno($rfh)),
166 Amanda::Xfer::Filter::Xor->new(0xde),
167 Amanda::Xfer::Filter::Xor->new(0xde),
168 Amanda::Xfer::Dest::Fd->new(fileno($wfh)),
172 my ($src, $msg, $xfer) = @_;
173 if ($msg->{type} == $XMSG_ERROR) {
174 die $msg->{elt} . " failed: " . $msg->{message};
176 if ($xfer->get_status() == $Amanda::Xfer::XFER_DONE) {
177 $xfer->get_source()->remove();
178 Amanda::MainLoop::quit();
182 $xfer->get_source()->set_callback($cb);
185 Amanda::MainLoop::run();
190 # now verify the file contents are identical
191 open($rfh, "<", $read_filename);
192 my $src = do { local $/; <$rfh> };
194 open($rfh, "<", $write_filename);
195 my $dest = do { local $/; <$rfh> };
197 is($src, $dest, "Source::Fd and Dest::Fd read and write files");
199 unlink($read_filename);
200 unlink($write_filename);
203 # exercise device source and destination
205 my $RANDOM_SEED = 0xFACADE;
209 my ($src, $msg, $xfer) = @_;
210 if ($msg->{type} == $XMSG_ERROR) {
211 die $msg->{elt} . " failed: " . $msg->{message};
213 if ($xfer->get_status() == $Amanda::Xfer::XFER_DONE) {
214 $xfer->get_source()->remove();
215 Amanda::MainLoop::quit();
220 my $testconf = Installcheck::Run::setup();
223 # set up a device for slot 1
224 my $device = Amanda::Device->new("file:" . Installcheck::Run::load_vtape(1));
225 die("Could not open VFS device: " . $device->error())
226 unless ($device->status() == $DEVICE_STATUS_SUCCESS);
229 my $hdr = Amanda::Types::dumpfile_t->new();
230 $hdr->{type} = $Amanda::Types::F_DUMPFILE;
231 $hdr->{name} = "installcheck";
233 $hdr->{datestamp} = "20080102030405";
236 $device->start($ACCESS_WRITE, "TESTCONF01", "20080102030405");
237 $device->start_file($hdr);
239 $xfer = Amanda::Xfer->new([
240 Amanda::Xfer::Source::Random->new(1024*1024, $RANDOM_SEED),
241 Amanda::Xfer::Dest::Device->new($device, $device->block_size() * 10),
244 $xfer->get_source()->set_callback($quit_cb);
247 Amanda::MainLoop::run();
248 pass("write to a device (completed succesfully; data may not be correct)");
250 # finish up the file and device
251 ok(!$device->in_file(), "not in_file");
252 ok($device->finish(), "finish");
254 # now turn around and read from it
255 $device->start($ACCESS_READ, undef, undef);
256 $device->seek_file(1);
258 $xfer = Amanda::Xfer->new([
259 Amanda::Xfer::Source::Device->new($device),
260 Amanda::Xfer::Dest::Null->new($RANDOM_SEED),
263 $xfer->get_source()->set_callback($quit_cb);
266 Amanda::MainLoop::run();
267 pass("read from a device succeeded, too, and data was correct");
271 my $RANDOM_SEED = 0x5EAF00D;
273 # build a transfer that will keep going forever
274 my $xfer = Amanda::Xfer->new([
275 Amanda::Xfer::Source::Random->new(0, $RANDOM_SEED),
276 Amanda::Xfer::Filter::Xor->new(14),
277 Amanda::Xfer::Filter::Xor->new(14),
278 Amanda::Xfer::Dest::Null->new($RANDOM_SEED),
282 Amanda::MainLoop::timeout_source(200)->set_callback(sub {
288 $xfer->get_source()->set_callback(sub {
289 my ($src, $msg, $xfer) = @_;
290 if ($msg->{type} == $XMSG_ERROR) {
291 die $msg->{elt} . " failed: " . $msg->{message};
293 if ($xfer->get_status() == $Amanda::Xfer::XFER_DONE) {
295 Amanda::MainLoop::quit();
299 Amanda::MainLoop::run();
300 ok($got_timeout, "A neverending transfer finishes after being cancelled");
301 # (note that this does not test all of the cancellation possibilities)
305 # build a transfer that will write to a read-only fd
306 my $read_filename = "$Amanda::Paths::AMANDA_TMPDIR/xfer-junk-src.tmp";
310 open($rfh, ">", $read_filename) or die("Could not open '$read_filename' for writing");
312 # open it for reading
313 open($rfh, "<", $read_filename) or die("Could not open '$read_filename' for reading");;
315 my $xfer = Amanda::Xfer->new([
316 Amanda::Xfer::Source::Random->new(0, 1),
317 Amanda::Xfer::Dest::Fd->new(fileno($rfh)),
321 $xfer->get_source()->set_callback(sub {
322 my ($src, $msg, $xfer) = @_;
323 if ($msg->{type} == $XMSG_ERROR) {
326 if ($xfer->get_status() == $Amanda::Xfer::XFER_DONE) {
328 Amanda::MainLoop::quit();
332 Amanda::MainLoop::run();
333 ok($got_error, "A transfer with an error cancels itself after sending an error");