s4: popt: Global replace of cmdline_credentials -> popt_get_cmdline_credentials().
[Samba.git] / source4 / torture / rpc / witness.c
blob4b44e91dbcf23ce705a14fcd45ec8c44f5e09300
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for rpc witness operations
5 Copyright (C) Guenther Deschner 2015
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
23 #include "torture/rpc/torture_rpc.h"
24 #include "librpc/gen_ndr/ndr_witness_c.h"
25 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
26 #include "librpc/gen_ndr/ndr_clusapi_c.h"
27 #include "param/param.h"
28 #include <tevent.h>
29 #include "lib/cmdline/popt_common.h"
31 struct torture_test_clusapi_state {
32 struct dcerpc_pipe *p;
35 struct torture_test_witness_state {
36 const char *net_name;
37 const char *share_name;
38 struct witness_interfaceList *list;
39 struct policy_handle context_handle;
40 struct torture_test_clusapi_state clusapi;
43 static bool test_witness_GetInterfaceList(struct torture_context *tctx,
44 struct dcerpc_pipe *p,
45 void *data)
47 struct dcerpc_binding_handle *b = p->binding_handle;
48 struct witness_GetInterfaceList r;
49 struct witness_interfaceList *l;
50 struct torture_test_witness_state *state =
51 (struct torture_test_witness_state *)data;
53 r.out.interface_list = &l;
55 torture_assert_ntstatus_ok(tctx,
56 dcerpc_witness_GetInterfaceList_r(b, tctx, &r),
57 "GetInterfaceList failed");
59 torture_assert_werr_ok(tctx,
60 r.out.result,
61 "GetInterfaceList failed");
63 state->list = l;
65 return true;
68 static bool find_sofs_share(struct torture_context *tctx,
69 const char **sofs_sharename)
71 struct dcerpc_pipe *p;
72 struct dcerpc_binding_handle *b;
73 struct srvsvc_NetShareEnumAll r;
74 struct srvsvc_NetShareInfoCtr info_ctr;
75 struct srvsvc_NetShareCtr1 ctr1;
76 uint32_t resume_handle = 0;
77 uint32_t totalentries = 0;
78 int i;
80 torture_assert_ntstatus_ok(tctx,
81 torture_rpc_connection_transport(tctx, &p, &ndr_table_srvsvc,
82 NCACN_NP, 0, 0),
83 "failed to setup srvsvc connection");
85 b = p->binding_handle;
87 ZERO_STRUCT(ctr1);
89 info_ctr.level = 1;
90 info_ctr.ctr.ctr1 = &ctr1;
92 r.in.server_unc = dcerpc_server_name(p);
93 r.in.max_buffer = -1;
94 r.in.info_ctr = &info_ctr;
95 r.in.resume_handle = &resume_handle;
96 r.out.totalentries = &totalentries;
97 r.out.info_ctr = &info_ctr;
98 r.out.resume_handle = &resume_handle;
100 torture_assert_ntstatus_ok(tctx,
101 dcerpc_srvsvc_NetShareEnumAll_r(b, tctx, &r),
102 "failed to call srvsvc_NetShareEnumAll");
104 torture_assert_werr_ok(tctx,
105 r.out.result,
106 "failed to call srvsvc_NetShareEnumAll");
108 for (i=0; i < r.out.info_ctr->ctr.ctr1->count; i++) {
110 if (r.out.info_ctr->ctr.ctr1->array[i].type == STYPE_CLUSTER_SOFS) {
111 *sofs_sharename = talloc_strdup(tctx, r.out.info_ctr->ctr.ctr1->array[i].name);
112 if (*sofs_sharename == NULL) {
113 return false;
115 torture_comment(tctx, "using SOFS share: %s\n", *sofs_sharename);
116 return true;
118 if (r.out.info_ctr->ctr.ctr1->array[i].type == STYPE_DISKTREE) {
119 *sofs_sharename = talloc_strdup(tctx, r.out.info_ctr->ctr.ctr1->array[i].name);
120 if (*sofs_sharename == NULL) {
121 return false;
123 torture_comment(tctx, "assuming SOFS share: %s\n", *sofs_sharename);
124 return true;
128 return false;
131 static bool init_witness_test_state(struct torture_context *tctx,
132 struct dcerpc_pipe *p,
133 struct torture_test_witness_state *state)
135 if (state->net_name == NULL) {
136 state->net_name = lpcfg_parm_string(tctx->lp_ctx, NULL, "torture", "net_name");
139 if (state->list == NULL) {
140 torture_assert(tctx,
141 test_witness_GetInterfaceList(tctx, p, state),
142 "failed to retrieve GetInterfaceList");
145 if (state->share_name == NULL) {
146 find_sofs_share(tctx, &state->share_name);
149 return true;
152 static bool test_witness_UnRegister_with_handle(struct torture_context *tctx,
153 struct dcerpc_pipe *p,
154 struct policy_handle *context_handle)
156 struct dcerpc_binding_handle *b = p->binding_handle;
157 struct witness_UnRegister r;
159 r.in.context_handle = *context_handle;
161 torture_assert_ntstatus_ok(tctx,
162 dcerpc_witness_UnRegister_r(b, tctx, &r),
163 "UnRegister failed");
165 torture_assert_werr_ok(tctx,
166 r.out.result,
167 "UnRegister failed");
169 /* make sure we are not able/allowed to reuse context handles after they
170 * have been unregistered */
172 torture_assert_ntstatus_ok(tctx,
173 dcerpc_witness_UnRegister_r(b, tctx, &r),
174 "UnRegister failed");
176 torture_assert_werr_equal(tctx,
177 r.out.result,
178 WERR_INVALID_PARAMETER,
179 "UnRegister failed");
181 return true;
184 static bool test_witness_UnRegister(struct torture_context *tctx,
185 struct dcerpc_pipe *p,
186 void *data)
188 /* acquire handle and free afterwards */
189 return true;
192 static bool get_ip_address_from_interface(struct torture_context *tctx,
193 struct witness_interfaceInfo *i,
194 const char **ip_address)
196 if (i->flags & WITNESS_INFO_IPv4_VALID) {
197 *ip_address = talloc_strdup(tctx, i->ipv4);
198 torture_assert(tctx, *ip_address, "talloc_strdup failed");
199 return true;
202 if (i->flags & WITNESS_INFO_IPv6_VALID) {
203 *ip_address = talloc_strdup(tctx, i->ipv6);
204 torture_assert(tctx, *ip_address, "talloc_strdup failed");
205 return true;
208 return false;
211 static bool check_valid_interface(struct torture_context *tctx,
212 struct witness_interfaceInfo *i)
214 /* continue looking for an interface that allows witness
215 * registration */
216 if (!(i->flags & WITNESS_INFO_WITNESS_IF)) {
217 return false;
220 /* witness should be available of course */
221 if (i->state != WITNESS_STATE_AVAILABLE) {
222 return false;
225 return true;
228 static bool test_witness_Register(struct torture_context *tctx,
229 struct dcerpc_pipe *p,
230 void *data)
232 struct dcerpc_binding_handle *b = p->binding_handle;
233 struct witness_Register r;
234 struct policy_handle context_handle;
235 struct torture_test_witness_state *state =
236 (struct torture_test_witness_state *)data;
237 int i;
239 struct {
240 enum witness_version version;
241 const char *net_name;
242 const char *ip_address;
243 const char *client_computer_name;
244 NTSTATUS expected_status;
245 WERROR expected_result;
246 } tests[] = {
248 .version = 0,
249 .expected_status = NT_STATUS_OK,
250 .expected_result = WERR_REVISION_MISMATCH
252 .version = 1,
253 .expected_status = NT_STATUS_OK,
254 .expected_result = WERR_REVISION_MISMATCH
256 .version = 123456,
257 .expected_status = NT_STATUS_OK,
258 .expected_result = WERR_REVISION_MISMATCH
260 .version = -1,
261 .expected_status = NT_STATUS_OK,
262 .expected_result = WERR_REVISION_MISMATCH
264 .version = WITNESS_V2,
265 .expected_status = NT_STATUS_OK,
266 .expected_result = WERR_REVISION_MISMATCH
268 .version = WITNESS_V1,
269 .net_name = "",
270 .ip_address = "",
271 .client_computer_name = "",
272 .expected_status = NT_STATUS_OK,
273 .expected_result = WERR_INVALID_PARAMETER
275 .version = WITNESS_V1,
276 .net_name = NULL,
277 .ip_address = NULL,
278 .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx),
279 .expected_status = NT_STATUS_OK,
280 .expected_result = WERR_INVALID_PARAMETER
282 .version = WITNESS_V2,
283 .net_name = NULL,
284 .ip_address = NULL,
285 .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx),
286 .expected_status = NT_STATUS_OK,
287 .expected_result = WERR_REVISION_MISMATCH
289 .version = WITNESS_V1,
290 .net_name = dcerpc_server_name(p),
291 .ip_address = NULL,
292 .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx),
293 .expected_status = NT_STATUS_OK,
294 .expected_result = WERR_INVALID_PARAMETER
299 for (i=0; i < ARRAY_SIZE(tests); i++) {
301 ZERO_STRUCT(r);
303 r.out.context_handle = &context_handle;
305 r.in.version = tests[i].version;
306 r.in.net_name = tests[i].net_name;
307 r.in.ip_address = tests[i].ip_address;
308 r.in.client_computer_name = tests[i].client_computer_name;
310 torture_assert_ntstatus_equal(tctx,
311 dcerpc_witness_Register_r(b, tctx, &r),
312 tests[i].expected_status,
313 "Register failed");
315 torture_assert_werr_equal(tctx,
316 r.out.result,
317 tests[i].expected_result,
318 "Register failed");
320 if (W_ERROR_IS_OK(r.out.result)) {
322 /* we have a handle, make sure to unregister it */
323 torture_assert(tctx,
324 test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
325 "Failed to unregister");
329 init_witness_test_state(tctx, p, state);
331 for (i=0; state->list && i < state->list->num_interfaces; i++) {
333 const char *ip_address;
334 struct witness_interfaceInfo interface = state->list->interfaces[i];
336 if (!check_valid_interface(tctx, &interface)) {
337 continue;
340 torture_assert(tctx,
341 get_ip_address_from_interface(tctx, &interface, &ip_address),
342 "failed to get ip_address from interface");
344 r.in.version = WITNESS_V1;
345 r.in.net_name = state->net_name;
346 r.in.ip_address = ip_address;
348 torture_assert_ntstatus_ok(tctx,
349 dcerpc_witness_Register_r(b, tctx, &r),
350 "Register failed");
352 torture_assert_werr_ok(tctx,
353 r.out.result,
354 "Register failed");
356 torture_assert(tctx,
357 test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
358 "Failed to unregister");
361 return true;
364 static bool test_witness_RegisterEx(struct torture_context *tctx,
365 struct dcerpc_pipe *p,
366 void *data)
368 struct dcerpc_binding_handle *b = p->binding_handle;
369 struct witness_RegisterEx r;
370 struct policy_handle context_handle;
371 struct torture_test_witness_state *state =
372 (struct torture_test_witness_state *)data;
373 int i;
375 struct {
376 enum witness_version version;
377 const char *net_name;
378 const char *ip_address;
379 const char *client_computer_name;
380 NTSTATUS expected_status;
381 WERROR expected_result;
382 } tests[] = {
384 .version = 0,
385 .expected_status = NT_STATUS_OK,
386 .expected_result = WERR_REVISION_MISMATCH
388 .version = 1,
389 .expected_status = NT_STATUS_OK,
390 .expected_result = WERR_REVISION_MISMATCH
392 .version = 123456,
393 .expected_status = NT_STATUS_OK,
394 .expected_result = WERR_REVISION_MISMATCH
396 .version = -1,
397 .expected_status = NT_STATUS_OK,
398 .expected_result = WERR_REVISION_MISMATCH
400 .version = WITNESS_V1,
401 .expected_status = NT_STATUS_OK,
402 .expected_result = WERR_REVISION_MISMATCH
404 .version = WITNESS_V2,
405 .net_name = "",
406 .ip_address = "",
407 .client_computer_name = "",
408 .expected_status = NT_STATUS_OK,
409 .expected_result = WERR_INVALID_PARAMETER
411 .version = WITNESS_V2,
412 .net_name = NULL,
413 .ip_address = NULL,
414 .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx),
415 .expected_status = NT_STATUS_OK,
416 .expected_result = WERR_INVALID_PARAMETER
418 .version = WITNESS_V1,
419 .net_name = NULL,
420 .ip_address = NULL,
421 .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx),
422 .expected_status = NT_STATUS_OK,
423 .expected_result = WERR_REVISION_MISMATCH
425 .version = WITNESS_V2,
426 .net_name = dcerpc_server_name(p),
427 .ip_address = NULL,
428 .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx),
429 .expected_status = NT_STATUS_OK,
430 .expected_result = WERR_INVALID_PARAMETER
435 for (i=0; i < ARRAY_SIZE(tests); i++) {
437 ZERO_STRUCT(r);
439 r.out.context_handle = &context_handle;
441 r.in.version = tests[i].version;
442 r.in.net_name = tests[i].net_name;
443 r.in.ip_address = tests[i].ip_address;
444 r.in.client_computer_name = tests[i].client_computer_name;
446 torture_assert_ntstatus_equal(tctx,
447 dcerpc_witness_RegisterEx_r(b, tctx, &r),
448 tests[i].expected_status,
449 "RegisterEx failed");
451 torture_assert_werr_equal(tctx,
452 r.out.result,
453 tests[i].expected_result,
454 "RegisterEx failed");
456 if (W_ERROR_IS_OK(r.out.result)) {
458 /* we have a handle, make sure to unregister it */
459 torture_assert(tctx,
460 test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
461 "Failed to unregister");
465 init_witness_test_state(tctx, p, state);
467 for (i=0; state->list && i < state->list->num_interfaces; i++) {
469 const char *ip_address;
470 struct witness_interfaceInfo interface = state->list->interfaces[i];
472 if (!check_valid_interface(tctx, &interface)) {
473 continue;
476 torture_assert(tctx,
477 get_ip_address_from_interface(tctx, &interface, &ip_address),
478 "failed to get ip_address from interface");
480 r.in.version = WITNESS_V2;
481 r.in.net_name = state->net_name;
482 r.in.ip_address = ip_address;
485 * a valid request with an invalid sharename fails with
486 * WERR_INVALID_STATE
488 r.in.share_name = "any_invalid_share_name";
490 torture_assert_ntstatus_ok(tctx,
491 dcerpc_witness_RegisterEx_r(b, tctx, &r),
492 "RegisterEx failed");
494 torture_assert_werr_equal(tctx,
495 r.out.result,
496 WERR_INVALID_STATE,
497 "RegisterEx failed");
499 r.in.share_name = NULL;
501 torture_assert_ntstatus_ok(tctx,
502 dcerpc_witness_RegisterEx_r(b, tctx, &r),
503 "RegisterEx failed");
505 torture_assert_werr_ok(tctx,
506 r.out.result,
507 "RegisterEx failed");
509 torture_assert(tctx,
510 test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
511 "Failed to unregister");
514 return true;
517 static bool setup_clusapi_connection(struct torture_context *tctx,
518 struct torture_test_witness_state *s)
520 struct dcerpc_binding *binding;
522 if (s->clusapi.p) {
523 return true;
526 torture_assert_ntstatus_ok(tctx,
527 torture_rpc_binding(tctx, &binding),
528 "failed to retrieve torture binding");
530 torture_assert_ntstatus_ok(tctx,
531 dcerpc_binding_set_transport(binding, NCACN_IP_TCP),
532 "failed to set transport");
534 torture_assert_ntstatus_ok(tctx,
535 dcerpc_binding_set_flags(binding, DCERPC_SEAL, 0),
536 "failed to set dcerpc flags");
538 torture_assert_ntstatus_ok(tctx,
539 dcerpc_pipe_connect_b(tctx, &s->clusapi.p, binding,
540 &ndr_table_clusapi,
541 popt_get_cmdline_credentials(),
542 tctx->ev, tctx->lp_ctx),
543 "failed to connect dcerpc pipe");
545 return true;
548 #if 0
549 static bool cluster_get_nodes(struct torture_context *tctx,
550 struct torture_test_witness_state *s)
552 struct clusapi_CreateEnum r;
553 struct ENUM_LIST *ReturnEnum;
554 WERROR rpc_status;
555 struct dcerpc_binding_handle *b;
557 torture_assert(tctx,
558 setup_clusapi_connection(tctx, s),
559 "failed to setup clusapi connection");
561 b = s->clusapi.p->binding_handle;
563 r.in.dwType = CLUSTER_ENUM_NODE;
564 r.out.ReturnEnum = &ReturnEnum;
565 r.out.rpc_status = &rpc_status;
567 torture_assert_ntstatus_ok(tctx,
568 dcerpc_clusapi_CreateEnum_r(b, tctx, &r),
569 "failed to enumerate nodes");
571 return true;
573 #endif
575 static bool test_GetResourceState_int(struct torture_context *tctx,
576 struct dcerpc_pipe *p,
577 struct policy_handle *hResource,
578 enum clusapi_ClusterResourceState *State)
580 struct dcerpc_binding_handle *b = p->binding_handle;
581 struct clusapi_GetResourceState r;
582 const char *NodeName;
583 const char *GroupName;
584 WERROR rpc_status;
586 r.in.hResource = *hResource;
587 r.out.State = State;
588 r.out.NodeName = &NodeName;
589 r.out.GroupName = &GroupName;
590 r.out.rpc_status = &rpc_status;
592 torture_assert_ntstatus_ok(tctx,
593 dcerpc_clusapi_GetResourceState_r(b, tctx, &r),
594 "GetResourceState failed");
595 torture_assert_werr_ok(tctx,
596 r.out.result,
597 "GetResourceState failed");
599 return true;
602 static bool toggle_cluster_resource_state(struct torture_context *tctx,
603 struct dcerpc_pipe *p,
604 const char *resource_name,
605 enum clusapi_ClusterResourceState *old_state,
606 enum clusapi_ClusterResourceState *new_state)
608 struct policy_handle hResource;
609 enum clusapi_ClusterResourceState State;
611 torture_assert(tctx,
612 test_OpenResource_int(tctx, p, resource_name, &hResource),
613 "failed to open resource");
614 torture_assert(tctx,
615 test_GetResourceState_int(tctx, p, &hResource, &State),
616 "failed to query resource state");
618 if (old_state) {
619 *old_state = State;
622 switch (State) {
623 case ClusterResourceOffline:
624 if (!test_OnlineResource_int(tctx, p, &hResource)) {
625 test_CloseResource_int(tctx, p, &hResource);
626 torture_warning(tctx, "failed to set resource online");
627 return false;
629 break;
630 case ClusterResourceOnline:
631 if (!test_OfflineResource_int(tctx, p, &hResource)) {
632 test_CloseResource_int(tctx, p, &hResource);
633 torture_warning(tctx, "failed to set resource offline");
634 return false;
636 break;
638 default:
639 break;
642 torture_assert(tctx,
643 test_GetResourceState_int(tctx, p, &hResource, &State),
644 "failed to query resource state");
646 if (new_state) {
647 *new_state = State;
650 test_CloseResource_int(tctx, p, &hResource);
652 return true;
655 static bool test_witness_AsyncNotify(struct torture_context *tctx,
656 struct dcerpc_pipe *p,
657 void *data)
659 struct dcerpc_binding_handle *b = p->binding_handle;
660 struct witness_AsyncNotify r;
661 struct witness_notifyResponse *response;
662 struct torture_test_witness_state *state =
663 (struct torture_test_witness_state *)data;
664 int i;
666 init_witness_test_state(tctx, p, state);
668 setup_clusapi_connection(tctx, state);
670 for (i=0; state->list && i < state->list->num_interfaces; i++) {
672 const char *ip_address;
673 struct witness_interfaceInfo interface = state->list->interfaces[i];
674 struct witness_Register reg;
675 struct tevent_req *req;
676 enum clusapi_ClusterResourceState old_state, new_state;
678 if (!check_valid_interface(tctx, &interface)) {
679 continue;
682 torture_assert(tctx,
683 get_ip_address_from_interface(tctx, &interface, &ip_address),
684 "failed to get ip_address from interface");
686 reg.in.version = WITNESS_V1;
687 reg.in.net_name = state->net_name;
688 reg.in.ip_address = ip_address;
689 reg.in.client_computer_name = lpcfg_netbios_name(tctx->lp_ctx);
690 reg.out.context_handle = &state->context_handle;
692 torture_assert_ntstatus_ok(tctx,
693 dcerpc_witness_Register_r(b, tctx, &reg),
694 "Register failed");
696 torture_assert_werr_ok(tctx,
697 reg.out.result,
698 "Register failed");
700 r.in.context_handle = state->context_handle;
701 r.out.response = &response;
703 req = dcerpc_witness_AsyncNotify_r_send(tctx, tctx->ev, b, &r);
704 torture_assert(tctx, req, "failed to create request");
706 torture_assert(tctx,
707 toggle_cluster_resource_state(tctx, state->clusapi.p, state->net_name, &old_state, &new_state),
708 "failed to toggle cluster resource state");
709 torture_assert(tctx, old_state != new_state, "failed to change cluster resource state");
711 torture_assert(tctx,
712 tevent_req_poll(req, tctx->ev),
713 "failed to call event loop");
715 torture_assert_ntstatus_ok(tctx,
716 dcerpc_witness_AsyncNotify_r_recv(req, tctx),
717 "failed to receive reply");
719 torture_assert_int_equal(tctx, response->num, 1, "num");
720 torture_assert_int_equal(tctx, response->type, WITNESS_NOTIFY_RESOURCE_CHANGE, "type");
723 * TODO: find out how ClusterResourceOfflinePending and
724 * ClusterResourceOnlinePending are represented as witness
725 * types.
728 if (new_state == ClusterResourceOffline) {
729 torture_assert_int_equal(tctx, response->messages[0].resource_change.type, WITNESS_RESOURCE_STATE_UNAVAILABLE, "resource_change.type");
731 if (new_state == ClusterResourceOnline) {
732 torture_assert_int_equal(tctx, response->messages[0].resource_change.type, WITNESS_RESOURCE_STATE_AVAILABLE, "resource_change.type");
734 torture_assert(tctx,
735 test_witness_UnRegister_with_handle(tctx, p, &state->context_handle),
736 "Failed to unregister");
738 ZERO_STRUCT(state->context_handle);
740 torture_assert(tctx,
741 toggle_cluster_resource_state(tctx, state->clusapi.p, state->net_name, &old_state, &new_state),
742 "failed to toggle cluster resource state");
743 torture_assert(tctx, old_state != new_state, "failed to change cluster resource state");
746 return true;
749 static bool test_do_witness_RegisterEx(struct torture_context *tctx,
750 struct dcerpc_binding_handle *b,
751 uint32_t version,
752 const char *net_name,
753 const char *share_name,
754 const char *ip_address,
755 const char *client_computer_name,
756 uint32_t flags,
757 uint32_t timeout,
758 struct policy_handle *context_handle)
760 struct witness_RegisterEx r;
762 r.in.version = version;
763 r.in.net_name = net_name;
764 r.in.share_name = NULL;
765 r.in.ip_address = ip_address;
766 r.in.client_computer_name = client_computer_name;
767 r.in.flags = flags;
768 r.in.timeout = timeout;
769 r.out.context_handle = context_handle;
771 torture_assert_ntstatus_ok(tctx,
772 dcerpc_witness_RegisterEx_r(b, tctx, &r),
773 "RegisterEx failed");
775 torture_assert_werr_ok(tctx,
776 r.out.result,
777 "RegisterEx failed");
779 return true;
782 static void torture_subunit_report_time(struct torture_context *tctx)
784 struct timespec tp;
785 struct tm *tmp;
786 char timestr[200];
788 if (clock_gettime(CLOCK_REALTIME, &tp) != 0) {
789 torture_comment(tctx, "failed to call clock_gettime");
790 return;
793 tmp = localtime(&tp.tv_sec);
794 if (!tmp) {
795 torture_comment(tctx, "failed to call localtime");
796 return;
799 if (strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tmp) <= 0) {
800 torture_comment(tctx, "failed to call strftime");
801 return;
804 torture_comment(tctx, "time: %s.%06ld\n", timestr, tp.tv_nsec / 1000);
807 static bool test_witness_AsyncNotify_timeouts(struct torture_context *tctx,
808 struct dcerpc_pipe *p,
809 void *data)
811 struct dcerpc_binding_handle *b = p->binding_handle;
812 struct witness_AsyncNotify r;
813 struct witness_notifyResponse *response;
814 struct torture_test_witness_state *state =
815 (struct torture_test_witness_state *)data;
816 int i;
818 init_witness_test_state(tctx, p, state);
820 setup_clusapi_connection(tctx, state);
822 for (i=0; state->list && i < state->list->num_interfaces; i++) {
824 const char *ip_address;
825 struct witness_interfaceInfo interface = state->list->interfaces[i];
826 uint32_t timeouts[] = {
827 0, 1, 10, 100, 120
829 int t;
830 uint32_t old_timeout;
832 if (!check_valid_interface(tctx, &interface)) {
833 continue;
836 torture_assert(tctx,
837 get_ip_address_from_interface(tctx, &interface, &ip_address),
838 "failed to get ip_address from interface");
840 for (t=0; t < ARRAY_SIZE(timeouts); t++) {
842 torture_comment(tctx, "Testing Async Notify with timeout of %d milliseconds", timeouts[t]);
844 torture_assert(tctx,
845 test_do_witness_RegisterEx(tctx, b,
846 WITNESS_V2,
847 state->net_name,
848 NULL,
849 ip_address,
850 lpcfg_netbios_name(tctx->lp_ctx),
852 timeouts[t],
853 &state->context_handle),
854 "failed to RegisterEx");
856 r.in.context_handle = state->context_handle;
857 r.out.response = &response;
859 old_timeout = dcerpc_binding_handle_set_timeout(b, UINT_MAX);
861 torture_subunit_report_time(tctx);
863 torture_assert_ntstatus_ok(tctx,
864 dcerpc_witness_AsyncNotify_r(b, tctx, &r),
865 "AsyncNotify failed");
866 torture_assert_werr_equal(tctx,
867 r.out.result,
868 WERR_TIMEOUT,
869 "AsyncNotify failed");
871 torture_subunit_report_time(tctx);
873 dcerpc_binding_handle_set_timeout(b, old_timeout);
875 torture_assert(tctx,
876 test_witness_UnRegister_with_handle(tctx, p, &state->context_handle),
877 "Failed to unregister");
879 ZERO_STRUCT(state->context_handle);
883 return true;
886 struct torture_suite *torture_rpc_witness(TALLOC_CTX *mem_ctx)
888 struct torture_rpc_tcase *tcase;
889 struct torture_suite *suite = torture_suite_create(mem_ctx, "witness");
890 struct torture_test_witness_state *state;
892 tcase = torture_suite_add_rpc_iface_tcase(suite, "witness",
893 &ndr_table_witness);
895 state = talloc_zero(tcase, struct torture_test_witness_state);
897 torture_rpc_tcase_add_test_ex(tcase, "GetInterfaceList",
898 test_witness_GetInterfaceList, state);
899 torture_rpc_tcase_add_test_ex(tcase, "Register",
900 test_witness_Register, state);
901 torture_rpc_tcase_add_test_ex(tcase, "UnRegister",
902 test_witness_UnRegister, state);
903 torture_rpc_tcase_add_test_ex(tcase, "RegisterEx",
904 test_witness_RegisterEx, state);
905 torture_rpc_tcase_add_test_ex(tcase, "AsyncNotify",
906 test_witness_AsyncNotify, state);
907 torture_rpc_tcase_add_test_ex(tcase, "AsyncNotify_timeouts",
908 test_witness_AsyncNotify_timeouts, state);
910 return suite;