r4690: - add support for async rpc server replies
[kai/samba-autobuild/.git] / source4 / torture / rpc / echo.c
index 43c794e040ed8a28112e37f08e59ba26a2b8f926..13731383eee4888a276cd3ae564bc293c9ccfbb0 100644 (file)
@@ -3,6 +3,7 @@
    test suite for echo rpc operations
 
    Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Stefan (metze) Metzmacher 2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -20,6 +21,7 @@
 */
 
 #include "includes.h"
+#include "librpc/gen_ndr/ndr_echo.h"
 
 
 /*
@@ -55,14 +57,14 @@ static BOOL test_echodata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 {
        int i;
        NTSTATUS status;
-       char *data_in, *data_out;
+       uint8_t *data_in, *data_out;
        int len = 1 + (random() % 5000);
        struct echo_EchoData r;
 
        printf("\nTesting EchoData\n");
 
-       data_in = talloc(mem_ctx, len);
-       data_out = talloc(mem_ctx, len);
+       data_in = talloc_size(mem_ctx, len);
+       data_out = talloc_size(mem_ctx, len);
        for (i=0;i<len;i++) {
                data_in[i] = i;
        }
@@ -103,12 +105,12 @@ static BOOL test_sourcedata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        int i;
        NTSTATUS status;
        int len = 200000 + (random() % 5000);
-       char *data_out;
+       uint8_t *data_out;
        struct echo_SourceData r;
 
        printf("\nTesting SourceData\n");
 
-       data_out = talloc(mem_ctx, len);
+       data_out = talloc_size(mem_ctx, len);
 
        r.in.len = len;
        r.out.data = data_out;
@@ -137,13 +139,13 @@ static BOOL test_sinkdata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 {
        int i;
        NTSTATUS status;
-       char *data_in;
+       uint8_t *data_in;
        int len = 200000 + (random() % 5000);
        struct echo_SinkData r;
 
        printf("\nTesting SinkData\n");
 
-       data_in = talloc(mem_ctx, len);
+       data_in = talloc_size(mem_ctx, len);
        for (i=0;i<len;i++) {
                data_in[i] = i+1;
        }
@@ -207,7 +209,6 @@ static BOOL test_testcall2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        return ret;
 }
 
-
 /*
   test the TestSleep interface
 */
