Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndma_ctst_data.c
diff --git a/ndmp-src/ndma_ctst_data.c b/ndmp-src/ndma_ctst_data.c
new file mode 100644 (file)
index 0000000..f5ae194
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 1998,1999,2000
+ *     Traakan, Inc., Los Altos, CA
+ *     All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Project:  NDMJOB
+ * Ident:    $Id: $
+ *
+ * Description:
+ *
+ ********************************************************************
+ *
+ * NDMP Elements of a test-data session
+ *
+ *                   +-----+     ###########
+ *                   | Job |----># CONTROL #
+ *                   +-----+     #  Agent  #
+ *                               #         #
+ *                               ###########
+ *                                 |      #
+ *                +----------------+      #
+ *                | control connection    #     CONTROL
+ *                V                       #     impersonates
+ *           ############                 #     TAPE side of
+ *           #  DATA    #                 #     image stream
+ *           #  Agent   #                 #
+ *  +-----+  # +------+ # image           #
+ *  |FILES|====|butype|===================#
+ *  +-----+  # +------+ # stream
+ *           ############
+ *
+ *
+ ********************************************************************
+ *
+ */
+
+
+#include "ndmagents.h"
+
+
+#ifndef NDMOS_OPTION_NO_CONTROL_AGENT
+
+
+extern int     ndmca_td_wrapper (struct ndm_session *sess,
+                               int (*func)(struct ndm_session *sess));
+
+
+extern int     ndmca_op_test_data (struct ndm_session *sess);
+extern int     ndmca_td_idle (struct ndm_session *sess);
+
+extern int     ndmca_td_listen (struct ndm_session *sess);
+extern int     ndmca_td_listen_subr (struct ndm_session *sess,
+                                     ndmp9_error expect_err,
+                                     ndmp9_addr_type addr_type);
+extern int     ndmca_test_check_data_state  (struct ndm_session *sess,
+                       ndmp9_data_state expected, int reason);
+extern int     ndmca_test_data_get_state (struct ndm_session *sess,
+                       ndmp9_error expect_err);
+extern int     ndmca_test_data_abort (struct ndm_session *sess,
+                       ndmp9_error expect_err);
+extern int     ndmca_test_data_stop (struct ndm_session *sess,
+                       ndmp9_error expect_err);
+
+
+
+int
+ndmca_op_test_data (struct ndm_session *sess)
+{
+       struct ndm_control_agent *ca = &sess->control_acb;
+       struct ndmconn *        conn;
+       int                     (*save_call) (struct ndmconn *conn,
+                                               struct ndmp_xa_buf *xa);
+       int                     rc;
+
+       rc = ndmca_connect_data_agent(sess);
+       if (rc) {
+               ndmconn_destruct (sess->plumb.data);
+               return rc;
+       }
+
+       conn = sess->plumb.data;
+       save_call = conn->call;
+       conn->call = ndma_call_no_tattle;
+
+       /* perform query to find out about TCP and LOCAL support */
+       rc = ndmca_test_query_conn_types (sess, conn);
+       if (rc) return rc;
+
+       rc = ndmca_td_wrapper (sess, ndmca_td_idle);
+       if (sess->plumb.data->protocol_version >= 3) {
+           // version 3 and later adds LISTEN
+           rc = ndmca_td_wrapper (sess, ndmca_td_listen);
+       }
+
+       ndmca_test_done_series (sess, "test-data");
+
+       ca = &sess->control_acb;
+       if (ca->has_tcp_addr && ca->has_local_addr) {
+           ndmalogf (sess, "TEST", 0, "LOCAL and TCP addressing tested.");
+       } else if (ca->has_tcp_addr) {
+           ndmalogf (sess, "TEST", 0, "TCP addressing ONLY tested.");
+       } else if (ca->has_local_addr) {
+           ndmalogf (sess, "TEST", 0, "LOCAL addressing ONLY tested.");
+       } else {
+           ndmalogf (sess, "TEST", 0, "Neither TCP or LOCAL addressing tested.");
+       }
+
+       return 0;
+}
+
+int
+ndmca_td_wrapper (struct ndm_session *sess,
+  int (*func)(struct ndm_session *sess))
+{
+       int             rc;
+
+       rc = (*func)(sess);
+
+       if (rc != 0) {
+               ndmalogf (sess, "Test", 1, "Failure");
+       }
+
+       ndmca_test_done_phase (sess);
+
+       /* clean up mess */
+       ndmca_test_log_note (sess, 2, "Cleaning up...");
+
+       rc = 0;
+
+       return rc;
+}
+
+int
+ndmca_td_idle (struct ndm_session *sess)
+{
+       int             rc;
+
+       ndmca_test_phase (sess, "D-IDLE", "Data IDLE State Series");
+
+       rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
+       if (rc) return rc;
+
+       rc = ndmca_test_data_abort (sess, NDMP9_ILLEGAL_STATE_ERR);
+       if (rc) return rc;
+
+       rc = ndmca_test_data_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
+       if (rc) return rc;
+
+       return 0;       /* pass */
+}
+
+
+
+#define NDMTEST_CALL(CONN) ndmca_test_call(CONN, xa, expect_err);
+
+
+
+int
+ndmca_test_data_listen (struct ndm_session *sess, ndmp9_error expect_err,
+                       ndmp9_addr_type addr_type)
+{
+       struct ndmconn *        conn = sess->plumb.data;
+       struct ndm_control_agent *ca = &sess->control_acb;
+       int                     rc;
+
+       /* close previous test if there is one */
+       ndmca_test_close (sess);
+
+       switch (conn->protocol_version) {
+       default:        return -1234;
+
+#ifndef NDMOS_OPTION_NO_NDMP3
+       case NDMP3VER:
+           NDMC_WITH(ndmp3_data_listen, NDMP3VER)
+               request->addr_type = addr_type;
+
+               rc = NDMTEST_CALL(conn);
+               if (rc) return rc;
+
+               if (expect_err == NDMP9_NO_ERR
+                && request->addr_type
+                   != reply->data_connection_addr.addr_type) {
+                       /* TODO: use proper test format */
+                       ndmalogf (sess, "Test", 1,
+                               "DATA_LISTEN addr_type mismatch");
+                       return -1;
+               }
+               ndmp_3to9_addr (&reply->data_connection_addr, &ca->data_addr);
+           NDMC_ENDWITH
+           break;
+#endif /* !NDMOS_OPTION_NO_NDMP3 */
+#ifndef NDMOS_OPTION_NO_NDMP4
+       case NDMP4VER:
+           NDMC_WITH(ndmp4_data_listen, NDMP4VER)
+               request->addr_type = addr_type;
+
+               rc = NDMTEST_CALL(conn);
+               if (rc) return rc;
+
+               if (expect_err == NDMP9_NO_ERR
+                && request->addr_type
+                   != reply->connect_addr.addr_type) {
+                       /* TODO: use proper test format */
+                       ndmalogf (sess, "Test", 1,
+                               "DATA_LISTEN addr_type mismatch");
+                       return -1;
+               }
+               ndmp_4to9_addr (&reply->connect_addr, &ca->data_addr);
+           NDMC_ENDWITH
+           break;
+#endif /* !NDMOS_OPTION_NO_NDMP4 */
+       }
+
+       return 0;
+}
+
+
+int
+ndmca_td_listen (struct ndm_session *sess)
+{
+        struct ndm_control_agent *ca = &sess->control_acb;
+       int             rc;
+
+       ndmca_test_phase (sess, "D-LISTEN", "Data LISTEN State Series");
+
+       rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
+       if (rc) return rc;
+
+       if (ca->has_tcp_addr) {
+           rc = ndmca_td_listen_subr (sess, NDMP9_NO_ERR, NDMP9_ADDR_TCP);
+           if (rc) return rc;
+       }
+
+       if (ca->has_local_addr) {
+           rc = ndmca_td_listen_subr (sess, NDMP9_NO_ERR, NDMP9_ADDR_LOCAL);
+           if (rc) return rc;
+       }
+
+       ndmca_test_done_phase (sess);
+
+       /*
+        * Bogus arguments
+        */
+       ndmca_test_phase (sess, "D-LISTEN/bogus-args",
+                               "Data LISTEN State Series w/ bogus args");
+
+       rc = ndmca_test_data_listen (sess, NDMP9_ILLEGAL_ARGS_ERR,
+                                    123);
+       if (rc) return rc;
+
+       ndmca_test_done_phase (sess);
+
+
+       return 0;       /* pass */
+}
+
+int
+ndmca_td_listen_subr (struct ndm_session *sess,
+                     ndmp9_error expect_err,
+                     ndmp9_addr_type addr_type)
+{
+       int             rc;
+
+       rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
+       if (rc) return rc;
+
+       rc = ndmca_test_data_listen (sess, expect_err, addr_type);
+       if (rc) return rc;
+
+       if (expect_err != NDMP9_NO_ERR)
+               return 0;               /* got expected error */
+
+       rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_LISTEN, 0);
+       if (rc) return rc;
+
+       rc = ndmca_test_data_listen (sess, NDMP9_ILLEGAL_STATE_ERR,
+               addr_type);
+       if (rc) return rc;
+
+       rc = ndmca_test_data_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
+       if (rc) return rc;
+
+       rc = ndmca_test_data_abort (sess, NDMP9_NO_ERR);
+       if (rc) return rc;
+
+       rc = ndmca_test_check_data_state  (sess,
+               NDMP9_DATA_STATE_HALTED, NDMP9_DATA_HALT_ABORTED);
+       if (rc) return rc;
+
+       rc = ndmca_test_data_stop (sess, NDMP9_NO_ERR);
+       if (rc) return rc;
+
+       rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
+       if (rc) return rc;
+
+       return 0;
+}
+
+int
+ndmca_test_check_data_state  (struct ndm_session *sess,
+  ndmp9_data_state expected, int reason)
+{
+       struct ndm_control_agent *      ca = &sess->control_acb;
+       ndmp9_data_get_state_reply *    ds = &ca->data_state;
+       int                             rc;
+       char *                          what;
+       char                            errbuf[100];
+       char                            tmpbuf[256];
+
+       /* close previous test if there is one */
+       ndmca_test_close (sess);
+
+       /* open new test */
+       ndmca_test_open (sess,
+                        "data check",
+                        ndmp9_data_state_to_str (expected));
+
+       strcpy (errbuf, "???");
+
+       what = "get_state";
+       rc = ndmca_data_get_state (sess);
+       if (rc) goto fail;
+
+       what = "state self-consistent";
+       /* make sure the sensed state is self consistent */
+       switch (ds->state) {
+       case NDMP9_DATA_STATE_IDLE:
+       case NDMP9_DATA_STATE_ACTIVE:
+       case NDMP9_DATA_STATE_LISTEN:
+       case NDMP9_DATA_STATE_CONNECTED:
+               if (ds->halt_reason != NDMP9_DATA_HALT_NA) {
+                       strcpy (errbuf, "reason != NA");
+                       goto fail;
+               }
+               break;
+
+       case NDMP9_DATA_STATE_HALTED:
+               break;
+
+       default:
+               strcpy (errbuf, "bogus state");
+               goto fail;
+       }
+
+       what = "state";
+       if (ds->state != expected) {
+               sprintf (errbuf, "expected %s got %s",
+                       ndmp9_data_state_to_str (expected),
+                       ndmp9_data_state_to_str (ds->state));
+               goto fail;
+       }
+
+       what = "reason";
+       switch (ds->state) {
+       case NDMP9_DATA_STATE_HALTED:
+               if (ds->halt_reason != (ndmp9_data_halt_reason)reason) {
+                       sprintf (errbuf, "expected %s got %s",
+                           ndmp9_data_halt_reason_to_str (reason),
+                           ndmp9_data_halt_reason_to_str (ds->halt_reason));
+                       goto fail;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       /* test passed */
+       ndmca_test_close (sess);
+
+       return 0;
+
+  fail:
+       /* test failed */
+       sprintf(tmpbuf, "%s: %s", what, errbuf);
+       ndmca_test_fail(sess, tmpbuf);
+
+       ndmca_test_close (sess);
+
+       return -1;
+}
+
+
+
+int
+ndmca_test_data_get_state (struct ndm_session *sess, ndmp9_error expect_err)
+{
+       struct ndmconn *        conn = sess->plumb.data;
+       int                     rc;
+
+       /* close previous test if there is one */
+       ndmca_test_close (sess);
+
+       rc = ndmca_data_get_state (sess);
+
+       rc = ndmca_test_check_expect (conn, rc, expect_err);
+
+       return rc;
+}
+
+int
+ndmca_test_data_abort (struct ndm_session *sess, ndmp9_error expect_err)
+{
+       struct ndmconn *        conn = sess->plumb.data;
+       int                     rc;
+
+       /* close previous test if there is one */
+       ndmca_test_close (sess);
+
+       rc = ndmca_data_abort (sess);
+
+       rc = ndmca_test_check_expect (conn, rc, expect_err);
+
+       return rc;
+}
+
+int
+ndmca_test_data_stop (struct ndm_session *sess, ndmp9_error expect_err)
+{
+       struct ndmconn *        conn = sess->plumb.data;
+       int                     rc;
+
+       /* close previous test if there is one */
+       ndmca_test_close (sess);
+
+       rc = ndmca_data_stop (sess);
+
+       rc = ndmca_test_check_expect (conn, rc, expect_err);
+
+       return rc;
+}
+
+
+
+
+
+
+#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */