1 /*
2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /*
30 * Project: NDMJOB
31 * Ident: $Id: $
32 *
33 * Description:
34 *
35 *****************************************************************
36 *
37 * NDMP Elements of a test-tape session
38 *
39 * +-----+ ###########
40 * | Job |----># CONTROL #
41 * +-----+ # Agent #
42 * # #
43 * ###########
44 * | |
45 * | +---------------------+
46 * control | connections |
47 * V V
48 * ############ +-------+ #########
49 * # TAPE # | | # ROBOT #
50 * # Agent # | ROBOT |<-># Agent #
51 * # # |+-----+| # #
52 * # ======|DRIVE|| # #
53 * # # |+-----+| # #
54 * ############ +-------+ #########
55 *
56 ****************************************************************
57 */
58
59
60 #include "ndmagents.h"
61
62
63 #if !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && !defined(NDMOS_OPTION_NO_TEST_AGENTS)
64
65
66 extern int ndmca_tt_wrapper (struct ndm_session *sess,
67 int (*func)(struct ndm_session *sess));
68
69
70 extern int ndmca_op_test_tape (struct ndm_session *sess);
71 extern int ndmca_tt_openclose (struct ndm_session *sess);
72 extern int ndmca_tt_basic_getstate (struct ndm_session *sess);
73 extern int ndmca_tt_basic_write (struct ndm_session *sess);
74 extern int ndmca_tt_basic_read (struct ndm_session *sess);
75 extern int ndmca_tt_basic_write_and_read (struct ndm_session *sess);
76 extern int ndmca_tt_write (struct ndm_session *sess);
77 extern int ndmca_tt_read (struct ndm_session *sess);
78 extern int ndmca_tt_mtio (struct ndm_session *sess);
79
80 extern int ndmca_tt_check_fileno_recno (struct ndm_session *sess,
81 char *what, uint32_t file_num, uint32_t blockno,
82 char *note);
83
84 extern int ndmca_test_tape_open (struct ndm_session *sess,
85 ndmp9_error expect_err,
86 char *device, int mode);
87 extern int ndmca_test_tape_close (struct ndm_session *sess,
88 ndmp9_error expect_err);
89 extern int ndmca_test_tape_get_state (struct ndm_session *sess,
90 ndmp9_error expect_err);
91 extern int ndmca_test_tape_mtio (struct ndm_session *sess,
92 ndmp9_error expect_err,
93 ndmp9_tape_mtio_op op, uint32_t count, uint32_t *resid);
94 extern int ndmca_check_tape_mtio (struct ndm_session *sess,
95 ndmp9_error expect_err,
96 ndmp9_tape_mtio_op op, uint32_t count, uint32_t resid);
97 extern int ndmca_test_tape_write (struct ndm_session *sess,
98 ndmp9_error expect_err,
99 char *buf, unsigned count);
100 extern int ndmca_test_tape_read (struct ndm_session *sess,
101 ndmp9_error expect_err,
102 char *buf, unsigned count);
103 extern int ndmca_test_tape_read_2cnt (struct ndm_session *sess,
104 ndmp9_error expect_err,
105 char *buf, unsigned count, unsigned true_count);
106
107
108 struct series {
109 unsigned n_rec;
110 unsigned recsize;
111 };
112
113 struct series tt_series[] = {
114 { 1, 512 },
115 { 100, 1024 },
116 { 1, 512 },
117 { 100, 139 },
118 { 1, 512 },
119 { 99, 10240 },
120 { 1, 512 },
121 { 3, 32768 },
122 { 1, 512 },
123 { 0 }
124 };
125
126
127
128 int
ndmca_op_test_tape(struct ndm_session * sess)129 ndmca_op_test_tape (struct ndm_session *sess)
130 {
131 struct ndmconn * conn;
132 int (*save_call) (struct ndmconn *conn,
133 struct ndmp_xa_buf *xa);
134 int rc;
135
136 rc = ndmca_test_load_tape (sess);
137 if (rc) return rc;
138
139 conn = sess->plumb.tape;
140 save_call = conn->call;
141 conn->call = ndma_call_no_tattle;
142
143 if (rc == 0)
144 rc = ndmca_tt_wrapper (sess, ndmca_tt_openclose);
145 if (rc == 0)
146 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_getstate);
147 if (rc == 0)
148 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_write);
149 if (rc == 0)
150 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_read);
151 if (rc == 0)
152 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_write_and_read);
153 if (rc == 0)
154 rc = ndmca_tt_wrapper (sess, ndmca_tt_write);
155 if (rc == 0)
156 rc = ndmca_tt_wrapper (sess, ndmca_tt_read);
157 if (rc == 0)
158 rc = ndmca_tt_wrapper (sess, ndmca_tt_mtio);
159
160 ndmca_test_unload_tape (sess);
161
162 ndmca_test_done_series (sess, "test-tape");
163
164 conn->call = save_call;
165
166 return 0;
167 }
168
169 int
ndmca_tt_wrapper(struct ndm_session * sess,int (* func)(struct ndm_session * sess))170 ndmca_tt_wrapper (struct ndm_session *sess,
171 int (*func)(struct ndm_session *sess))
172 {
173 int rc;
174
175 rc = (*func)(sess);
176
177 if (rc != 0) {
178 ndmalogf (sess, "Test", 1, "Failure");
179 }
180
181 ndmca_test_done_phase (sess);
182
183 /* clean up mess */
184 ndmca_test_log_note (sess, 2, "Cleaning up...");
185
186 ndmca_tape_open (sess); /* Open the tape, OK if already opened */
187 ndmca_tape_mtio (sess, NDMP9_MTIO_REW, 1, 0);
188 rc = ndmca_tape_close (sess); /* close, collective error */
189 if (rc != 0) {
190 ndmca_test_log_note (sess, 0, "Cleaning up failed, quiting");
191 } else {
192 ndmca_test_log_note (sess, 2, "Cleaning up done");
193 }
194
195 return rc;
196 }
197
198
199 int
ndmca_tt_openclose(struct ndm_session * sess)200 ndmca_tt_openclose (struct ndm_session *sess)
201 {
202 int rc;
203
204 ndmca_test_phase (sess, "T-OC", "Tape Open/Close");
205
206 rc = ndmca_test_tape_close (sess, NDMP9_DEV_NOT_OPEN_ERR);
207 if (rc) return rc;
208
209 rc = ndmca_test_tape_open (sess, NDMP9_NO_DEVICE_ERR,
210 "bogus", NDMP9_TAPE_READ_MODE);
211 if (rc) return rc;
212
213 rc = ndmca_test_tape_open (sess, NDMP9_ILLEGAL_ARGS_ERR, 0, 123);
214 if (rc) return rc;
215
216 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
217 if (rc) return rc;
218
219 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
220 if (rc) return rc;
221
222 rc = ndmca_test_tape_open (sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
223 if (rc) return rc;
224
225 rc = ndmca_test_tape_open (sess, NDMP9_DEVICE_OPENED_ERR,
226 0, NDMP9_TAPE_READ_MODE);
227 if (rc) return rc;
228
229 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
230 if (rc) return rc;
231
232 return 0; /* pass */
233 }
234
235 int
ndmca_tt_basic_getstate(struct ndm_session * sess)236 ndmca_tt_basic_getstate (struct ndm_session *sess)
237 {
238 int rc;
239
240 ndmca_test_phase (sess, "T-BGS", "Tape Get State Basics");
241
242 rc = ndmca_test_tape_get_state (sess, NDMP9_DEV_NOT_OPEN_ERR);
243 if (rc) return rc;
244
245 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
246 if (rc) return rc;
247
248 rc = ndmca_test_tape_get_state (sess, NDMP9_NO_ERR);
249 if (rc) return rc;
250
251 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
252 if (rc) return rc;
253
254 return 0; /* pass */
255 }
256
257 /*
258 * Precedes tt_basic_read() so that we can make a "known" tape.
259 */
260 int
ndmca_tt_basic_write(struct ndm_session * sess)261 ndmca_tt_basic_write (struct ndm_session *sess)
262 {
263 int rc, ix;
264 char buf[1024];
265 ndmp9_error expect_errs[5];
266
267 ndmca_test_phase (sess, "T-BW", "Tape Write Basics");
268
269 rc = ndmca_test_tape_write (sess, NDMP9_DEV_NOT_OPEN_ERR, buf, 1024);
270 if (rc) return rc;
271
272 /*
273 * Write w/ read-only open mode
274 */
275 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
276 if (rc) return rc;
277
278 rc = ndmca_test_tape_write (sess, NDMP9_PERMISSION_ERR, buf, 1024);
279 if (rc) return rc;
280
281 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
282 if (rc) return rc;
283
284 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
285 if (rc) return rc;
286
287 /*
288 * Write w/ bogus lengths
289 */
290 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
291 if (rc) return rc;
292
293 /* OPEN Question: what does len==0 mean? */
294 /* write/len=0 MUST be NDMP[234]_NO_ERR or NDMP[234]_ILLEGAL_ARGS */
295 /* write/len=0 MUST be NDMP4_NO_ERR */
296 ix = 0;
297 if (sess->plumb.tape->protocol_version < 5) {
298 expect_errs[ix++] = NDMP9_ILLEGAL_ARGS_ERR;
299 }
300 expect_errs[ix++] = NDMP9_NO_ERR;
301 expect_errs[ix++] = -1;
302
303 rc = ndmca_tape_write (sess, buf, 0);
304
305 rc = ndmca_test_check_expect_errs (sess->plumb.tape, rc, expect_errs);
306 if (rc) return rc;
307
308 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
309 if (rc) return rc;
310
311 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
312 if (rc) return rc;
313
314 /*
315 * TODO: bogus length
316 */
317
318 /*
319 * Write works
320 */
321 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
322 if (rc) return rc;
323
324 rc = ndmca_test_tape_write (sess, NDMP9_NO_ERR, buf, 1024);
325 if (rc) return rc;
326
327 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_EOF, 1, 0);
328 if (rc) return rc;
329
330 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
331 if (rc) return rc;
332
333 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
334 if (rc) return rc;
335
336 return 0; /* pass */
337 }
338
339
340 /*
341 * Assumes tt_basic_write() passed. Uses resulting tape.
342 */
343
344 int
ndmca_tt_basic_read(struct ndm_session * sess)345 ndmca_tt_basic_read (struct ndm_session *sess)
346 {
347 int rc, ix;
348 char buf[2048];
349 ndmp9_error expect_errs[5];
350
351 ndmca_test_phase (sess, "T-BR", "Tape Read Basics");
352
353 rc = ndmca_test_tape_read (sess, NDMP9_DEV_NOT_OPEN_ERR, buf, 1024);
354 if (rc) return rc;
355
356
357 /*
358 * Read w/ bogus lengths -- mode=READ_MODE
359 */
360 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
361 if (rc) return rc;
362
363 /* read/len=0 MUST be NDMP[23]_NO_ERR or NDMP[23]_ILLEGAL_ARGS */
364 /* read/len=0 MUST be NDMP4_NO_ERR */
365 ix = 0;
366 if (sess->plumb.tape->protocol_version < 4) {
367 expect_errs[ix++] = NDMP9_ILLEGAL_ARGS_ERR;
368 }
369 expect_errs[ix++] = NDMP9_NO_ERR;
370 expect_errs[ix++] = -1;
371
372 rc = ndmca_tape_read (sess, buf, 0);
373
374 rc = ndmca_test_check_expect_errs (sess->plumb.tape, rc, expect_errs);
375 if (rc) return rc;
376
377 rc = ndmca_test_tape_read(sess,NDMP9_ILLEGAL_ARGS_ERR,buf,0x80000000);
378 if (rc) return rc;
379
380 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
381 if (rc) return rc;
382
383 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
384 if (rc) return rc;
385
386 /*
387 * Read works -- mode=WRITE_MODE (just to mix it up)
388 */
389 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
390 if (rc) return rc;
391
392 rc = ndmca_test_tape_read (sess, NDMP9_NO_ERR, buf, 1024);
393 if (rc) return rc;
394
395 rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
396 if (rc) return rc;
397
398 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
399 if (rc) return rc;
400
401 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
402 if (rc) return rc;
403
404
405 /*
406 * Read works w/ oversize -- mode=READ_MODE (just to mix it up)
407 */
408 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
409 if (rc) return rc;
410
411 rc = ndmca_test_tape_read_2cnt (sess, NDMP9_NO_ERR, buf, 2048, 1024);
412 if (rc) return rc;
413
414 rc = ndmca_test_tape_read_2cnt (sess, NDMP9_EOF_ERR, buf, 2048, 1024);
415 if (rc) return rc;
416
417 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
418 if (rc) return rc;
419
420 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
421 if (rc) return rc;
422
423
424 /*
425 * Read works w/ undersize -- mode=READ_MODE (just to mix it up)
426 */
427 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
428 if (rc) return rc;
429
430 rc = ndmca_test_tape_read_2cnt (sess, NDMP9_NO_ERR, buf, 512, 512);
431 if (rc) return rc;
432
433 rc = ndmca_test_tape_read_2cnt (sess, NDMP9_EOF_ERR, buf, 512, 512);
434 if (rc) return rc;
435
436 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
437 if (rc) return rc;
438
439 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
440 if (rc) return rc;
441
442 return 0; /* pass */
443 }
444
445 #define CHECK_FILENO_RECNO(WHAT,FILENO,RECNO) { \
446 what = WHAT; \
447 rc = ndmca_tt_check_fileno_recno (sess, \
448 WHAT, FILENO, RECNO, note); \
449 if (rc) return -1; \
450 }
451
452 /*
453 * Assumes tt_basic_read() and tt_basic_write() have been done verifying
454 * READ and WRITE operations work...
455 */
456 int
ndmca_tt_basic_write_and_read(struct ndm_session * sess)457 ndmca_tt_basic_write_and_read (struct ndm_session *sess)
458 {
459 int rc, i, f, pass;
460 char buf[64*1024];
461 char *p;
462
463 ndmca_test_phase (sess, "T-BWR", "Tape Write and Read Basics");
464
465 /*
466 * check EOF and EOM by rewinding and putting on 1 EOF mark
467 */
468 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
469 if (rc) return rc;
470
471 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
472 if (rc) return rc;
473
474 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSR, 100, 100);
475 if (rc) return rc;
476
477 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSF, 100, 100);
478 if (rc) return rc;
479
480 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_EOF, 1, 0);
481 if (rc) return rc;
482
483 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSF, 100, 99);
484 if (rc) return rc;
485
486 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSF, 100, 99);
487 if (rc) return rc;
488
489 /* we are at EOM */
490 if (sess->plumb.tape->protocol_version < 4) {
491 rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, sizeof(buf));
492 if (rc) return rc;
493
494 /* check it again */
495 rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
496 if (rc) return rc;
497
498 } else {
499 rc = ndmca_test_tape_read (sess, NDMP9_EOM_ERR, buf, sizeof(buf));
500 if (rc) return rc;
501
502 /* check it again */
503 rc = ndmca_test_tape_read (sess, NDMP9_EOM_ERR, buf, 1024);
504 if (rc) return rc;
505 }
506
507 /* rewind and place 1 record in tape -- no EOF marker by seeking */
508
509 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
510 if (rc) return rc;
511
512 rc = ndmca_test_tape_write (sess, NDMP9_NO_ERR, buf, 512);
513 if (rc) return rc;
514
515 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSR, 100, 99);
516 if (rc) return rc;
517
518 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSR, 100, 99);
519 if (rc) return rc;
520
521 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSR, 100, 100);
522 if (rc) return rc;
523
524 rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSF, 100, 100);
525 if (rc) return rc;
526
527 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
528 if (rc) return rc;
529
530 /*
531 * perform tape label type processing with positioning ops
532 */
533 for(pass = 0; pass < 2; pass++) {
534 /*
535 * open the tape and write 1 record and close it
536 */
537 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
538 if (rc) return rc;
539
540 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
541 if (rc) return rc;
542
543 for(p = buf, i = 0; i < 1024; i++, p++)
544 *p = ((i - 4) & 0xff);
545
546 rc = ndmca_test_tape_write (sess, NDMP9_NO_ERR, buf, 1024);
547 if (rc) return rc;
548
549 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_EOF, 1, 0);
550 if (rc) return rc;
551
552 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
553 if (rc) return rc;
554
555 /*
556 * open the tape and read it
557 */
558 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
559 if (rc) return rc;
560
561 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
562 if (rc) return rc;
563
564 if (pass == 1)
565 rc = ndmca_test_tape_read_2cnt (sess, NDMP9_NO_ERR, buf, sizeof(buf), 1024);
566 else
567 rc = ndmca_test_tape_read (sess, NDMP9_NO_ERR, buf, 1024);
568 if (rc) return rc;
569
570 for(p = buf, f = i = 0;
571 f < 64 && i < 1024;
572 i++, p++)
573 if (*p != ((i - 4) & 0xff)) {
574 char tmp[80];
575 snprintf (tmp, sizeof(tmp),
576 "%d: 0x%x => 0x%x",
577 i, ((i - 4) & 0xff), *p);
578 ndmalogf (sess, "DATA", 6, tmp);
579 f++;
580 }
581 if (f > 0) {
582 ndmca_test_fail (sess, "Failed compare");
583 return -1;
584 }
585
586 rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
587 if (rc) return rc;
588
589 /* check EOM */
590 if (sess->plumb.tape->protocol_version < 4) {
591 rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
592 if (rc) return rc;
593 } else {
594 /* skip over filemark */
595 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, 1, 0);
596 /* read EOM */
597 rc = ndmca_test_tape_read (sess, NDMP9_EOM_ERR, buf, 1024);
598 if (rc) return rc;
599 }
600
601 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
602 if (rc) return rc;
603 }
604
605 return 0; /* pass */
606 }
607
608 /*
609 * Precedes tt_read() so that we can make a "known" tape.
610 */
611 int
ndmca_tt_write(struct ndm_session * sess)612 ndmca_tt_write (struct ndm_session *sess)
613 {
614 int rc;
615 unsigned n_rec;
616 unsigned recsize;
617 unsigned fileno, recno;
618 char * what;
619 char note[128];
620 char buf[64*1024];
621
622 ndmca_test_phase (sess, "T-WRITE", "Tape Write Series");
623
624 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
625 if (rc) return rc;
626
627 for (fileno = 0; tt_series[fileno].n_rec > 0; fileno++) {
628 n_rec = tt_series[fileno].n_rec;
629 recsize = tt_series[fileno].recsize;
630
631 snprintf (note, sizeof(note), "Write tape file %d", fileno+1);
632 ndmca_test_open (sess, note, 0);
633
634 snprintf (note, sizeof(note), "file #%d, %d records, %d bytes/rec",
635 fileno+1, n_rec, recsize);
636 ndmca_test_log_note (sess, 2, note);
637
638 for (recno = 0; recno < n_rec; recno++) {
639 ndmca_test_fill_data (buf, recsize, recno, fileno);
640
641 what = "write";
642 rc = ndmca_tape_write (sess, buf, recsize);
643 if (rc) goto fail;
644
645 CHECK_FILENO_RECNO ("write", fileno, recno+1);
646 }
647
648 what = "write filemark";
649 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_EOF, 1, 0);
650 if (rc) goto fail;
651
652 CHECK_FILENO_RECNO ("wfm", fileno+1, 0);
653
654 /* no test calls so the file operation is the test */
655 snprintf (buf, sizeof(buf), "Passed tape write %s", note);
656 ndmca_test_log_step (sess, 2, buf);
657 }
658
659 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
660 if (rc) return rc;
661
662 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
663 if (rc) return rc;
664
665 return 0;
666
667 fail:
668 snprintf (buf, sizeof(buf), "Failed %s recno=%d; %s", what, recno, note);
669 ndmca_test_fail (sess, buf);
670 return -1;
671 }
672
673
674
675
676 /*
677 * Assumes tt_write() passed
678 */
679 int
ndmca_tt_read(struct ndm_session * sess)680 ndmca_tt_read (struct ndm_session *sess)
681 {
682 int rc;
683 unsigned n_rec;
684 unsigned recsize;
685 unsigned fileno, recno;
686 char * what;
687 char note[128];
688 char pbuf[64*1024];
689 char buf[64*1024];
690
691 ndmca_test_phase (sess, "T-READ", "Tape Read Series");
692
693 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
694 if (rc) return rc;
695
696 for (fileno = 0; tt_series[fileno].n_rec > 0; fileno++) {
697 n_rec = tt_series[fileno].n_rec;
698 recsize = tt_series[fileno].recsize;
699
700 snprintf (note, sizeof(note), "Read tape file %d", fileno+1);
701 ndmca_test_open (sess, note, 0);
702
703 snprintf (note, sizeof(note), "file #%d, %d records, %d bytes/rec",
704 fileno+1, n_rec, recsize);
705 ndmca_test_log_note (sess, 2, note);
706
707 for (recno = 0; recno < n_rec; recno++) {
708 ndmca_test_fill_data (pbuf, recsize, recno, fileno);
709
710 what = "read";
711 rc = ndmca_tape_read (sess, buf, recsize);
712 if (rc) goto fail;
713
714 CHECK_FILENO_RECNO ("read", fileno, recno+1);
715
716 what = "compare";
717 #if 0
718 if (bcmp (buf, pbuf, recsize) != 0)
719 goto fail;
720 #else
721 if (bcmp (buf, pbuf, recsize) != 0) {
722 unsigned char *expect_p = (unsigned char *)pbuf;
723 unsigned char *got_p = (unsigned char *)buf;
724 unsigned int i, f;
725 for(f = i = 0;
726 f < 64 && i < recsize;
727 i++, expect_p++, got_p++) {
728 if (*expect_p != *got_p) {
729 char tmp[80];
730 snprintf (tmp, sizeof(tmp),
731 "%d: 0x%x => 0x%x",
732 i, *expect_p, *got_p);
733 ndmalogf (sess, "DATA", 6, tmp);
734 f++;
735 }
736 }
737 goto fail;
738 }
739 #endif
740 }
741
742 what = "eof read";
743 rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, recsize);
744 if (rc) goto fail;
745
746 if (sess->plumb.tape->protocol_version > 3) {
747 CHECK_FILENO_RECNO ("eof", fileno, -1);
748
749 what = "skip filemark";
750 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, 1, 0);
751 if (rc) goto fail;
752
753 CHECK_FILENO_RECNO ("skip", fileno+1, 0);
754 } else {
755 CHECK_FILENO_RECNO ("eof", fileno+1, 0);
756 }
757
758 snprintf (buf, sizeof(buf), "Passed tape read %s", note);
759 ndmca_test_log_step (sess, 2, buf);
760 }
761
762 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
763 if (rc) return rc;
764
765 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
766 if (rc) return rc;
767
768 return 0;
769
770 fail:
771 snprintf (buf, sizeof(buf), "Failed %s recno=%d; %s", what, recno, note);
772 ndmca_test_fail (sess, buf);
773 return -1;
774 }
775
776
777 /*
778 * Assumes tt_write() passed
779 */
780 int
ndmca_tt_mtio(struct ndm_session * sess)781 ndmca_tt_mtio (struct ndm_session *sess)
782 {
783 int rc;
784 unsigned n_rec;
785 unsigned recsize;
786 unsigned fileno, recno;
787 uint32_t count, resid;
788 char * what;
789 char note[128];
790 char pbuf[64*1024];
791 char buf[64*1024];
792
793 ndmca_test_phase (sess, "T-MTIO", "Tape MTIO");
794
795 rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
796 if (rc) return rc;
797
798 rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
799 if (rc) return rc;
800
801 for (fileno = 0; tt_series[fileno].n_rec > 0; fileno++) {
802 n_rec = tt_series[fileno].n_rec;
803 recsize = tt_series[fileno].recsize;
804
805 snprintf (note, sizeof(note), "Seek around tape file %d", fileno+1);
806 ndmca_test_open (sess, note, 0);
807
808 snprintf (note, sizeof(note), "file #%d, %d records, %d bytes/rec",
809 fileno+1, n_rec, recsize);
810 ndmca_test_log_note (sess, 2, note);
811
812 what = "rew";
813 count = 1;
814 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_REW, count, &resid);
815 if (rc) goto fail;
816
817 what = "rew resid";
818 if (resid != 0)
819 goto fail;
820
821 CHECK_FILENO_RECNO ("rew", 0, 0);
822
823
824 what = "fsf(n)";
825 count = fileno;
826 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, count, &resid);
827 if (rc) goto fail;
828
829 what = "fsf(n) resid";
830 if (resid != 0)
831 goto fail;
832
833 CHECK_FILENO_RECNO ("fsf", fileno, 0);
834
835
836 what = "fsr(1m)";
837 count = 1000000;
838 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSR, count, &resid);
839 if (rc) goto fail;
840
841 what = "fsr(1m) resid";
842 if (n_rec + resid != count)
843 goto fail;
844
845 if (sess->plumb.tape->protocol_version < 4) {
846 CHECK_FILENO_RECNO ("fsr(1m)", fileno + 1, 0);
847
848 what = "bsf 1 after fsr(1m)";
849 count = 1;
850 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_BSF, count, 0);
851 if (rc) goto fail;
852
853 CHECK_FILENO_RECNO (what, fileno, -1);
854
855 recno = n_rec;
856 } else {
857 /* EOT side of EOF marker */
858 recno = n_rec;
859 CHECK_FILENO_RECNO ("fsr(1m)", fileno, recno);
860 }
861
862 what = "bsr(1m)";
863 count = 1000000;
864 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_BSR, count, &resid);
865 if (rc) goto fail;
866
867 what = "bsr(1m) resid";
868 if (n_rec + resid != count)
869 goto fail;
870
871 if ((fileno > 0) && (sess->plumb.tape->protocol_version < 4)) {
872 /* at BOT side of EOF marker (not BOT) */
873 CHECK_FILENO_RECNO ("bsr(1m)", fileno - 1, -1);
874
875 what = "fsf 1 after bsr(1m)";
876 count = 1;
877 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, count, 0);
878 if (rc) goto fail;
879 }
880
881 recno = 0;
882 CHECK_FILENO_RECNO ("bsr(1m)", fileno, recno);
883
884 what = "fsr(0)";
885 count = 0;
886 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSR, count, &resid);
887 if (rc) goto fail;
888
889 what = "fsr(0) resid";
890 if (resid != 0)
891 goto fail;
892
893 recno = 0;
894 CHECK_FILENO_RECNO ("fsr(0)", fileno, recno);
895
896
897 what = "fsr(x)";
898 count = n_rec / 2;
899 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSR, count, &resid);
900 if (rc) goto fail;
901
902 what = "fsr(x) resid";
903 if (resid != 0)
904 goto fail;
905
906 recno = n_rec / 2;
907 CHECK_FILENO_RECNO ("fsr(x)", fileno, recno);
908
909 what = "fsr(x) read";
910 rc = ndmca_tape_read (sess, buf, recsize);
911 if (rc) goto fail;
912
913 what = "fsr(x) compare";
914 ndmca_test_fill_data (pbuf, recsize, recno, fileno);
915 if (bcmp (buf, pbuf, recsize) != 0)
916 goto fail;
917
918 recno++; /* caused by tape_read */
919
920 if (recno > 1) {
921 what = "bsr(2)";
922 count = 2;
923 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_BSR,
924 count, &resid);
925 if (rc) goto fail;
926
927 what = "bsr(2) resid";
928 if (resid != 0)
929 goto fail;
930
931 recno -= count;
932 CHECK_FILENO_RECNO ("bsr(2)", fileno, recno);
933
934 what = "bsr(2) read";
935 rc = ndmca_tape_read (sess, buf, recsize);
936 if (rc) goto fail;
937
938 what = "bsr(2) compare";
939 ndmca_test_fill_data (pbuf, recsize, recno, fileno);
940 if (bcmp (buf, pbuf, recsize) != 0)
941 goto fail;
942 }
943
944 snprintf (buf, sizeof(buf), "Passed %s", note);
945 ndmca_test_log_step (sess, 2, buf);
946 }
947
948 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
949 if (rc) return rc;
950
951 return 0;
952
953 fail:
954 snprintf (buf, sizeof(buf), "Failed %s: %s", what, note);
955 ndmca_test_fail (sess, buf);
956 return -1;
957 }
958
959
960
961 /*
962 * Check the tape_state accurately reflects position
963 */
964
965 int
ndmca_tt_check_fileno_recno(struct ndm_session * sess,char * what,uint32_t file_num,uint32_t blockno,char * note)966 ndmca_tt_check_fileno_recno (struct ndm_session *sess,
967 char *what, uint32_t file_num, uint32_t blockno, char *note)
968 {
969 struct ndm_control_agent *ca = sess->control_acb;
970 struct ndmp9_tape_get_state_reply *ts = 0;
971 char buf[100];
972 int rc;
973 char * oper;
974
975 oper ="get_state";
976 rc = ndmca_tape_get_state (sess);
977 if (rc) goto fail;
978
979 ts = &ca->tape_state;
980
981 oper = "check file_num";
982 if (ts->file_num.value != file_num)
983 goto fail;
984
985 oper = "check blockno";
986 if ((ts->blockno.value != blockno) && (ts->blockno.value != NDMP9_INVALID_U_LONG))
987 goto fail;
988
989 return 0;
990
991 fail:
992 snprintf (buf, sizeof(buf), "Failed %s while testing %s", oper, what);
993 ndmca_test_log_note (sess, 1, buf);
994 if (ts) {
995 snprintf (buf, sizeof(buf), " expect file_num=%ld got file_num=%ld",
996 (long)file_num, (long)ts->file_num.value);
997 ndmca_test_log_note (sess, 1, buf);
998
999 snprintf (buf, sizeof(buf), " expect blockno=%ld got blockno=%ld",
1000 (long)blockno, (long)ts->blockno.value);
1001 ndmca_test_log_note (sess, 1, buf);
1002 }
1003
1004 snprintf (buf, sizeof(buf), " note: %s", note);
1005 ndmca_test_fail (sess, buf);
1006 return -1;
1007 }
1008
1009
1010
1011
1012 #define NDMTEST_CALL(CONN) ndmca_test_call(CONN, xa, expect_err);
1013
1014
1015 int
ndmca_test_tape_open(struct ndm_session * sess,ndmp9_error expect_err,char * device,int mode)1016 ndmca_test_tape_open (struct ndm_session *sess, ndmp9_error expect_err,
1017 char *device, int mode)
1018 {
1019 struct ndmconn * conn = sess->plumb.tape;
1020 struct ndm_control_agent *ca = sess->control_acb;
1021 int rc;
1022
1023 /* close previous test if there is one */
1024 ndmca_test_close (sess);
1025
1026 switch (conn->protocol_version) {
1027 default: return -1234;
1028
1029 #ifndef NDMOS_OPTION_NO_NDMP2
1030 case NDMP2VER:
1031 NDMC_WITH (ndmp2_tape_open, NDMP2VER)
1032 if (device)
1033 request->device.name = device;
1034 else
1035 request->device.name = ca->job.tape_device;
1036 if (mode != -1)
1037 request->mode = mode;
1038 else
1039 request->mode = ca->tape_mode;
1040 rc = NDMTEST_CALL(conn);
1041 NDMC_ENDWITH
1042 break;
1043 #endif /* !NDMOS_OPTION_NO_NDMP2 */
1044 #ifndef NDMOS_OPTION_NO_NDMP3
1045 case NDMP3VER:
1046 NDMC_WITH (ndmp3_tape_open, NDMP3VER)
1047 if (device)
1048 request->device = device;
1049 else
1050 request->device = ca->job.tape_device;
1051 if (mode != -1)
1052 request->mode = mode;
1053 else
1054 request->mode = ca->tape_mode;
1055 rc = NDMTEST_CALL(conn);
1056 NDMC_ENDWITH
1057 break;
1058 #endif /* !NDMOS_OPTION_NO_NDMP3 */
1059 #ifndef NDMOS_OPTION_NO_NDMP4
1060 case NDMP4VER:
1061 NDMC_WITH (ndmp4_tape_open, NDMP4VER)
1062 if (device)
1063 request->device = device;
1064 else
1065 request->device = ca->job.tape_device;
1066 if (mode != -1)
1067 request->mode = mode;
1068 else
1069 request->mode = ca->tape_mode;
1070 rc = NDMTEST_CALL(conn);
1071 NDMC_ENDWITH
1072 break;
1073 #endif /* !NDMOS_OPTION_NO_NDMP4 */
1074 }
1075
1076 return rc;
1077 }
1078
1079 int
ndmca_test_tape_close(struct ndm_session * sess,ndmp9_error expect_err)1080 ndmca_test_tape_close (struct ndm_session *sess, ndmp9_error expect_err)
1081 {
1082 struct ndmconn * conn = sess->plumb.tape;
1083 int rc;
1084
1085 /* close previous test if there is one */
1086 ndmca_test_close (sess);
1087
1088 rc = ndmca_tape_close (sess);
1089
1090 rc = ndmca_test_check_expect (conn, rc, expect_err);
1091
1092 return rc;
1093 }
1094
1095 int
ndmca_test_tape_get_state(struct ndm_session * sess,ndmp9_error expect_err)1096 ndmca_test_tape_get_state (struct ndm_session *sess, ndmp9_error expect_err)
1097 {
1098 struct ndmconn * conn = sess->plumb.tape;
1099 int rc;
1100
1101 /* close previous test if there is one */
1102 ndmca_test_close (sess);
1103
1104 rc = ndmca_tape_get_state (sess);
1105
1106 rc = ndmca_test_check_expect (conn, rc, expect_err);
1107
1108 return rc;
1109 }
1110
1111 int
ndmca_test_tape_mtio(struct ndm_session * sess,ndmp9_error expect_err,ndmp9_tape_mtio_op op,uint32_t count,uint32_t * resid)1112 ndmca_test_tape_mtio (struct ndm_session *sess, ndmp9_error expect_err,
1113 ndmp9_tape_mtio_op op, uint32_t count, uint32_t *resid)
1114 {
1115 struct ndmconn * conn = sess->plumb.tape;
1116 int rc;
1117
1118 /* close previous test if there is one */
1119 ndmca_test_close (sess);
1120
1121 rc = ndmca_tape_mtio (sess, op, count, resid);
1122
1123 rc = ndmca_test_check_expect (conn, rc, expect_err);
1124
1125 return rc;
1126 }
1127
1128 int
ndmca_check_tape_mtio(struct ndm_session * sess,ndmp9_error expect_err,ndmp9_tape_mtio_op op,uint32_t count,uint32_t resid)1129 ndmca_check_tape_mtio (struct ndm_session *sess, ndmp9_error expect_err,
1130 ndmp9_tape_mtio_op op, uint32_t count, uint32_t resid)
1131 {
1132 struct ndmconn * conn = sess->plumb.tape;
1133 uint32_t got_resid;
1134 int rc;
1135
1136 /* close previous test if there is one */
1137 ndmca_test_close (sess);
1138
1139 got_resid = ~resid;
1140
1141 rc = ndmca_tape_mtio (sess, op, count, &got_resid);
1142
1143 rc = ndmca_test_check_expect (conn, rc, expect_err);
1144 if (rc) return rc;
1145
1146 if (resid != got_resid) {
1147 char tmp[128];
1148 snprintf (tmp, sizeof(tmp),
1149 "Residual incorrect, got %lu expected %lu",
1150 got_resid,
1151 resid);
1152 ndmca_test_fail (sess, tmp);
1153 return -1;
1154 }
1155
1156 return rc;
1157 }
1158
1159
1160 int
ndmca_test_tape_write(struct ndm_session * sess,ndmp9_error expect_err,char * buf,unsigned count)1161 ndmca_test_tape_write (struct ndm_session *sess, ndmp9_error expect_err,
1162 char *buf, unsigned count)
1163 {
1164 struct ndmconn * conn = sess->plumb.tape;
1165 int rc;
1166
1167 /* close previous test if there is one */
1168 ndmca_test_close (sess);
1169
1170 rc = ndmca_tape_write (sess, buf, count);
1171
1172 rc = ndmca_test_check_expect (conn, rc, expect_err);
1173
1174 return rc;
1175 }
1176
1177 int
ndmca_test_tape_read(struct ndm_session * sess,ndmp9_error expect_err,char * buf,unsigned count)1178 ndmca_test_tape_read (struct ndm_session *sess, ndmp9_error expect_err,
1179 char *buf, unsigned count)
1180 {
1181 struct ndmconn * conn = sess->plumb.tape;
1182 int rc;
1183
1184 /* close previous test if there is one */
1185 ndmca_test_close (sess);
1186
1187 rc = ndmca_tape_read (sess, buf, count);
1188
1189 rc = ndmca_test_check_expect (conn, rc, expect_err);
1190
1191 return rc;
1192 }
1193
1194 int
ndmca_test_tape_read_2cnt(struct ndm_session * sess,ndmp9_error expect_err,char * buf,unsigned count,unsigned true_count)1195 ndmca_test_tape_read_2cnt (struct ndm_session *sess, ndmp9_error expect_err,
1196 char *buf, unsigned count, unsigned true_count)
1197 {
1198 struct ndmconn * conn = sess->plumb.tape;
1199 int rc;
1200
1201 /* close previous test if there is one */
1202 ndmca_test_close (sess);
1203
1204 switch (conn->protocol_version) {
1205 default: return -1234;
1206
1207 #ifndef NDMOS_OPTION_NO_NDMP2
1208 case NDMP2VER:
1209 NDMC_WITH(ndmp2_tape_read, NDMP2VER)
1210 request->count = count;
1211 rc = NDMTEST_CALL(conn);
1212 if (rc == 0 && expect_err == NDMP9_NO_ERR) {
1213 if (reply->data_in.data_in_len == true_count) {
1214 bcopy (reply->data_in.data_in_val,
1215 buf, true_count);
1216 } else {
1217 rc = -1;
1218 }
1219 }
1220 NDMC_FREE_REPLY();
1221 NDMC_ENDWITH
1222 break;
1223 #endif /* !NDMOS_OPTION_NO_NDMP2 */
1224 #ifndef NDMOS_OPTION_NO_NDMP3
1225 case NDMP3VER:
1226 NDMC_WITH(ndmp3_tape_read, NDMP3VER)
1227 request->count = count;
1228 rc = NDMTEST_CALL(conn);
1229 if (rc == 0 && expect_err == NDMP9_NO_ERR) {
1230 if (reply->data_in.data_in_len == true_count) {
1231 bcopy (reply->data_in.data_in_val,
1232 buf, true_count);
1233 } else {
1234 rc = -1;
1235 }
1236 }
1237 NDMC_FREE_REPLY();
1238 NDMC_ENDWITH
1239 break;
1240 #endif /* !NDMOS_OPTION_NO_NDMP3 */
1241 #ifndef NDMOS_OPTION_NO_NDMP4
1242 case NDMP4VER:
1243 NDMC_WITH(ndmp4_tape_read, NDMP4VER)
1244 request->count = count;
1245 rc = NDMTEST_CALL(conn);
1246 if (rc == 0 && expect_err == NDMP9_NO_ERR) {
1247 if (reply->data_in.data_in_len == true_count) {
1248 bcopy (reply->data_in.data_in_val,
1249 buf, true_count);
1250 } else {
1251 rc = -1;
1252 }
1253 }
1254 NDMC_FREE_REPLY();
1255 NDMC_ENDWITH
1256 break;
1257 #endif /* !NDMOS_OPTION_NO_NDMP4 */
1258 }
1259
1260 return rc;
1261 }
1262 #endif /* !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && !defined(NDMOS_OPTION_NO_TEST_AGENTS) */
1263