@@ -215,10 +216,13 @@ static BOOL test_sleep(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 {
        int i;
        NTSTATUS status;
-#define ASYNC_COUNT 5
+#define ASYNC_COUNT 3
        struct rpc_request *req[ASYNC_COUNT];
        struct echo_TestSleep r[ASYNC_COUNT];
-       int done[ASYNC_COUNT];
+       BOOL done[ASYNC_COUNT];
+       struct timeval snd[ASYNC_COUNT];
+       struct timeval rcv[ASYNC_COUNT];
+       struct timeval diff[ASYNC_COUNT];
        struct event_context *ctx;
        int total_done = 0;
        BOOL ret = True;
@@ -226,7 +230,9 @@ static BOOL test_sleep(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        printf("\nTesting TestSleep\n");
 
        for (i=0;i<ASYNC_COUNT;i++) {
-               done[i] = 0;
+               done[i]         = False;
+               snd[i]          = timeval_current();
+               rcv[i]          = timeval_zero();
                r[i].in.seconds = ASYNC_COUNT-i;
                req[i] = dcerpc_echo_TestSleep_send(p, mem_ctx, &r[i]);
                if (!req[i]) {
@@ -241,17 +247,37 @@ static BOOL test_sleep(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                        return False;
                }
                for (i=0;i<ASYNC_COUNT;i++) {
-                       if (done[i] == 0 && req[i]->state == RPC_REQUEST_DONE) {
+                       if (done[i] == False && req[i]->state == RPC_REQUEST_DONE) {
                                total_done++;
-                               done[i] = 1;
-                               status = dcerpc_ndr_request_recv(req[i]);
+                               done[i] = True;
+                               rcv[i]  = timeval_current();
+                               diff[i] = timeval_diff(&rcv[i], &snd[i]);
+                               status  = dcerpc_ndr_request_recv(req[i]);
                                if (!NT_STATUS_IS_OK(status)) {
                                        printf("TestSleep(%d) failed - %s\n",
                                               i, nt_errstr(status));
                                        ret = False;
+                               } else if (r[i].out.result != r[i].in.seconds) {
+                                       printf("Failed - Sleeped for %u seconds (but we said %u seconds and the reply takes only %u seconds)\n", 
+                                               r[i].out.result, r[i].in.seconds, (uint_t)diff[i].tv_sec);
+                                       ret = False;
                                } else {
-                                       printf("Sleep for %d seconds\n", 
-                                              r[i].out.result);
+                                       if (r[i].out.result > diff[i].tv_sec) {
+                                               printf("Failed - Sleeped for %u seconds (but reply takes only %u seconds)\n", 
+                                                       r[i].out.result, (uint_t)diff[i].tv_sec);
+                                               ret = False;
+                                       } else if (r[i].out.result+1 == diff[i].tv_sec) {
+                                               printf("Sleeped for %u seconds (but reply takes %u seconds - busy server?)\n", 
+                                                       r[i].out.result, (uint_t)diff[i].tv_sec);
+                                       } else if (r[i].out.result == diff[i].tv_sec) {
+                                               printf("Sleeped for %u seconds (reply takes %u seconds - ok)\n", 
+                                                       r[i].out.result, (uint_t)diff[i].tv_sec);
+                                       } else {
+                                               printf("(Failed) - Not async - Sleeped for %u seconds (but reply takes %u seconds)\n", 
+                                                       r[i].out.result, (uint_t)diff[i].tv_sec);
+                                               /* TODO: let the test fail here, when we support async rpc on ncacn_np
+                                               ret = False;*/
+                                       }
                                }
                        }
                }
@@ -260,7 +286,40 @@ static BOOL test_sleep(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        return ret;
 }
 
-BOOL torture_rpc_echo(int dummy)
+/*
+  test enum handling
+*/
+static BOOL test_enum(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+       NTSTATUS status;
+       struct echo_TestEnum r;
+       BOOL ret = True;
+       enum echo_Enum1 v = ECHO_ENUM1;
+       struct echo_Enum2 e2;
+       union echo_Enum3 e3;
+
+       r.in.foo1 = &v;
+       r.in.foo2 = &e2;
+       r.in.foo3 = &e3;
+       r.out.foo1 = &v;
+       r.out.foo2 = &e2;
+       r.out.foo3 = &e3;
+
+       e2.e1 = 76;
+       e2.e2 = ECHO_ENUM1_32;
+       e3.e1 = ECHO_ENUM2;
+
+       printf("\nTesting TestEnum\n");
+       status = dcerpc_echo_TestEnum(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TestEnum failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+BOOL torture_rpc_echo(void)
 {
         NTSTATUS status;
         struct dcerpc_pipe *p;
@@ -277,23 +336,21 @@ BOOL torture_rpc_echo(int dummy)
                return False;
        }
 
-#if 1
        if (!test_addone(p, mem_ctx)) {
                ret = False;
        }
 
-       if (!test_echodata(p, mem_ctx)) {
+       if (!test_sinkdata(p, mem_ctx)) {
                ret = False;
        }
 
-       if (!test_sourcedata(p, mem_ctx)) {
+       if (!test_echodata(p, mem_ctx)) {
                ret = False;
        }
 
-       if (!test_sinkdata(p, mem_ctx)) {
+       if (!test_sourcedata(p, mem_ctx)) {
                ret = False;
        }
-#endif
 
        if (!test_testcall(p, mem_ctx)) {
                ret = False;
@@ -303,13 +360,17 @@ BOOL torture_rpc_echo(int dummy)
                ret = False;
        }
 
+       if (!test_enum(p, mem_ctx)) {
+               ret = False;
+       }
+
        if (!test_sleep(p, mem_ctx)) {
                ret = False;
        }
 
        printf("\n");
        
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
         torture_rpc_close(p);
        return ret;