LCOV - code coverage report
Current view: top level - source4/lib/messaging/tests - irpc.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 122 128 95.3 %
Date: 2024-04-21 15:09:00 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    local test for irpc code
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/events/events.h"
      24             : #include "lib/messaging/irpc.h"
      25             : #include "librpc/gen_ndr/ndr_echo.h"
      26             : #include "librpc/gen_ndr/ndr_echo_c.h"
      27             : #include "torture/torture.h"
      28             : #include "cluster/cluster.h"
      29             : #include "param/param.h"
      30             : #include "torture/local/proto.h"
      31             : 
      32             : const uint32_t MSG_ID1 = 1, MSG_ID2 = 2;
      33             : 
      34             : static bool test_debug;
      35             : 
      36             : struct irpc_test_data
      37             : {
      38             :         struct imessaging_context *msg_ctx1, *msg_ctx2;
      39             :         struct tevent_context *ev;
      40             : };
      41             : 
      42             : /*
      43             :   serve up AddOne over the irpc system
      44             : */
      45       16533 : static NTSTATUS irpc_AddOne(struct irpc_message *irpc, struct echo_AddOne *r)
      46             : {
      47       16533 :         *r->out.out_data = r->in.in_data + 1;
      48       16533 :         if (test_debug) {
      49       16538 :                 printf("irpc_AddOne: in=%u in+1=%u out=%u\n", 
      50           5 :                         r->in.in_data, r->in.in_data+1, *r->out.out_data);
      51             :         }
      52       16533 :         return NT_STATUS_OK;
      53             : }
      54             : 
      55             : /*
      56             :   a deferred reply to echodata
      57             : */
      58           1 : static void deferred_echodata(struct tevent_context *ev, struct tevent_timer *te, 
      59             :                               struct timeval t, void *private_data)
      60             : {
      61           1 :         struct irpc_message *irpc = talloc_get_type(private_data, struct irpc_message);
      62           1 :         struct echo_EchoData *r = (struct echo_EchoData *)irpc->data;
      63           1 :         r->out.out_data = (uint8_t *)talloc_memdup(r, r->in.in_data, r->in.len);
      64           1 :         if (r->out.out_data == NULL) {
      65           0 :                 irpc_send_reply(irpc, NT_STATUS_NO_MEMORY);
      66             :         }
      67           1 :         printf("sending deferred reply\n");
      68           1 :         irpc_send_reply(irpc, NT_STATUS_OK);
      69           1 : }
      70             : 
      71             : 
      72             : /*
      73             :   serve up EchoData over the irpc system
      74             : */
      75           1 : static NTSTATUS irpc_EchoData(struct irpc_message *irpc, struct echo_EchoData *r)
      76             : {
      77           1 :         struct irpc_test_data *data = talloc_get_type_abort(irpc->private_data, struct irpc_test_data);
      78           1 :         irpc->defer_reply = true;
      79           1 :         tevent_add_timer(data->ev, irpc, timeval_zero(), deferred_echodata, irpc);
      80           1 :         return NT_STATUS_OK;
      81             : }
      82             : 
      83             : 
      84             : /*
      85             :   test a addone call over the internal messaging system
      86             : */
      87           5 : static bool test_addone(struct torture_context *test, const void *_data,
      88             :                         const void *_value)
      89             : {
      90           5 :         struct echo_AddOne r;
      91           5 :         NTSTATUS status;
      92           5 :         const struct irpc_test_data *data = (const struct irpc_test_data *)_data;
      93           5 :         uint32_t value = *(const uint32_t *)_value;
      94           5 :         struct dcerpc_binding_handle *irpc_handle;
      95             : 
      96           5 :         irpc_handle = irpc_binding_handle(test, data->msg_ctx1,
      97             :                                           cluster_id(0, MSG_ID2),
      98             :                                           &ndr_table_rpcecho);
      99           5 :         torture_assert(test, irpc_handle, "no memory");
     100             : 
     101             :         /* make the call */
     102           5 :         r.in.in_data = value;
     103             : 
     104           5 :         test_debug = true;
     105             :         /*
     106             :          * Note: this makes use of nested event loops
     107             :          * as client and server use the same loop.
     108             :          */
     109           5 :         dcerpc_binding_handle_set_sync_ev(irpc_handle, data->ev);
     110           5 :         status = dcerpc_echo_AddOne_r(irpc_handle, test, &r);
     111           5 :         test_debug = false;
     112           5 :         torture_assert_ntstatus_ok(test, status, "AddOne failed");
     113             : 
     114             :         /* check the answer */
     115           5 :         torture_assert(test, *r.out.out_data == r.in.in_data + 1, 
     116             :                                    "AddOne wrong answer");
     117             : 
     118           5 :         torture_comment(test, "%u + 1 = %u\n", r.in.in_data, *r.out.out_data);
     119           5 :         return true;
     120             : }
     121             : 
     122             : /*
     123             :   test a echodata call over the internal messaging system
     124             : */
     125           1 : static bool test_echodata(struct torture_context *tctx,
     126             :                                                   const void *tcase_data,
     127             :                                                   const void *test_data)
     128             : {
     129           1 :         struct echo_EchoData r;
     130           1 :         NTSTATUS status;
     131           1 :         const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data;
     132           1 :         TALLOC_CTX *mem_ctx = tctx;
     133           1 :         struct dcerpc_binding_handle *irpc_handle;
     134             : 
     135           1 :         irpc_handle = irpc_binding_handle(mem_ctx, data->msg_ctx1,
     136             :                                           cluster_id(0, MSG_ID2),
     137             :                                           &ndr_table_rpcecho);
     138           1 :         torture_assert(tctx, irpc_handle, "no memory");
     139             : 
     140             :         /* make the call */
     141           1 :         r.in.in_data = (unsigned char *)talloc_strdup(mem_ctx, "0123456789");
     142           1 :         r.in.len = strlen((char *)r.in.in_data);
     143             : 
     144             :         /*
     145             :          * Note: this makes use of nested event loops
     146             :          * as client and server use the same loop.
     147             :          */
     148           1 :         dcerpc_binding_handle_set_sync_ev(irpc_handle, data->ev);
     149           1 :         status = dcerpc_echo_EchoData_r(irpc_handle, mem_ctx, &r);
     150           1 :         torture_assert_ntstatus_ok(tctx, status, "EchoData failed");
     151             : 
     152             :         /* check the answer */
     153           1 :         if (memcmp(r.out.out_data, r.in.in_data, r.in.len) != 0) {
     154           0 :                 NDR_PRINT_OUT_DEBUG(echo_EchoData, &r);
     155           0 :                 torture_fail(tctx, "EchoData wrong answer");
     156             :         }
     157             : 
     158           1 :         torture_comment(tctx, "Echo '%*.*s' -> '%*.*s'\n", 
     159             :                r.in.len, r.in.len,
     160             :                r.in.in_data,
     161             :                r.in.len, r.in.len,
     162             :                r.out.out_data);
     163           1 :         return true;
     164             : }
     165             : 
     166             : struct irpc_callback_state {
     167             :         struct echo_AddOne r;
     168             :         int *pong_count;
     169             : };
     170             : 
     171       16528 : static void irpc_callback(struct tevent_req *subreq)
     172             : {
     173       16528 :         struct irpc_callback_state *s =
     174       16528 :                 tevent_req_callback_data(subreq,
     175             :                 struct irpc_callback_state);
     176       16528 :         NTSTATUS status;
     177             : 
     178       16528 :         status = dcerpc_echo_AddOne_r_recv(subreq, s);
     179       16528 :         TALLOC_FREE(subreq);
     180       16528 :         if (!NT_STATUS_IS_OK(status)) {
     181           0 :                 printf("irpc call failed - %s\n", nt_errstr(status));
     182             :         }
     183       16528 :         if (*s->r.out.out_data != s->r.in.in_data + 1) {
     184           0 :                 printf("AddOne wrong answer - %u + 1 = %u should be %u\n", 
     185           0 :                        s->r.in.in_data, *s->r.out.out_data, s->r.in.in_data+1);
     186             :         }
     187       16528 :         (*s->pong_count)++;
     188       16528 : }
     189             : 
     190             : /*
     191             :   test echo speed
     192             : */
     193           1 : static bool test_speed(struct torture_context *tctx,
     194             :                                            const void *tcase_data,
     195             :                                            const void *test_data)
     196             : {
     197           1 :         int ping_count = 0;
     198           1 :         int pong_count = 0;
     199           1 :         const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data;
     200           1 :         struct timeval tv;
     201           1 :         TALLOC_CTX *mem_ctx = tctx;
     202           1 :         int timelimit = torture_setting_int(tctx, "timelimit", 10);
     203           1 :         struct dcerpc_binding_handle *irpc_handle;
     204             : 
     205           1 :         irpc_handle = irpc_binding_handle(mem_ctx, data->msg_ctx1,
     206             :                                           cluster_id(0, MSG_ID2),
     207             :                                           &ndr_table_rpcecho);
     208           1 :         torture_assert(tctx, irpc_handle, "no memory");
     209             : 
     210           1 :         tv = timeval_current();
     211             : 
     212           1 :         torture_comment(tctx, "Sending echo for %d seconds\n", timelimit);
     213       16529 :         while (timeval_elapsed(&tv) < timelimit) {
     214       16528 :                 struct tevent_req *subreq;
     215       16528 :                 struct irpc_callback_state *s;
     216             : 
     217       16528 :                 s = talloc_zero(mem_ctx, struct irpc_callback_state);
     218       16528 :                 torture_assert(tctx, s != NULL, "no mem");
     219             : 
     220       16528 :                 s->pong_count = &pong_count;
     221             : 
     222       16528 :                 subreq = dcerpc_echo_AddOne_r_send(mem_ctx,
     223             :                                                    tctx->ev,
     224             :                                                    irpc_handle,
     225             :                                                    &s->r);
     226       16528 :                 torture_assert(tctx, subreq != NULL, "AddOne send failed");
     227             : 
     228       16528 :                 tevent_req_set_callback(subreq, irpc_callback, s);
     229             : 
     230       16528 :                 ping_count++;
     231             : 
     232      148508 :                 while (ping_count > pong_count + 20) {
     233      131980 :                         tevent_loop_once(data->ev);
     234             :                 }
     235             :         }
     236             : 
     237           1 :         torture_comment(tctx, "waiting for %d remaining replies (done %d)\n", 
     238             :                ping_count - pong_count, pong_count);
     239          82 :         while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
     240          81 :                 tevent_loop_once(data->ev);
     241             :         }
     242             : 
     243           1 :         torture_assert_int_equal(tctx, ping_count, pong_count, "ping test failed");
     244             : 
     245           2 :         torture_comment(tctx, "echo rate of %.0f messages/sec\n", 
     246           1 :                (ping_count+pong_count)/timeval_elapsed(&tv));
     247           1 :         return true;
     248             : }
     249             : 
     250             : 
     251           1 : static bool irpc_setup(struct torture_context *tctx, void **_data)
     252             : {
     253           1 :         struct irpc_test_data *data;
     254             : 
     255           1 :         *_data = data = talloc(tctx, struct irpc_test_data);
     256             : 
     257           1 :         lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
     258             : 
     259           1 :         data->ev = tctx->ev;
     260           1 :         torture_assert(tctx, data->msg_ctx1 = 
     261             :                        imessaging_init(tctx,
     262             :                                       tctx->lp_ctx,
     263             :                                       cluster_id(0, MSG_ID1),
     264             :                                       data->ev),
     265             :                        "Failed to init first messaging context");
     266             : 
     267           1 :         torture_assert(tctx, data->msg_ctx2 = 
     268             :                        imessaging_init(tctx,
     269             :                                       tctx->lp_ctx,
     270             :                                       cluster_id(0, MSG_ID2), 
     271             :                                       data->ev),
     272             :                        "Failed to init second messaging context");
     273             : 
     274             :         /* register the server side function */
     275           1 :         IRPC_REGISTER(data->msg_ctx1, rpcecho, ECHO_ADDONE, irpc_AddOne, data);
     276           1 :         IRPC_REGISTER(data->msg_ctx2, rpcecho, ECHO_ADDONE, irpc_AddOne, data);
     277             : 
     278           1 :         IRPC_REGISTER(data->msg_ctx1, rpcecho, ECHO_ECHODATA, irpc_EchoData, data);
     279           1 :         IRPC_REGISTER(data->msg_ctx2, rpcecho, ECHO_ECHODATA, irpc_EchoData, data);
     280             : 
     281           1 :         return true;
     282             : }
     283             : 
     284        2354 : struct torture_suite *torture_local_irpc(TALLOC_CTX *mem_ctx)
     285             : {
     286        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "irpc");
     287        2354 :         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "irpc");
     288         125 :         int i;
     289        2354 :         uint32_t *values = talloc_array(tcase, uint32_t, 5);
     290             : 
     291        2354 :         values[0] = 0;
     292        2354 :         values[1] = 0x7FFFFFFE;
     293        2354 :         values[2] = 0xFFFFFFFE;
     294        2354 :         values[3] = 0xFFFFFFFF;
     295        2354 :         values[4] = random() & 0xFFFFFFFF;
     296             : 
     297        2354 :         tcase->setup = irpc_setup;
     298             : 
     299       14124 :         for (i = 0; i < 5; i++) {
     300       11770 :                 torture_tcase_add_test_const(tcase, "addone", test_addone,
     301       11770 :                                 (void *)&values[i]);
     302             :         }
     303             : 
     304        2354 :         torture_tcase_add_test_const(tcase, "echodata", test_echodata, NULL);
     305        2354 :         torture_tcase_add_test_const(tcase, "speed", test_speed, NULL);
     306             : 
     307        2354 :         return suite;
     308             : }

Generated by: LCOV version 1.14