2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
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.
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
35 *****************************************************************
37 * NDMP Elements of a test-mover session
40 * | Job |----># CONTROL #
45 * #=============# | +---------------------+
47 * CONTROL # control | connections |
49 * DATA side of # ############ +-------+ #########
50 * image stream # # TAPE # | | # ROBOT #
51 * # # Agent # | ROBOT |<-># Agent #
52 * # image # +------+ # |+-----+| # #
53 * #==============|mover |=====|DRIVE|| # #
54 * stream # +------+ # |+-----+| # #
55 * ############ +-------+ #########
57 ****************************************************************
62 #include "ndmagents.h"
65 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
68 extern int ndmca_tm_wrapper (struct ndm_session *sess,
69 int (*func)(struct ndm_session *sess));
72 extern int ndmca_op_test_mover (struct ndm_session *sess);
73 extern int ndmca_tm_idle (struct ndm_session *sess);
75 extern int ndmca_tm_listen (struct ndm_session *sess);
76 extern int ndmca_tm_listen_subr (struct ndm_session *sess,
77 ndmp9_error expect_err,
78 ndmp9_addr_type addr_type,
79 ndmp9_mover_mode mode);
80 extern int ndmca_test_check_mover_state (struct ndm_session *sess,
81 ndmp9_mover_state expected, int reason);
82 extern int ndmca_test_mover_get_state (struct ndm_session *sess,
83 ndmp9_error expect_err);
84 extern int ndmca_test_mover_listen (struct ndm_session *sess,
85 ndmp9_error expect_err,
86 ndmp9_addr_type addr_type,
87 ndmp9_mover_mode mode);
88 extern int ndmca_test_mover_continue (struct ndm_session *sess,
89 ndmp9_error expect_err);
90 extern int ndmca_test_mover_abort (struct ndm_session *sess,
91 ndmp9_error expect_err);
92 extern int ndmca_test_mover_stop (struct ndm_session *sess,
93 ndmp9_error expect_err);
94 extern int ndmca_test_mover_set_window (struct ndm_session *sess,
95 ndmp9_error expect_err,
96 unsigned long long offset,
97 unsigned long long length);
98 extern int ndmca_test_mover_read (struct ndm_session *sess,
99 ndmp9_error expect_err,
100 unsigned long long offset,
101 unsigned long long length);
102 extern int ndmca_test_mover_close (struct ndm_session *sess,
103 ndmp9_error expect_err);
104 extern int ndmca_test_mover_set_record_size (struct ndm_session *sess,
105 ndmp9_error expect_err);
114 struct series tm_series[] = {
129 ndmca_op_test_mover (struct ndm_session *sess)
131 struct ndmconn * conn;
132 int (*save_call) (struct ndmconn *conn,
133 struct ndmp_xa_buf *xa);
135 struct ndm_control_agent *ca = &sess->control_acb;
137 if (sess->control_acb.job.data_agent.conn_type != NDMCONN_TYPE_NONE) {
139 * Sometimes needed to aid resident tape agent test
141 rc = ndmca_connect_data_agent (sess);
143 ndmconn_destruct (sess->plumb.data);
148 rc = ndmca_test_load_tape (sess);
151 conn = sess->plumb.tape;
152 save_call = conn->call;
153 conn->call = ndma_call_no_tattle;
155 /* perform query to find out about TCP and LOCAL support */
156 rc = ndmca_test_query_conn_types (sess, conn);
159 rc = ndmca_tm_wrapper (sess, ndmca_tm_idle);
160 rc = ndmca_tm_wrapper (sess, ndmca_tm_listen);
162 ndmca_test_unload_tape (sess);
164 ndmca_test_done_series (sess, "test-mover");
166 ca = &sess->control_acb;
167 if (ca->has_tcp_addr && ca->has_local_addr) {
168 ndmalogf (sess, "TEST", 0, "LOCAL and TCP addressing tested.");
169 } else if (ca->has_tcp_addr) {
170 ndmalogf (sess, "TEST", 0, "TCP addressing ONLY tested.");
171 } else if (ca->has_local_addr) {
172 ndmalogf (sess, "TEST", 0, "LOCAL addressing ONLY tested.");
174 ndmalogf (sess, "TEST", 0, "Neither TCP or LOCAL addressing tested.");
181 ndmca_tm_wrapper (struct ndm_session *sess,
182 int (*func)(struct ndm_session *sess))
189 ndmalogf (sess, "Test", 1, "Failure");
192 ndmca_test_done_phase (sess);
195 ndmca_test_log_note (sess, 2, "Cleaning up...");
197 ndmca_tape_open (sess); /* Open the tape, OK if already opened */
198 ndmca_tape_mtio (sess, NDMP9_MTIO_REW, 1, 0);
199 rc = ndmca_tape_close (sess); /* close, collective error */
201 ndmca_test_log_note (sess, 0, "Cleaning up failed, quiting");
203 ndmca_test_log_note (sess, 2, "Cleaning up done");
210 ndmca_tm_idle (struct ndm_session *sess)
214 ndmca_test_phase (sess, "M-IDLE", "Mover IDLE State Series");
216 rc = ndmca_test_check_mover_state (sess, NDMP9_MOVER_STATE_IDLE, 0);
219 rc = ndmca_test_mover_continue (sess, NDMP9_ILLEGAL_STATE_ERR);
222 rc = ndmca_test_mover_abort (sess, NDMP9_ILLEGAL_STATE_ERR);
225 rc = ndmca_test_mover_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
228 rc = ndmca_test_mover_close (sess, NDMP9_ILLEGAL_STATE_ERR);
231 rc = ndmca_test_mover_set_window (sess, NDMP9_NO_ERR, 0, 0);
234 rc = ndmca_test_mover_set_record_size (sess, NDMP9_NO_ERR);
240 extern int ndmca_test_tape_open (struct ndm_session *sess,
241 ndmp9_error expect_err,
242 char *device, int mode);
243 extern int ndmca_test_tape_close (struct ndm_session *sess,
244 ndmp9_error expect_err);
247 ndmca_tm_listen (struct ndm_session *sess)
249 struct ndm_control_agent *ca = &sess->control_acb;
252 ndmca_test_phase (sess, "M-LISTEN", "Mover LISTEN State Series");
254 rc = ndmca_test_check_mover_state (sess, NDMP9_MOVER_STATE_IDLE, 0);
257 rc = ndmca_test_mover_set_record_size (sess, NDMP9_NO_ERR);
260 rc = ndmca_test_mover_set_window (sess, NDMP9_NO_ERR, 0, 0);
263 ndmca_test_done_phase (sess);
268 ndmca_test_phase (sess, "M-LISTEN/bogus-args",
269 "Mover LISTEN State Series w/ bogus args");
271 if (ca->has_local_addr) {
272 rc = ndmca_test_mover_listen (sess, NDMP9_ILLEGAL_ARGS_ERR,
273 NDMP9_ADDR_LOCAL, 123);
277 rc = ndmca_test_mover_listen (sess, NDMP9_ILLEGAL_ARGS_ERR,
278 123, NDMP9_MOVER_MODE_READ);
281 ndmca_test_done_phase (sess);
284 * Tape drive not open
287 ndmca_test_phase (sess, "M-LISTEN/not-open",
288 "Mover LISTEN State Series w/o tape open");
290 if (ca->has_local_addr) {
291 rc = ndmca_tm_listen_subr (sess,
292 NDMP9_DEV_NOT_OPEN_ERR,
293 NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_READ);
297 if (ca->has_tcp_addr) {
298 rc = ndmca_tm_listen_subr (sess,
299 NDMP9_DEV_NOT_OPEN_ERR,
300 NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_READ);
304 if (ca->has_local_addr) {
305 rc = ndmca_tm_listen_subr (sess,
306 NDMP9_DEV_NOT_OPEN_ERR,
307 NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_WRITE);
311 if (ca->has_tcp_addr) {
312 rc = ndmca_tm_listen_subr (sess,
313 NDMP9_DEV_NOT_OPEN_ERR,
314 NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_WRITE);
318 ndmca_test_done_phase (sess);
321 * Tape drive open for READ
323 ndmca_test_phase (sess, "M-LISTEN/tape-ro",
324 "Mover LISTEN State Series w/ tape r/o");
326 rc = ndmca_test_tape_open(sess, NDMP9_NO_ERR, 0, NDMP9_TAPE_READ_MODE);
329 if (ca->has_local_addr) {
330 rc = ndmca_tm_listen_subr (sess,
331 NDMP9_PERMISSION_ERR,
332 NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_READ);
336 if (ca->has_tcp_addr) {
337 rc = ndmca_tm_listen_subr (sess,
338 NDMP9_PERMISSION_ERR,
339 NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_READ);
343 if (ca->has_local_addr) {
344 rc = ndmca_tm_listen_subr (sess,
346 NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_WRITE);
350 if (ca->has_tcp_addr) {
351 rc = ndmca_tm_listen_subr (sess,
353 NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_WRITE);
357 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
360 ndmca_test_done_phase (sess);
363 * Tape drive open for WRITE
365 ndmca_test_phase (sess, "M-LISTEN/tape-rw",
366 "Mover LISTEN State Series w/ tape r/w");
368 rc = ndmca_test_tape_open(sess, NDMP9_NO_ERR, 0, NDMP9_TAPE_RDWR_MODE);
371 if (ca->has_local_addr) {
372 rc = ndmca_tm_listen_subr (sess,
374 NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_READ);
378 if (ca->has_tcp_addr) {
379 rc = ndmca_tm_listen_subr (sess,
381 NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_READ);
385 if (ca->has_local_addr) {
386 rc = ndmca_tm_listen_subr (sess,
388 NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_WRITE);
392 if (ca->has_tcp_addr) {
393 rc = ndmca_tm_listen_subr (sess,
395 NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_WRITE);
399 rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
403 ndmca_test_done_phase (sess);
405 // done by the wrapper...
409 * TODO: NDMP9_MOVER_MODE_DATA
417 ndmca_test_phase (sess, "M-LISTEN", "Mover LISTEN State Series");
424 ndmca_tm_listen_subr (struct ndm_session *sess,
425 ndmp9_error expect_err,
426 ndmp9_addr_type addr_type, ndmp9_mover_mode mode)
430 rc = ndmca_test_check_mover_state (sess, NDMP9_MOVER_STATE_IDLE, 0);
433 rc = ndmca_test_mover_listen (sess, expect_err, addr_type, mode);
436 if (expect_err != NDMP9_NO_ERR)
437 return 0; /* got expected error */
439 rc = ndmca_test_check_mover_state (sess, NDMP9_MOVER_STATE_LISTEN, 0);
442 rc = ndmca_test_mover_listen (sess, NDMP9_ILLEGAL_STATE_ERR,
446 rc = ndmca_test_mover_continue (sess, NDMP9_ILLEGAL_STATE_ERR);
450 /* let it slide for Veritas 3.2 for the moment... Oct 23, 2002 */
452 rc = ndmca_test_mover_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
458 rc = ndmca_test_mover_close (sess, NDMP9_ILLEGAL_STATE_ERR);
462 /* setting the window size in LISTEN mode is not legal in
463 * version 4 and is required to work in earlier versions
465 if (sess->plumb.tape->protocol_version < 4) {
466 rc = ndmca_test_mover_set_window (sess, NDMP9_NO_ERR, 0, 0);
470 rc = ndmca_test_mover_set_window (sess, NDMP9_ILLEGAL_STATE_ERR, 0, 0);
475 rc = ndmca_test_mover_set_record_size (sess, NDMP9_ILLEGAL_STATE_ERR);
478 rc = ndmca_test_mover_abort (sess, NDMP9_NO_ERR);
481 rc = ndmca_test_check_mover_state (sess,
482 NDMP9_MOVER_STATE_HALTED, NDMP9_MOVER_HALT_ABORTED);
485 rc = ndmca_test_mover_stop (sess, NDMP9_NO_ERR);
488 rc = ndmca_test_check_mover_state (sess, NDMP9_MOVER_STATE_IDLE, 0);
497 ndmca_test_check_mover_state (struct ndm_session *sess,
498 ndmp9_mover_state expected, int reason)
500 struct ndm_control_agent * ca = &sess->control_acb;
501 ndmp9_mover_get_state_reply * ms = &ca->mover_state;
507 /* close previous test if there is one */
508 ndmca_test_close (sess);
511 ndmca_test_open (sess,
513 ndmp9_mover_state_to_str (expected));
515 strcpy (errbuf, "???");
518 rc = ndmca_mover_get_state (sess);
521 what = "state self-consistent";
522 /* make sure the sensed state is self consistent */
524 case NDMP9_MOVER_STATE_IDLE:
525 case NDMP9_MOVER_STATE_LISTEN:
526 case NDMP9_MOVER_STATE_ACTIVE:
527 if (ms->pause_reason != NDMP9_MOVER_PAUSE_NA
528 || ms->halt_reason != NDMP9_MOVER_HALT_NA) {
529 strcpy (errbuf, "reason(s) != NA");
534 case NDMP9_MOVER_STATE_PAUSED:
535 if (ms->halt_reason != NDMP9_MOVER_HALT_NA) {
536 strcpy (errbuf, "halt_reason != NA");
541 case NDMP9_MOVER_STATE_HALTED:
542 if (ms->pause_reason != NDMP9_MOVER_PAUSE_NA) {
543 strcpy (errbuf, "pause_reason != NA");
549 strcpy (errbuf, "bogus state");
554 if (ms->state != expected) {
555 sprintf (errbuf, "expected %s got %s",
556 ndmp9_mover_state_to_str (expected),
557 ndmp9_mover_state_to_str (ms->state));
563 case NDMP9_MOVER_STATE_PAUSED:
564 if (ms->pause_reason != (ndmp9_mover_pause_reason)reason) {
565 sprintf (errbuf, "expected %s got %s",
566 ndmp9_mover_pause_reason_to_str (reason),
567 ndmp9_mover_pause_reason_to_str (ms->pause_reason));
572 case NDMP9_MOVER_STATE_HALTED:
573 if (ms->halt_reason != (ndmp9_mover_halt_reason)reason) {
574 sprintf (errbuf, "expected %s got %s",
575 ndmp9_mover_halt_reason_to_str (reason),
576 ndmp9_mover_halt_reason_to_str (ms->halt_reason));
586 ndmca_test_close (sess);
592 sprintf(tmpbuf, "%s: %s", what, errbuf);
593 ndmca_test_fail(sess, tmpbuf);
595 ndmca_test_close (sess);
602 #define NDMTEST_CALL(CONN) ndmca_test_call(CONN, xa, expect_err);
606 ndmca_test_mover_get_state (struct ndm_session *sess, ndmp9_error expect_err)
608 struct ndmconn * conn = sess->plumb.tape;
611 /* close previous test if there is one */
612 ndmca_test_close (sess);
614 rc = ndmca_mover_get_state (sess);
616 rc = ndmca_test_check_expect (conn, rc, expect_err);
622 ndmca_test_mover_listen (struct ndm_session *sess, ndmp9_error expect_err,
623 ndmp9_addr_type addr_type, ndmp9_mover_mode mode)
625 struct ndmconn * conn = sess->plumb.tape;
626 struct ndm_control_agent *ca = &sess->control_acb;
629 /* close previous test if there is one */
630 ndmca_test_close (sess);
632 switch (conn->protocol_version) {
633 default: return -1234;
635 #ifndef NDMOS_OPTION_NO_NDMP2
637 NDMC_WITH(ndmp2_mover_listen, NDMP2VER)
638 request->mode = mode;
640 request->addr_type = addr_type;
642 rc = NDMTEST_CALL(conn);
645 if (expect_err == NDMP9_NO_ERR
646 && request->addr_type != reply->mover.addr_type) {
647 /* TODO: use proper test format */
648 ndmalogf (sess, "Test", 1,
649 "MOVER_LISTEN addr_type mismatch");
652 ndmp_2to9_mover_addr (&reply->mover, &ca->mover_addr);
655 #endif /* !NDMOS_OPTION_NO_NDMP2 */
656 #ifndef NDMOS_OPTION_NO_NDMP3
658 NDMC_WITH(ndmp3_mover_listen, NDMP3VER)
659 request->mode = mode;
661 request->addr_type = addr_type;
663 rc = NDMTEST_CALL(conn);
666 if (expect_err == NDMP9_NO_ERR
667 && request->addr_type
668 != reply->data_connection_addr.addr_type) {
669 /* TODO: use proper test format */
670 ndmalogf (sess, "Test", 1,
671 "MOVER_LISTEN addr_type mismatch");
674 ndmp_3to9_addr (&reply->data_connection_addr, &ca->mover_addr);
677 #endif /* !NDMOS_OPTION_NO_NDMP3 */
678 #ifndef NDMOS_OPTION_NO_NDMP4
680 NDMC_WITH(ndmp4_mover_listen, NDMP4VER)
681 request->mode = mode;
683 request->addr_type = addr_type;
685 rc = NDMTEST_CALL(conn);
688 if (expect_err == NDMP9_NO_ERR
689 && request->addr_type
690 != reply->connect_addr.addr_type) {
691 /* TODO: use proper test format */
692 ndmalogf (sess, "Test", 1,
693 "MOVER_LISTEN addr_type mismatch");
696 ndmp_4to9_addr (&reply->connect_addr, &ca->mover_addr);
699 #endif /* !NDMOS_OPTION_NO_NDMP4 */
706 ndmca_test_mover_continue (struct ndm_session *sess, ndmp9_error expect_err)
708 struct ndmconn * conn = sess->plumb.tape;
711 /* close previous test if there is one */
712 ndmca_test_close (sess);
714 rc = ndmca_mover_continue (sess);
716 rc = ndmca_test_check_expect (conn, rc, expect_err);
722 ndmca_test_mover_abort (struct ndm_session *sess, ndmp9_error expect_err)
724 struct ndmconn * conn = sess->plumb.tape;
727 /* close previous test if there is one */
728 ndmca_test_close (sess);
730 rc = ndmca_mover_abort (sess);
732 rc = ndmca_test_check_expect (conn, rc, expect_err);
738 ndmca_test_mover_stop (struct ndm_session *sess, ndmp9_error expect_err)
740 struct ndmconn * conn = sess->plumb.tape;
743 /* close previous test if there is one */
744 ndmca_test_close (sess);
746 rc = ndmca_mover_stop (sess);
748 rc = ndmca_test_check_expect (conn, rc, expect_err);
754 ndmca_test_mover_set_window (struct ndm_session *sess, ndmp9_error expect_err,
755 unsigned long long offset, unsigned long long length)
757 struct ndmconn * conn = sess->plumb.tape;
760 /* close previous test if there is one */
761 ndmca_test_close (sess);
763 rc = ndmca_mover_set_window (sess, offset, length);
765 rc = ndmca_test_check_expect (conn, rc, expect_err);
771 ndmca_test_mover_read (struct ndm_session *sess, ndmp9_error expect_err,
772 unsigned long long offset, unsigned long long length)
774 struct ndmconn * conn = sess->plumb.tape;
777 /* close previous test if there is one */
778 ndmca_test_close (sess);
780 rc = ndmca_mover_read (sess, offset, length);
782 rc = ndmca_test_check_expect (conn, rc, expect_err);
788 ndmca_test_mover_close (struct ndm_session *sess, ndmp9_error expect_err)
790 struct ndmconn * conn = sess->plumb.tape;
793 /* close previous test if there is one */
794 ndmca_test_close (sess);
796 rc = ndmca_mover_close (sess);
798 rc = ndmca_test_check_expect (conn, rc, expect_err);
804 ndmca_test_mover_set_record_size (struct ndm_session *sess,
805 ndmp9_error expect_err)
807 struct ndmconn * conn = sess->plumb.tape;
808 struct ndm_control_agent *ca = &sess->control_acb;
811 /* close previous test if there is one */
812 ndmca_test_close (sess);
814 switch (conn->protocol_version) {
815 default: return -1234;
817 #ifndef NDMOS_OPTION_NO_NDMP2
819 NDMC_WITH(ndmp2_mover_set_record_size, NDMP2VER)
820 request->len = ca->job.record_size;
821 rc = NDMTEST_CALL(conn);
824 #endif /* !NDMOS_OPTION_NO_NDMP2 */
825 #ifndef NDMOS_OPTION_NO_NDMP3
827 NDMC_WITH(ndmp3_mover_set_record_size, NDMP3VER)
828 request->len = ca->job.record_size;
829 rc = NDMTEST_CALL(conn);
832 #endif /* !NDMOS_OPTION_NO_NDMP3 */
833 #ifndef NDMOS_OPTION_NO_NDMP4
835 NDMC_WITH(ndmp4_mover_set_record_size, NDMP4VER)
836 request->len = ca->job.record_size;
837 rc = NDMTEST_CALL(conn);
840 #endif /* !NDMOS_OPTION_NO_NDMP4 */
845 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */