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
38 #include "ndmagents.h"
39
40
41 #if !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && \
42 !defined(NDMOS_OPTION_NO_TEST_AGENTS)
43
ndmca_test_query_conn_types(struct ndm_session * sess,struct ndmconn * ref_conn)44 int ndmca_test_query_conn_types(struct ndm_session* sess,
45 struct ndmconn* ref_conn)
46 {
47 struct ndmconn* conn = ref_conn;
48 struct ndm_control_agent* ca = sess->control_acb;
49 int rc;
50 unsigned int i;
51
52 switch (conn->protocol_version) {
53 default:
54 return -1234;
55
56 #ifndef NDMOS_OPTION_NO_NDMP2
57 case NDMP2VER:
58 NDMC_WITH_VOID_REQUEST(ndmp2_config_get_mover_type, NDMP2VER)
59 rc = NDMC_CALL(conn);
60 if (rc) {
61 ndmalogf(sess, "Test", 1, "GET_MOVER_TYPE failed");
62 return rc;
63 }
64
65 for (i = 0; i < reply->methods.methods_len; i++) {
66 switch (reply->methods.methods_val[i]) {
67 case NDMP2_ADDR_LOCAL:
68 ca->has_local_addr = 1;
69 break;
70 case NDMP2_ADDR_TCP:
71 ca->has_tcp_addr = 1;
72 break;
73 default:
74 break;
75 }
76 }
77
78 NDMC_FREE_REPLY();
79 NDMC_ENDWITH
80 break;
81 #endif /* !NDMOS_OPTION_NO_NDMP2 */
82
83 #ifndef NDMOS_OPTION_NO_NDMP3
84 case NDMP3VER:
85 NDMC_WITH_VOID_REQUEST(ndmp3_config_get_connection_type, NDMP3VER)
86 rc = NDMC_CALL(conn);
87 if (rc) {
88 ndmalogf(sess, "Test", 1, "GET_CONNECTION_TYPE failed");
89 return rc;
90 }
91
92 for (i = 0; i < reply->addr_types.addr_types_len; i++) {
93 switch (reply->addr_types.addr_types_val[i]) {
94 case NDMP3_ADDR_LOCAL:
95 ca->has_local_addr = 1;
96 break;
97 case NDMP3_ADDR_TCP:
98 ca->has_tcp_addr = 1;
99 break;
100 default:
101 break;
102 }
103 }
104 NDMC_FREE_REPLY();
105 NDMC_ENDWITH
106 break;
107 #endif /* !NDMOS_OPTION_NO_NDMP3 */
108
109 #ifndef NDMOS_OPTION_NO_NDMP4
110 case NDMP4VER:
111 NDMC_WITH_VOID_REQUEST(ndmp4_config_get_connection_type, NDMP4VER)
112 rc = NDMC_CALL(conn);
113 if (rc) {
114 ndmalogf(sess, "Test", 1, "GET_CONNECTION_TYPE failed");
115 return rc;
116 }
117
118 for (i = 0; i < reply->addr_types.addr_types_len; i++) {
119 switch (reply->addr_types.addr_types_val[i]) {
120 case NDMP4_ADDR_LOCAL:
121 ca->has_local_addr = 1;
122 break;
123 case NDMP4_ADDR_TCP:
124 ca->has_tcp_addr = 1;
125 break;
126 default:
127 break;
128 }
129 }
130 NDMC_FREE_REPLY();
131 NDMC_ENDWITH
132 break;
133 #endif /* !NDMOS_OPTION_NO_NDMP4 */
134 }
135
136 return 0;
137 }
138
139
ndmca_test_load_tape(struct ndm_session * sess)140 int ndmca_test_load_tape(struct ndm_session* sess)
141 {
142 struct ndm_control_agent* ca = sess->control_acb;
143 int rc;
144
145 ca->tape_mode = NDMP9_TAPE_READ_MODE;
146 ca->is_label_op = 1;
147
148 rc = ndmca_op_robot_startup(sess, 1);
149 if (rc) return rc;
150
151 rc = ndmca_connect_tape_agent(sess);
152 if (rc) {
153 ndmconn_destruct(sess->plumb.tape);
154 sess->plumb.tape = NULL;
155 return rc; /* already tattled */
156 }
157
158 rc = ndmca_media_load_first(sess);
159 if (rc) return rc;
160
161 ndmca_tape_close(sess);
162
163 return 0;
164 }
165
ndmca_test_unload_tape(struct ndm_session * sess)166 int ndmca_test_unload_tape(struct ndm_session* sess)
167 {
168 ndmca_tape_open(sess);
169
170 ndmca_media_unload_current(sess);
171
172 return 0;
173 }
174
ndmca_test_check_expect_errs(struct ndmconn * conn,int rc,ndmp9_error expect_errs[])175 int ndmca_test_check_expect_errs(struct ndmconn* conn,
176 int rc,
177 ndmp9_error expect_errs[])
178 {
179 struct ndm_session* sess = conn->context;
180 int protocol_version = conn->protocol_version;
181 struct ndmp_xa_buf* xa = &conn->call_xa_buf;
182 unsigned msg = xa->request.header.message;
183 char* msgname = ndmp_message_to_str(protocol_version, msg);
184 ndmp9_error reply_error = conn->last_reply_error;
185 int i;
186
187 /* make sure we have a 'test' active */
188 ndmca_test_open(sess, msgname, ndmp9_error_to_str(expect_errs[0]));
189
190 if (rc >= 0) {
191 /* Call succeeded. Body valid */
192 rc = 1;
193 for (i = 0; (int)expect_errs[i] >= 0; i++) {
194 if (reply_error == expect_errs[i]) {
195 rc = 0;
196 break;
197 }
198 }
199
200 if (rc) {
201 if (reply_error != NDMP9_NO_ERR && expect_errs[0] != NDMP9_NO_ERR) {
202 /* both are errors, don't be picky */
203 rc = 2;
204 } else {
205 /* intolerable mismatch */
206 }
207 } else {
208 /* Worked as expected */
209 }
210 }
211
212 if (rc != 0) {
213 char tmpbuf[128];
214
215 for (i = 0; (int)expect_errs[i] >= 0; i++) {
216 ndmalogf(sess, "Test", 1, "%s #%d -- .... %s %s",
217 sess->control_acb->test_phase, sess->control_acb->test_step,
218 (i == 0) ? "expected" : "or",
219 ndmp9_error_to_str(expect_errs[i]));
220 }
221
222 snprintf(tmpbuf, sizeof(tmpbuf), "got %s (error expected)",
223 ndmp9_error_to_str(reply_error));
224
225 if (rc == 2)
226 ndmca_test_warn(sess, tmpbuf);
227 else
228 ndmca_test_fail(sess, tmpbuf);
229
230 ndma_tattle(conn, xa, rc);
231
232 if (rc == 2) rc = 0;
233 }
234
235 return rc;
236 }
237
ndmca_test_check_expect(struct ndmconn * conn,int rc,ndmp9_error expect_err)238 int ndmca_test_check_expect(struct ndmconn* conn,
239 int rc,
240 ndmp9_error expect_err)
241 {
242 ndmp9_error errs[2];
243
244 errs[0] = expect_err;
245 errs[1] = -1;
246
247 return ndmca_test_check_expect_errs(conn, rc, errs);
248 }
249
ndmca_test_check_expect_no_err(struct ndmconn * conn,int rc)250 int ndmca_test_check_expect_no_err(struct ndmconn* conn, int rc)
251 {
252 return ndmca_test_check_expect(conn, rc, NDMP9_NO_ERR);
253 }
254
ndmca_test_check_expect_illegal_state(struct ndmconn * conn,int rc)255 int ndmca_test_check_expect_illegal_state(struct ndmconn* conn, int rc)
256 {
257 return ndmca_test_check_expect(conn, rc, NDMP9_ILLEGAL_STATE_ERR);
258 }
259
ndmca_test_check_expect_illegal_args(struct ndmconn * conn,int rc)260 int ndmca_test_check_expect_illegal_args(struct ndmconn* conn, int rc)
261 {
262 return ndmca_test_check_expect(conn, rc, NDMP9_ILLEGAL_ARGS_ERR);
263 }
264
265
ndmca_test_call(struct ndmconn * conn,struct ndmp_xa_buf * xa,ndmp9_error expect_err)266 int ndmca_test_call(struct ndmconn* conn,
267 struct ndmp_xa_buf* xa,
268 ndmp9_error expect_err)
269 {
270 struct ndm_session* sess = conn->context;
271 int protocol_version = conn->protocol_version;
272 unsigned msg = xa->request.header.message;
273 char* msgname = ndmp_message_to_str(protocol_version, msg);
274 unsigned reply_error;
275 int rc;
276
277 /* close previous test if there is one */
278 ndmca_test_close(sess);
279
280 /* open new 'test' */
281 ndmca_test_open(sess, msgname, ndmp9_error_to_str(expect_err));
282
283 rc = ndma_call_no_tattle(conn, xa);
284
285 reply_error = ndmnmb_get_reply_error(&xa->reply);
286
287 if (rc >= 0) {
288 /* Call succeeded. Body valid */
289 if (reply_error == expect_err) {
290 /* Worked exactly as expected */
291 rc = 0;
292 } else if (reply_error != NDMP9_NO_ERR && expect_err != NDMP9_NO_ERR) {
293 /* both are errors, don't be picky about the codes */
294 rc = 2;
295 } else {
296 /* intolerable mismatch */
297 rc = 1;
298 }
299 }
300
301 if (rc != 0) {
302 char tmpbuf[128];
303 snprintf(tmpbuf, sizeof(tmpbuf), "got %s (call)",
304 ndmp9_error_to_str(reply_error));
305 if (rc == 2)
306 ndmca_test_warn(sess, tmpbuf);
307 else
308 ndmca_test_fail(sess, tmpbuf);
309
310 ndma_tattle(conn, xa, rc);
311
312 if (rc == 2) rc = 0;
313 }
314
315 return rc;
316 }
317
318 /*
319 * start or open a test if not already opened
320 */
ndmca_test_open(struct ndm_session * sess,char * test_name,char * sub_test_name)321 void ndmca_test_open(struct ndm_session* sess,
322 char* test_name,
323 char* sub_test_name)
324 {
325 static char test_name_buf[512];
326
327 if (sess->control_acb->active_test == 0) {
328 /* record name */
329 if (sub_test_name)
330 snprintf(test_name_buf, sizeof(test_name_buf), "%s/%s", test_name,
331 sub_test_name);
332 else
333 strcpy(test_name_buf, test_name);
334 sess->control_acb->active_test = test_name_buf;
335
336 /* make sure flags are cleared */
337 sess->control_acb->active_test_failed = (char*)0;
338 sess->control_acb->active_test_warned = (char*)0;
339 }
340 }
341
ndmca_test_warn(struct ndm_session * sess,char * warn_msg)342 void ndmca_test_warn(struct ndm_session* sess, char* warn_msg)
343 {
344 static char warn_msg_buf[512];
345
346 ndmca_test_open(sess, "UNKNOWN WARN", 0);
347
348 strcpy(warn_msg_buf, warn_msg);
349 sess->control_acb->active_test_warned = warn_msg_buf;
350 }
351
ndmca_test_fail(struct ndm_session * sess,char * fail_msg)352 void ndmca_test_fail(struct ndm_session* sess, char* fail_msg)
353 {
354 static char fail_msg_buf[512];
355
356 ndmca_test_open(sess, "UNKNOWN FAIL", 0);
357
358 strcpy(fail_msg_buf, fail_msg);
359 sess->control_acb->active_test_failed = fail_msg_buf;
360 }
361
362
363 /*
364 * close or end a test if not already closed
365 */
ndmca_test_close(struct ndm_session * sess)366 void ndmca_test_close(struct ndm_session* sess)
367 {
368 if (sess->control_acb->active_test != 0) {
369 /* count test */
370 sess->control_acb->n_step_tests++;
371
372 /* display results */
373 if (sess->control_acb->active_test_failed) {
374 ndmalogf(sess, "Test", 1, "%s #%d -- Failed %s %s",
375 sess->control_acb->test_phase, sess->control_acb->test_step,
376 sess->control_acb->active_test,
377 sess->control_acb->active_test_failed);
378 sess->control_acb->n_step_fail++;
379 exit(1);
380 } else if (sess->control_acb->active_test_warned) {
381 ndmalogf(sess, "Test", 1, "%s #%d -- Almost %s %s",
382 sess->control_acb->test_phase, sess->control_acb->test_step,
383 sess->control_acb->active_test,
384 sess->control_acb->active_test_warned);
385 sess->control_acb->n_step_warn++;
386 exit(1);
387 } else {
388 ndmalogf(sess, "Test", 2, "%s #%d -- Passed %s",
389 sess->control_acb->test_phase, sess->control_acb->test_step,
390 sess->control_acb->active_test);
391 sess->control_acb->n_step_pass++;
392 }
393
394 /* clear flags */
395 sess->control_acb->active_test = (char*)0;
396 sess->control_acb->active_test_failed = (char*)0;
397 sess->control_acb->active_test_warned = (char*)0;
398
399 /* advance test count */
400 sess->control_acb->test_step++;
401 }
402 }
403
404
405 /*
406 * start a test phase (part of a series)
407 */
ndmca_test_phase(struct ndm_session * sess,char * test_phase,char * desc)408 void ndmca_test_phase(struct ndm_session* sess, char* test_phase, char* desc)
409 {
410 ndmalogf(sess, "TEST", 0, "Test %s -- %s", test_phase, desc);
411
412 sess->control_acb->test_phase = test_phase;
413 sess->control_acb->test_step = 1;
414 sess->control_acb->n_step_pass = 0;
415 sess->control_acb->n_step_fail = 0;
416 sess->control_acb->n_step_warn = 0;
417 sess->control_acb->n_step_tests = 0;
418 }
419
ndmca_test_log_step(struct ndm_session * sess,int level,char * msg)420 void ndmca_test_log_step(struct ndm_session* sess, int level, char* msg)
421 {
422 int had_active = (sess->control_acb->active_test != 0);
423
424 ndmalogf(sess, "Test", level, "%s #%d -- %s", sess->control_acb->test_phase,
425 sess->control_acb->test_step, msg);
426
427 /* in case we have a open test -- close it */
428 ndmca_test_close(sess);
429
430 /* advance test count if we didn't have an active test */
431 if (!had_active) sess->control_acb->test_step++;
432 }
433
ndmca_test_log_note(struct ndm_session * sess,int level,char * msg)434 void ndmca_test_log_note(struct ndm_session* sess, int level, char* msg)
435 {
436 ndmalogf(sess, "Test", level, "%s #%d %s", sess->control_acb->test_phase,
437 sess->control_acb->test_step, msg);
438 }
439
440 /*
441 * finish a test phase (part of a series)
442 */
ndmca_test_done_phase(struct ndm_session * sess)443 void ndmca_test_done_phase(struct ndm_session* sess)
444 {
445 struct ndm_control_agent* ca = sess->control_acb;
446 char* status;
447 int had_active = (sess->control_acb->active_test != 0);
448
449 /* close previous test if there is one */
450 ndmca_test_close(sess);
451
452 if (ca->n_step_fail)
453 status = "Failed";
454 else if (ca->n_step_warn)
455 status = "Almost";
456 else if (ca->n_step_pass > 0)
457 status = "Passed";
458 else
459 status = "Whiffed";
460
461 ndmalogf(sess, "TEST", 0, "Test %s %s -- pass=%d warn=%d fail=%d (total %d)",
462 ca->test_phase, status, ca->n_step_pass, ca->n_step_warn,
463 ca->n_step_fail, ca->n_step_tests);
464
465 ca->total_n_step_pass += ca->n_step_pass;
466 ca->total_n_step_warn += ca->n_step_warn;
467 ca->total_n_step_fail += ca->n_step_fail;
468 ca->total_n_step_tests += ca->n_step_tests;
469
470 /* advance test count if we didn't have an active test so
471 * clean up phases have a new test count
472 */
473 if (!had_active) sess->control_acb->test_step++;
474 }
475
476 /*
477 * finish a test series (which may include test phases)
478 */
ndmca_test_done_series(struct ndm_session * sess,char * series_name)479 void ndmca_test_done_series(struct ndm_session* sess, char* series_name)
480 {
481 struct ndm_control_agent* ca = sess->control_acb;
482 char* status;
483
484 /* close previous test if there is one */
485 ndmca_test_close(sess);
486
487 if (ca->total_n_step_fail)
488 status = "Failed";
489 else if (ca->total_n_step_warn)
490 status = "Almost";
491 else
492 status = "Passed";
493
494 ndmalogf(sess, "TEST", 0, "FINAL %s %s -- pass=%d warn=%d fail=%d (total %d)",
495 series_name, status, ca->total_n_step_pass, ca->total_n_step_warn,
496 ca->total_n_step_fail, ca->total_n_step_tests);
497 }
498
499
ndmca_test_fill_data(char * buf,int bufsize,int recno,int fileno)500 void ndmca_test_fill_data(char* buf, int bufsize, int recno, int fileno)
501 {
502 char* src;
503 char* srcend;
504 char* dst = buf;
505 char* dstend = buf + bufsize;
506 uint16_t sequence = 0;
507 struct {
508 uint16_t fileno;
509 uint16_t sequence;
510 uint32_t recno;
511 } x;
512
513 x.fileno = fileno;
514 x.recno = recno;
515
516 srcend = (char*)&x;
517 srcend += sizeof x;
518
519 while (dst < dstend) {
520 x.sequence = sequence++;
521 src = (char*)&x;
522
523 while (src < srcend && dst < dstend) *dst++ = *src++;
524 }
525 }
526 #endif /* !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && \
527 !defined(NDMOS_OPTION_NO_TEST_AGENTS) */
528