+
+/*
+ * This test writes Bacula blocks to the tape in
+ * several files. It then rewinds the tape and attepts
+ * to read these blocks back checking the data.
+ */
+static int write_read_test()
+{
+ DEV_BLOCK *block;
+ DEV_RECORD *rec;
+ int stat = 0;
+ int len, i, j;
+ int *p;
+
+ Pmsg0(-1, _("\n=== Write, rewind, and re-read test ===\n\n"
+ "I'm going to write 1000 records and an EOF\n"
+ "then write 1000 records and an EOF, then rewind,\n"
+ "and re-read the data to verify that it is correct.\n\n"
+ "This is an *essential* feature ...\n\n"));
+ block = new_block(dev);
+ rec = new_record();
+ if (!rewind_dev(dev)) {
+ Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
+ goto bail_out;
+ }
+ rec->data = check_pool_memory_size(rec->data, block->buf_len);
+ rec->data_len = block->buf_len-100;
+ len = rec->data_len/sizeof(i);
+ for (i=1; i<=1000; i++) {
+ p = (int *)rec->data;
+ for (j=0; j<len; j++) {
+ *p++ = i;
+ }
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, _("Error writing record to block.\n"));
+ goto bail_out;
+ }
+ if (!write_block_to_dev(dcr)) {
+ Pmsg0(0, _("Error writing block to device.\n"));
+ goto bail_out;
+ }
+ }
+ Pmsg1(0, _("Wrote 1000 blocks of %d bytes.\n"), rec->data_len);
+ weofcmd();
+ for (i=1001; i<=2000; i++) {
+ p = (int *)rec->data;
+ for (j=0; j<len; j++) {
+ *p++ = i;
+ }
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, _("Error writing record to block.\n"));
+ goto bail_out;
+ }
+ if (!write_block_to_dev(dcr)) {
+ Pmsg0(0, _("Error writing block to device.\n"));
+ goto bail_out;
+ }
+ }
+ Pmsg1(0, _("Wrote 1000 blocks of %d bytes.\n"), rec->data_len);
+ weofcmd();
+ if (dev_cap(dev, CAP_TWOEOF)) {
+ weofcmd();
+ }
+ if (!rewind_dev(dev)) {
+ Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
+ goto bail_out;
+ } else {
+ Pmsg0(0, "Rewind OK.\n");
+ }
+ for (i=1; i<=2000; i++) {
+read_again:
+ if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (dev_state(dev, ST_EOF)) {
+ Pmsg0(-1, _("Got EOF on tape.\n"));
+ goto read_again;
+ }
+ Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ memset(rec->data, 0, rec->data_len);
+ if (!read_record_from_block(block, rec)) {
+ Pmsg1(0, _("Read record failed! ERR=%s\n"), strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ p = (int *)rec->data;
+ for (j=0; j<len; j++) {
+ if (*p != i) {
+ Pmsg3(0, _("Bad data in record. Expected %d, got %d at byte %d. Test failed!\n"),
+ i, *p, j);
+ goto bail_out;
+ }
+ p++;
+ }
+ if (i == 1000 || i == 2000) {
+ Pmsg0(-1, _("1000 blocks re-read correctly.\n"));
+ }
+ }
+ Pmsg0(-1, _("=== Test Succeeded. End Write, rewind, and re-read test ===\n\n"));
+ stat = 1;
+
+bail_out:
+ free_block(block);
+ free_record(rec);
+ return stat;
+}
+
+/*
+ * This test writes Bacula blocks to the tape in
+ * several files. It then rewinds the tape and attepts
+ * to read these blocks back checking the data.
+ */
+static int position_test()
+{
+ DEV_BLOCK *block;
+ DEV_RECORD *rec;
+ int stat = 0;
+ int len, i, j;
+ bool ok = true;
+ int recno = 0;
+ int file = 0, blk = 0;
+ int *p;
+
+ Pmsg0(-1, _("\n=== Write, rewind, and position test ===\n\n"
+ "I'm going to write 1000 records and an EOF\n"
+ "then write 1000 records and an EOF, then rewind,\n"
+ "and position to a few blocks and verify that it is correct.\n\n"
+ "This is an *essential* feature ...\n\n"));
+ block = new_block(dev);
+ rec = new_record();
+ if (!rewind_dev(dev)) {
+ Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
+ goto bail_out;
+ }
+ rec->data = check_pool_memory_size(rec->data, block->buf_len);
+ rec->data_len = block->buf_len-100;
+ len = rec->data_len/sizeof(i);
+ for (i=1; i<=1000; i++) {
+ p = (int *)rec->data;
+ for (j=0; j<len; j++) {
+ *p++ = i;
+ }
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, _("Error writing record to block.\n"));
+ goto bail_out;
+ }
+ if (!write_block_to_dev(dcr)) {
+ Pmsg0(0, _("Error writing block to device.\n"));
+ goto bail_out;
+ }
+ }
+ Pmsg1(0, _("Wrote 1000 blocks of %d bytes.\n"), rec->data_len);
+ weofcmd();
+ for (i=1001; i<=2000; i++) {
+ p = (int *)rec->data;
+ for (j=0; j<len; j++) {
+ *p++ = i;
+ }
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, _("Error writing record to block.\n"));
+ goto bail_out;
+ }
+ if (!write_block_to_dev(dcr)) {
+ Pmsg0(0, _("Error writing block to device.\n"));
+ goto bail_out;
+ }
+ }
+ Pmsg1(0, _("Wrote 1000 blocks of %d bytes.\n"), rec->data_len);
+ weofcmd();
+ if (dev_cap(dev, CAP_TWOEOF)) {
+ weofcmd();
+ }
+ if (!rewind_dev(dev)) {
+ Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
+ goto bail_out;
+ } else {
+ Pmsg0(0, "Rewind OK.\n");
+ }
+
+ while(ok) {
+ /* Set up next item to read based on where we are */
+ switch (recno) {
+ case 0:
+ recno = 5;
+ file = 0;
+ blk = 4;
+ break;
+ case 5:
+ recno = 201;
+ file = 0;
+ blk = 200;
+ break;
+ case 201:
+ recno = 1000;
+ file = 0;
+ blk = 999;
+ break;
+ case 1000:
+ recno = 1001;
+ file = 1;
+ blk = 0;
+ break;
+ case 1001:
+ recno = 1601;
+ file = 1;
+ blk = 600;
+ break;
+ case 1601:
+ recno = 2000;
+ file = 1;
+ blk = 999;
+ break;
+ case 2000:
+ ok = false;
+ continue;
+ }
+ Pmsg2(-1, "Reposition to file:block %d:%d\n", file, blk);
+ if (!reposition_dev(dev, file, blk)) {
+ Pmsg0(0, "Reposition error.\n");
+ goto bail_out;
+ }
+read_again:
+ if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (dev_state(dev, ST_EOF)) {
+ Pmsg0(-1, _("Got EOF on tape.\n"));
+ goto read_again;
+ }
+ Pmsg1(0, _("Read block failed! ERR=%s\n\n"), strerror(dev->dev_errno));
+ Pmsg0(0, _("This may be because the tape drive block size is not\n"
+ " set to variable blocking as normally used by Bacula.\n"
+ " Please see the Tape Testing chapter in the manual and \n"
+ " look for using mt with defblksize and setoptions\n"));
+ goto bail_out;
+ }
+ memset(rec->data, 0, rec->data_len);
+ if (!read_record_from_block(block, rec)) {
+ Pmsg1(0, _("Read record failed! ERR=%s\n"), strerror(dev->dev_errno));
+ goto bail_out;
+ }
+ p = (int *)rec->data;
+ for (j=0; j<len; j++) {
+ if (p[j] != recno) {
+ Pmsg3(0, _("Bad data in record. Expected %d, got %d at byte %d. Test failed!\n"),
+ recno, p[j], j);
+ goto bail_out;
+ }
+ }
+ Pmsg0(-1, _("Block re-read correctly.\n"));
+ }
+ Pmsg0(-1, _("=== Test Succeeded. End Write, rewind, and re-read test ===\n\n"));
+ stat = 1;
+
+bail_out:
+ free_block(block);
+ free_record(rec);
+ return stat;
+}
+
+
+
+