Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndma_ctst_mover.c
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-mover session
38  *
39  *                   +-----+     ###########
40  *                   | Job |----># CONTROL #
41  *                   +-----+     #  Agent  #
42  *                               #         #
43  *                               ###########
44  *                                #   |  |
45  *                  #=============#   |  +---------------------+
46  *                  #                 |                        |
47  *   CONTROL        #         control | connections            |
48  *   impersonates   #                 V                        V
49  *   DATA side of   #            ############  +-------+   #########
50  *   image stream   #            #  TAPE    #  |       |   # ROBOT #
51  *                  #            #  Agent   #  | ROBOT |<-># Agent #
52  *                  #     image  # +------+ #  |+-----+|   #       #
53  *                  #==============|mover |=====|DRIVE||   #       #
54  *                        stream # +------+ #  |+-----+|   #       #
55  *                               ############  +-------+   #########
56  *
57  ****************************************************************
58  *
59  */
60
61
62 #include "ndmagents.h"
63
64
65 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
66
67
68 extern int      ndmca_tm_wrapper (struct ndm_session *sess,
69                                 int (*func)(struct ndm_session *sess));
70
71
72 extern int      ndmca_op_test_mover (struct ndm_session *sess);
73 extern int      ndmca_tm_idle (struct ndm_session *sess);
74
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);
106
107
108
109 struct series {
110         unsigned        n_rec;
111         unsigned        recsize;
112 };
113
114 struct series tm_series[] = {
115         { 1,    512 },
116         { 100,  1024 },
117         { 1,    512 },
118         { 100,  139 },
119         { 1,    512 },
120         { 99,   10240 },
121         { 1,    512 },
122         { 3,    32768 },
123         { 1,    512 },
124         { 0 }
125 };
126
127
128 int
129 ndmca_op_test_mover (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         struct ndm_control_agent *ca = &sess->control_acb;
136
137         if (sess->control_acb.job.data_agent.conn_type != NDMCONN_TYPE_NONE) {
138                 /*
139                  * Sometimes needed to aid resident tape agent test
140                  */
141                 rc = ndmca_connect_data_agent (sess);
142                 if (rc) {
143                         ndmconn_destruct (sess->plumb.data);
144                         return rc;
145                 }
146         }
147
148         rc = ndmca_test_load_tape (sess);
149         if (rc) return rc;
150
151         conn = sess->plumb.tape;
152         save_call = conn->call;
153         conn->call = ndma_call_no_tattle;
154
155         /* perform query to find out about TCP and LOCAL support */
156         rc = ndmca_test_query_conn_types (sess, conn);
157         if (rc) return rc;
158
159         rc = ndmca_tm_wrapper (sess, ndmca_tm_idle);
160         rc = ndmca_tm_wrapper (sess, ndmca_tm_listen);
161
162         ndmca_test_unload_tape (sess);
163
164         ndmca_test_done_series (sess, "test-mover");
165
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.");
173         } else {
174             ndmalogf (sess, "TEST", 0, "Neither TCP or LOCAL addressing tested.");
175         }
176
177         return 0;
178 }
179
180 int
181 ndmca_tm_wrapper (struct ndm_session *sess,
182   int (*func)(struct ndm_session *sess))
183 {
184         int             rc;
185
186         rc = (*func)(sess);
187
188         if (rc != 0) {
189                 ndmalogf (sess, "Test", 1, "Failure");
190         }
191
192         ndmca_test_done_phase (sess);
193
194         /* clean up mess */
195         ndmca_test_log_note (sess, 2, "Cleaning up...");
196
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 */
200         if (rc != 0) {
201                 ndmca_test_log_note (sess, 0, "Cleaning up failed, quiting");
202         } else {
203                 ndmca_test_log_note (sess, 2, "Cleaning up done");
204         }
205
206         return rc;
207 }
208
209 int
210 ndmca_tm_idle (struct ndm_session *sess)
211 {
212         int             rc;
213
214         ndmca_test_phase (sess, "M-IDLE", "Mover IDLE State Series");
215
216         rc = ndmca_test_check_mover_state  (sess, NDMP9_MOVER_STATE_IDLE, 0);
217         if (rc) return rc;
218
219         rc = ndmca_test_mover_continue (sess, NDMP9_ILLEGAL_STATE_ERR);
220         if (rc) return rc;
221
222         rc = ndmca_test_mover_abort (sess, NDMP9_ILLEGAL_STATE_ERR);
223         if (rc) return rc;
224
225         rc = ndmca_test_mover_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
226         if (rc) return rc;
227
228         rc = ndmca_test_mover_close (sess, NDMP9_ILLEGAL_STATE_ERR);
229         if (rc) return rc;
230
231         rc = ndmca_test_mover_set_window (sess, NDMP9_NO_ERR, 0, 0);
232         if (rc) return rc;
233
234         rc = ndmca_test_mover_set_record_size (sess, NDMP9_NO_ERR);
235         if (rc) return rc;
236
237         return 0;       /* pass */
238 }
239
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);
245
246 int
247 ndmca_tm_listen (struct ndm_session *sess)
248 {
249         struct ndm_control_agent *ca = &sess->control_acb;
250         int             rc;
251
252         ndmca_test_phase (sess, "M-LISTEN", "Mover LISTEN State Series");
253
254         rc = ndmca_test_check_mover_state  (sess, NDMP9_MOVER_STATE_IDLE, 0);
255         if (rc) return rc;
256
257         rc = ndmca_test_mover_set_record_size (sess, NDMP9_NO_ERR);
258         if (rc) return rc;
259
260         rc = ndmca_test_mover_set_window (sess, NDMP9_NO_ERR, 0, 0);
261         if (rc) return rc;
262
263         ndmca_test_done_phase (sess);
264
265         /*
266          * Bogus arguments
267          */
268         ndmca_test_phase (sess, "M-LISTEN/bogus-args",
269                                 "Mover LISTEN State Series w/ bogus args");
270
271         if (ca->has_local_addr) {
272             rc = ndmca_test_mover_listen (sess, NDMP9_ILLEGAL_ARGS_ERR,
273                                           NDMP9_ADDR_LOCAL, 123);
274             if (rc) return rc;
275         }
276
277         rc = ndmca_test_mover_listen (sess, NDMP9_ILLEGAL_ARGS_ERR,
278                 123, NDMP9_MOVER_MODE_READ);
279         if (rc) return rc;
280
281         ndmca_test_done_phase (sess);
282
283         /*
284          * Tape drive not open
285          */
286
287         ndmca_test_phase (sess, "M-LISTEN/not-open",
288                                 "Mover LISTEN State Series w/o tape open");
289
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);
294             if (rc) return rc;
295         }
296
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);
301             if (rc) return rc;
302         }
303
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);
308             if (rc) return rc;
309         }
310
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);
315             if (rc) return rc;
316         }
317
318         ndmca_test_done_phase (sess);
319
320         /*
321          * Tape drive open for READ
322          */
323         ndmca_test_phase (sess, "M-LISTEN/tape-ro",
324                                 "Mover LISTEN State Series w/ tape r/o");
325
326         rc = ndmca_test_tape_open(sess, NDMP9_NO_ERR, 0, NDMP9_TAPE_READ_MODE);
327         if (rc) return rc;
328
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);
333             if (rc) return rc;
334         }
335
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);
340             if (rc) return rc;
341         }
342
343         if (ca->has_local_addr) {
344             rc = ndmca_tm_listen_subr (sess,
345                                        NDMP9_NO_ERR,
346                                        NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_WRITE);
347             if (rc) return rc;
348         }
349
350         if (ca->has_tcp_addr) {
351             rc = ndmca_tm_listen_subr (sess,
352                                        NDMP9_NO_ERR,
353                                        NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_WRITE);
354             if (rc) return rc;
355         }
356
357         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
358         if (rc) return rc;
359
360         ndmca_test_done_phase (sess);
361
362         /*
363          * Tape drive open for WRITE
364          */
365         ndmca_test_phase (sess, "M-LISTEN/tape-rw",
366                                 "Mover LISTEN State Series w/ tape r/w");
367
368         rc = ndmca_test_tape_open(sess, NDMP9_NO_ERR, 0, NDMP9_TAPE_RDWR_MODE);
369         if (rc) return rc;
370
371         if (ca->has_local_addr) {
372             rc = ndmca_tm_listen_subr (sess,
373                                        NDMP9_NO_ERR,
374                                        NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_READ);
375             if (rc) return rc;
376         }
377
378         if (ca->has_tcp_addr) {
379             rc = ndmca_tm_listen_subr (sess,
380                                        NDMP9_NO_ERR,
381                                        NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_READ);
382             if (rc) return rc;
383         }
384
385         if (ca->has_local_addr) {
386             rc = ndmca_tm_listen_subr (sess,
387                                        NDMP9_NO_ERR,
388                                        NDMP9_ADDR_LOCAL, NDMP9_MOVER_MODE_WRITE);
389             if (rc) return rc;
390         }
391
392         if (ca->has_tcp_addr) {
393             rc = ndmca_tm_listen_subr (sess,
394                                        NDMP9_NO_ERR,
395                                        NDMP9_ADDR_TCP, NDMP9_MOVER_MODE_WRITE);
396             if (rc) return rc;
397         }
398
399         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
400         if (rc) return rc;
401
402 #if 0
403         ndmca_test_done_phase (sess);
404 #else
405         // done by the wrapper...
406 #endif
407
408         /*
409          * TODO: NDMP9_MOVER_MODE_DATA
410          */
411
412         /*
413          * Good enough
414          */
415
416 #if 0
417         ndmca_test_phase (sess, "M-LISTEN", "Mover LISTEN State Series");
418 #endif
419
420         return 0;       /* pass */
421 }
422
423 int
424 ndmca_tm_listen_subr (struct ndm_session *sess,
425  ndmp9_error expect_err,
426  ndmp9_addr_type addr_type, ndmp9_mover_mode mode)
427 {
428         int             rc;
429
430         rc = ndmca_test_check_mover_state  (sess, NDMP9_MOVER_STATE_IDLE, 0);
431         if (rc) return rc;
432
433         rc = ndmca_test_mover_listen (sess, expect_err, addr_type, mode);
434         if (rc) return rc;
435
436         if (expect_err != NDMP9_NO_ERR)
437                 return 0;               /* got expected error */
438
439         rc = ndmca_test_check_mover_state  (sess, NDMP9_MOVER_STATE_LISTEN, 0);
440         if (rc) return rc;
441
442         rc = ndmca_test_mover_listen (sess, NDMP9_ILLEGAL_STATE_ERR,
443                 addr_type, mode);
444         if (rc) return rc;
445
446         rc = ndmca_test_mover_continue (sess, NDMP9_ILLEGAL_STATE_ERR);
447         if (rc) return rc;
448
449 #if 0
450         /* let it slide for Veritas 3.2 for the moment... Oct 23, 2002 */
451 #else
452         rc = ndmca_test_mover_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
453         if (rc) return rc;
454 #endif
455
456 #if 0
457         /* ??? */
458         rc = ndmca_test_mover_close (sess, NDMP9_ILLEGAL_STATE_ERR);
459         if (rc) return rc;
460 #endif
461
462         /* setting the window size in LISTEN mode is not legal in
463          * version 4 and is required to work in earlier versions
464          */
465         if (sess->plumb.tape->protocol_version < 4) {
466             rc = ndmca_test_mover_set_window (sess, NDMP9_NO_ERR, 0, 0);
467             if (rc) return rc;
468
469         } else {
470             rc = ndmca_test_mover_set_window (sess, NDMP9_ILLEGAL_STATE_ERR, 0, 0);
471             if (rc) return rc;
472
473         }
474
475         rc = ndmca_test_mover_set_record_size (sess, NDMP9_ILLEGAL_STATE_ERR);
476         if (rc) return rc;
477
478         rc = ndmca_test_mover_abort (sess, NDMP9_NO_ERR);
479         if (rc) return rc;
480
481         rc = ndmca_test_check_mover_state  (sess,
482                 NDMP9_MOVER_STATE_HALTED, NDMP9_MOVER_HALT_ABORTED);
483         if (rc) return rc;
484
485         rc = ndmca_test_mover_stop (sess, NDMP9_NO_ERR);
486         if (rc) return rc;
487
488         rc = ndmca_test_check_mover_state  (sess, NDMP9_MOVER_STATE_IDLE, 0);
489         if (rc) return rc;
490
491         return 0;
492 }
493
494
495
496 int
497 ndmca_test_check_mover_state  (struct ndm_session *sess,
498   ndmp9_mover_state expected, int reason)
499 {
500         struct ndm_control_agent *      ca = &sess->control_acb;
501         ndmp9_mover_get_state_reply *   ms = &ca->mover_state;
502         int                             rc;
503         char *                          what;
504         char                            errbuf[100];
505         char                            tmpbuf[256];
506
507         /* close previous test if there is one */
508         ndmca_test_close (sess);
509
510         /* open new test */
511         ndmca_test_open (sess,
512                          "mover check",
513                          ndmp9_mover_state_to_str (expected));
514
515         strcpy (errbuf, "???");
516
517         what = "get_state";
518         rc = ndmca_mover_get_state (sess);
519         if (rc) goto fail;
520
521         what = "state self-consistent";
522         /* make sure the sensed state is self consistent */
523         switch (ms->state) {
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");
530                         goto fail;
531                 }
532                 break;
533
534         case NDMP9_MOVER_STATE_PAUSED:
535                 if (ms->halt_reason != NDMP9_MOVER_HALT_NA) {
536                         strcpy (errbuf, "halt_reason != NA");
537                         goto fail;
538                 }
539                 break;
540
541         case NDMP9_MOVER_STATE_HALTED:
542                 if (ms->pause_reason != NDMP9_MOVER_PAUSE_NA) {
543                         strcpy (errbuf, "pause_reason != NA");
544                         goto fail;
545                 }
546                 break;
547
548         default:
549                 strcpy (errbuf, "bogus state");
550                 goto fail;
551         }
552
553         what = "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));
558                 goto fail;
559         }
560
561         what = "reason";
562         switch (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));
568                         goto fail;
569                 }
570                 break;
571
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));
577                         goto fail;
578                 }
579                 break;
580
581         default:
582                 break;
583         }
584
585         /* test passed */
586         ndmca_test_close (sess);
587
588         return 0;
589
590   fail:
591         /* test failed */
592         sprintf(tmpbuf, "%s: %s", what, errbuf);
593         ndmca_test_fail(sess, tmpbuf);
594
595         ndmca_test_close (sess);
596
597         return -1;
598 }
599
600
601
602 #define NDMTEST_CALL(CONN) ndmca_test_call(CONN, xa, expect_err);
603
604
605 int
606 ndmca_test_mover_get_state (struct ndm_session *sess, ndmp9_error expect_err)
607 {
608         struct ndmconn *        conn = sess->plumb.tape;
609         int                     rc;
610
611         /* close previous test if there is one */
612         ndmca_test_close (sess);
613
614         rc = ndmca_mover_get_state (sess);
615
616         rc = ndmca_test_check_expect (conn, rc, expect_err);
617
618         return rc;
619 }
620
621 int
622 ndmca_test_mover_listen (struct ndm_session *sess, ndmp9_error expect_err,
623   ndmp9_addr_type addr_type, ndmp9_mover_mode mode)
624 {
625         struct ndmconn *        conn = sess->plumb.tape;
626         struct ndm_control_agent *ca = &sess->control_acb;
627         int                     rc;
628
629         /* close previous test if there is one */
630         ndmca_test_close (sess);
631
632         switch (conn->protocol_version) {
633         default:        return -1234;
634
635 #ifndef NDMOS_OPTION_NO_NDMP2
636         case NDMP2VER:
637             NDMC_WITH(ndmp2_mover_listen, NDMP2VER)
638                 request->mode = mode;
639
640                 request->addr_type = addr_type;
641
642                 rc = NDMTEST_CALL(conn);
643                 if (rc) return rc;
644
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");
650                         return -1;
651                 }
652                 ndmp_2to9_mover_addr (&reply->mover, &ca->mover_addr);
653             NDMC_ENDWITH
654             break;
655 #endif /* !NDMOS_OPTION_NO_NDMP2 */
656 #ifndef NDMOS_OPTION_NO_NDMP3
657         case NDMP3VER:
658             NDMC_WITH(ndmp3_mover_listen, NDMP3VER)
659                 request->mode = mode;
660
661                 request->addr_type = addr_type;
662
663                 rc = NDMTEST_CALL(conn);
664                 if (rc) return rc;
665
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");
672                         return -1;
673                 }
674                 ndmp_3to9_addr (&reply->data_connection_addr, &ca->mover_addr);
675             NDMC_ENDWITH
676             break;
677 #endif /* !NDMOS_OPTION_NO_NDMP3 */
678 #ifndef NDMOS_OPTION_NO_NDMP4
679         case NDMP4VER:
680             NDMC_WITH(ndmp4_mover_listen, NDMP4VER)
681                 request->mode = mode;
682
683                 request->addr_type = addr_type;
684
685                 rc = NDMTEST_CALL(conn);
686                 if (rc) return rc;
687
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");
694                         return -1;
695                 }
696                 ndmp_4to9_addr (&reply->connect_addr, &ca->mover_addr);
697             NDMC_ENDWITH
698             break;
699 #endif /* !NDMOS_OPTION_NO_NDMP4 */
700         }
701
702         return 0;
703 }
704
705 int
706 ndmca_test_mover_continue (struct ndm_session *sess, ndmp9_error expect_err)
707 {
708         struct ndmconn *        conn = sess->plumb.tape;
709         int                     rc;
710
711         /* close previous test if there is one */
712         ndmca_test_close (sess);
713
714         rc = ndmca_mover_continue (sess);
715
716         rc = ndmca_test_check_expect (conn, rc, expect_err);
717
718         return rc;
719 }
720
721 int
722 ndmca_test_mover_abort (struct ndm_session *sess, ndmp9_error expect_err)
723 {
724         struct ndmconn *        conn = sess->plumb.tape;
725         int                     rc;
726
727         /* close previous test if there is one */
728         ndmca_test_close (sess);
729
730         rc = ndmca_mover_abort (sess);
731
732         rc = ndmca_test_check_expect (conn, rc, expect_err);
733
734         return rc;
735 }
736
737 int
738 ndmca_test_mover_stop (struct ndm_session *sess, ndmp9_error expect_err)
739 {
740         struct ndmconn *        conn = sess->plumb.tape;
741         int                     rc;
742
743         /* close previous test if there is one */
744         ndmca_test_close (sess);
745
746         rc = ndmca_mover_stop (sess);
747
748         rc = ndmca_test_check_expect (conn, rc, expect_err);
749
750         return rc;
751 }
752
753 int
754 ndmca_test_mover_set_window (struct ndm_session *sess, ndmp9_error expect_err,
755   unsigned long long offset, unsigned long long length)
756 {
757         struct ndmconn *        conn = sess->plumb.tape;
758         int                     rc;
759
760         /* close previous test if there is one */
761         ndmca_test_close (sess);
762
763         rc = ndmca_mover_set_window (sess, offset, length);
764
765         rc = ndmca_test_check_expect (conn, rc, expect_err);
766
767         return rc;
768 }
769
770 int
771 ndmca_test_mover_read (struct ndm_session *sess, ndmp9_error expect_err,
772   unsigned long long offset, unsigned long long length)
773 {
774         struct ndmconn *        conn = sess->plumb.tape;
775         int                     rc;
776
777         /* close previous test if there is one */
778         ndmca_test_close (sess);
779
780         rc = ndmca_mover_read (sess, offset, length);
781
782         rc = ndmca_test_check_expect (conn, rc, expect_err);
783
784         return rc;
785 }
786
787 int
788 ndmca_test_mover_close (struct ndm_session *sess, ndmp9_error expect_err)
789 {
790         struct ndmconn *        conn = sess->plumb.tape;
791         int                     rc;
792
793         /* close previous test if there is one */
794         ndmca_test_close (sess);
795
796         rc = ndmca_mover_close (sess);
797
798         rc = ndmca_test_check_expect (conn, rc, expect_err);
799
800         return rc;
801 }
802
803 int
804 ndmca_test_mover_set_record_size (struct ndm_session *sess,
805   ndmp9_error expect_err)
806 {
807         struct ndmconn *        conn = sess->plumb.tape;
808         struct ndm_control_agent *ca = &sess->control_acb;
809         int                     rc;
810
811         /* close previous test if there is one */
812         ndmca_test_close (sess);
813
814         switch (conn->protocol_version) {
815         default:        return -1234;
816
817 #ifndef NDMOS_OPTION_NO_NDMP2
818         case NDMP2VER:
819             NDMC_WITH(ndmp2_mover_set_record_size, NDMP2VER)
820                 request->len = ca->job.record_size;
821                 rc = NDMTEST_CALL(conn);
822             NDMC_ENDWITH
823             break;
824 #endif /* !NDMOS_OPTION_NO_NDMP2 */
825 #ifndef NDMOS_OPTION_NO_NDMP3
826         case NDMP3VER:
827             NDMC_WITH(ndmp3_mover_set_record_size, NDMP3VER)
828                 request->len = ca->job.record_size;
829                 rc = NDMTEST_CALL(conn);
830             NDMC_ENDWITH
831             break;
832 #endif /* !NDMOS_OPTION_NO_NDMP3 */
833 #ifndef NDMOS_OPTION_NO_NDMP4
834         case NDMP4VER:
835             NDMC_WITH(ndmp4_mover_set_record_size, NDMP4VER)
836                 request->len = ca->job.record_size;
837                 rc = NDMTEST_CALL(conn);
838             NDMC_ENDWITH
839             break;
840 #endif /* !NDMOS_OPTION_NO_NDMP4 */
841         }
842
843         return rc;
844 }
845 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */