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