s4:RPC-ECHO: don't look at the internals of 'struct rpc_request'
[ira/wip.git] / source4 / torture / rpc / echo.c
index 7df2702d0a12c8729cf6a70c2bc18f016f5ccc80..2321500ca52c64857dc982f42c63ccf29b10b8f4 100644 (file)
@@ -8,7 +8,7 @@
    
    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
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "torture/torture.h"
+#include "torture/rpc/rpc.h"
 #include "lib/events/events.h"
-#include "librpc/gen_ndr/ndr_echo.h"
+#include "librpc/gen_ndr/ndr_echo_c.h"
 
 
 /*
   test the AddOne interface
 */
-#define TEST_ADDONE(value) do { \
+#define TEST_ADDONE(tctx, value) do { \
        n = i = value; \
        r.in.in_data = n; \
        r.out.out_data = &n; \
-       status = dcerpc_echo_AddOne(p, mem_ctx, &r); \
-       if (!NT_STATUS_IS_OK(status)) { \
-               printf("AddOne(%d) failed - %s\n", i, nt_errstr(status)); \
-               return False; \
-       } \
-       if (n != i+1) { \
-               printf("%d + 1 != %u (should be %u)\n", i, n, i+1); \
-               ret = False; \
-       } else { \
-               printf("%d + 1 = %u\n", i, n); \
-       } \
+       status = dcerpc_echo_AddOne(p, tctx, &r); \
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "AddOne(%d) failed", i)); \
+       torture_assert (tctx, n == i+1, talloc_asprintf(tctx, "%d + 1 != %u (should be %u)\n", i, n, i+1)); \
+       torture_comment (tctx, "%d + 1 = %u\n", i, n); \
 } while(0)
 
-static BOOL test_addone(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_addone(struct torture_context *tctx, 
+                                               struct dcerpc_pipe *p)
 {
-       BOOL ret = True;
        uint32_t i;
        NTSTATUS status;
        uint32_t n;
        struct echo_AddOne r;
 
-       printf("\nTesting AddOne\n");
-
        for (i=0;i<10;i++) {
-               TEST_ADDONE(i);
+               TEST_ADDONE(tctx, i);
        }
 
-       TEST_ADDONE(0x7FFFFFFE);
-       TEST_ADDONE(0xFFFFFFFE);
-       TEST_ADDONE(0xFFFFFFFF);
-       TEST_ADDONE(random() & 0xFFFFFFFF);
-
-       return ret;
+       TEST_ADDONE(tctx, 0x7FFFFFFE);
+       TEST_ADDONE(tctx, 0xFFFFFFFE);
+       TEST_ADDONE(tctx, 0xFFFFFFFF);
+       TEST_ADDONE(tctx, random() & 0xFFFFFFFF);
+       return true;
 }
 
 /*
   test the EchoData interface
 */
-static BOOL test_echodata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_echodata(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
 {
        int i;
        NTSTATUS status;
        uint8_t *data_in, *data_out;
-       int len = 1 + (random() % 5000);
+       int len;
        struct echo_EchoData r;
 
-       printf("\nTesting EchoData\n");
+       if (torture_setting_bool(tctx, "quick", false) &&
+           (p->conn->flags & DCERPC_DEBUG_VALIDATE_BOTH)) {
+               len = 1 + (random() % 500);
+       } else {
+               len = 1 + (random() % 5000);
+       }
 
-       data_in = talloc_size(mem_ctx, len);
-       data_out = talloc_size(mem_ctx, len);
+       data_in = talloc_array(tctx, uint8_t, len);
+       data_out = talloc_array(tctx, uint8_t, len);
        for (i=0;i<len;i++) {
                data_in[i] = i;
        }
@@ -91,76 +86,79 @@ static BOOL test_echodata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        r.in.len = len;
        r.in.in_data = data_in;
 
-       status = dcerpc_echo_EchoData(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("EchoData(%d) failed - %s\n", len, nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_echo_EchoData(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, 
+                                                                                       "EchoData(%d) failed\n", len));
 
        data_out = r.out.out_data;
 
        for (i=0;i<len;i++) {
                if (data_in[i] != data_out[i]) {
-                       printf("Bad data returned for len %d at offset %d\n", 
+                       torture_comment(tctx, "Bad data returned for len %d at offset %d\n", 
                               len, i);
-                       printf("in:\n");
+                       torture_comment(tctx, "in:\n");
                        dump_data(0, data_in+i, MIN(len-i, 16));
-                       printf("out:\n");
+                       torture_comment(tctx, "out:\n");
                        dump_data(0, data_out+i, MIN(len-1, 16));
-                       return False;
+                       return false;
                }
        }
-
-
-       return True;
+       return true;
 }
 
-
 /*
   test the SourceData interface
 */
-static BOOL test_sourcedata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_sourcedata(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
 {
        int i;
        NTSTATUS status;
-       int len = 200000 + (random() % 5000);
+       int len;
        struct echo_SourceData r;
 
-       printf("\nTesting SourceData\n");
+       if (torture_setting_bool(tctx, "quick", false) &&
+           (p->conn->flags & DCERPC_DEBUG_VALIDATE_BOTH)) {
+               len = 100 + (random() % 500);
+       } else {
+               len = 200000 + (random() % 5000);
+       }
 
        r.in.len = len;
 
-       status = dcerpc_echo_SourceData(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SourceData(%d) failed - %s\n", len, nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_echo_SourceData(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, 
+                                                                               "SourceData(%d) failed", len));
 
        for (i=0;i<len;i++) {
                uint8_t *v = (uint8_t *)r.out.data;
-               if (v[i] != (i & 0xFF)) {
-                       printf("bad data 0x%x at %d\n", (uint8_t)r.out.data[i], i);
-                       return False;
-               }
+               torture_assert(tctx, v[i] == (i & 0xFF),
+                       talloc_asprintf(tctx, 
+                                               "bad data 0x%x at %d\n", (uint8_t)r.out.data[i], i));
        }
-
-       return True;
+       return true;
 }
 
 /*
   test the SinkData interface
 */
-static BOOL test_sinkdata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_sinkdata(struct torture_context *tctx, 
+                                                 struct dcerpc_pipe *p)
 {
        int i;
        NTSTATUS status;
        uint8_t *data_in;
-       int len = 200000 + (random() % 5000);
+       int len;
        struct echo_SinkData r;
 
-       printf("\nTesting SinkData\n");
+       if (torture_setting_bool(tctx, "quick", false) &&
+           (p->conn->flags & DCERPC_DEBUG_VALIDATE_BOTH)) {
+               len = 100 + (random() % 5000);
+       } else {
+               len = 200000 + (random() % 5000);
+       }
 
-       data_in = talloc_size(mem_ctx, len);
+       data_in = talloc_array(tctx, uint8_t, len);
        for (i=0;i<len;i++) {
                data_in[i] = i+1;
        }
@@ -168,151 +166,148 @@ static BOOL test_sinkdata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        r.in.len = len;
        r.in.data = data_in;
 
-       status = dcerpc_echo_SinkData(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SinkData(%d) failed - %s\n", len, nt_errstr(status));
-               return False;
-       }
-
-       printf("sunk %d bytes\n", len);
+       status = dcerpc_echo_SinkData(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, 
+                                                                               "SinkData(%d) failed", 
+                                                          len));
 
-       return True;
+       torture_comment(tctx, "sunk %d bytes\n", len);
+       return true;
 }
 
 
 /*
   test the testcall interface
 */
-static BOOL test_testcall(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_testcall(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct echo_TestCall r;
+       const char *s = NULL;
 
        r.in.s1 = "input string";
+       r.out.s2 = &s;
 
-       printf("\nTesting TestCall\n");
-       status = dcerpc_echo_TestCall(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("TestCall failed - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_echo_TestCall(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "TestCall failed");
+
+       torture_assert_str_equal(tctx, s, "input string", "Didn't receive back same string");
 
-       return True;
+       return true;
 }
 
 /*
   test the testcall interface
 */
-static BOOL test_testcall2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_testcall2(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct echo_TestCall2 r;
        int i;
-       BOOL ret = True;
 
        for (i=1;i<=7;i++) {
                r.in.level = i;
-               r.out.info = talloc(mem_ctx, union echo_Info);
+               r.out.info = talloc(tctx, union echo_Info);
 
-               printf("\nTesting TestCall2 level %d\n", i);
-               status = dcerpc_echo_TestCall2(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("TestCall2 failed - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               torture_comment(tctx, "Testing TestCall2 level %d\n", i);
+               status = dcerpc_echo_TestCall2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "TestCall2 failed");
        }
+       return true;
+}
 
-       return ret;
+static void test_sleep_done(struct rpc_request *rreq)
+{
+       bool *done1 = (bool *)rreq->async.private_data;
+       *done1 = true;
 }
 
 /*
   test the TestSleep interface
 */
-static BOOL test_sleep(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_sleep(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
 {
        int i;
        NTSTATUS status;
 #define ASYNC_COUNT 3
        struct rpc_request *req[ASYNC_COUNT];
        struct echo_TestSleep r[ASYNC_COUNT];
-       BOOL done[ASYNC_COUNT];
+       bool done1[ASYNC_COUNT];
+       bool done2[ASYNC_COUNT];
        struct timeval snd[ASYNC_COUNT];
        struct timeval rcv[ASYNC_COUNT];
        struct timeval diff[ASYNC_COUNT];
-       struct event_context *ctx;
+       struct tevent_context *ctx;
        int total_done = 0;
-       BOOL ret = True;
 
-       if (lp_parm_bool(-1, "torture", "quick", False)) {
-               printf("TestSleep disabled - use \"torture:quick=no\" to enable\n");
-               return True;
+       if (torture_setting_bool(tctx, "quick", false)) {
+               torture_skip(tctx, "TestSleep disabled - use \"torture:quick=no\" to enable\n");
        }
-       printf("Testing TestSleep - use \"torture:quick=no\" to disable\n");
+       torture_comment(tctx, "Testing TestSleep - use \"torture:quick=yes\" to disable\n");
 
        for (i=0;i<ASYNC_COUNT;i++) {
-               done[i]         = False;
+               done1[i]        = false;
+               done2[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]) {
-                       printf("Failed to send async sleep request\n");
-                       return False;
-               }
+               req[i] = dcerpc_echo_TestSleep_send(p, tctx, &r[i]);
+               torture_assert(tctx, req[i], "Failed to send async sleep request\n");
+               req[i]->async.callback = test_sleep_done;
+               req[i]->async.private_data = &done1[i];
        }
 
        ctx = dcerpc_event_context(p);
        while (total_done < ASYNC_COUNT) {
-               if (event_loop_once(ctx) != 0) {
-                       return False;
-               }
+               torture_assert(tctx, event_loop_once(ctx) == 0, 
+                                          "Event context loop failed");
                for (i=0;i<ASYNC_COUNT;i++) {
-                       if (done[i] == False && req[i]->state == RPC_REQUEST_DONE) {
+                       if (done2[i] == false && done1[i] == true) {
+                               int rounded_tdiff;
                                total_done++;
-                               done[i] = True;
+                               done2[i] = true;
                                rcv[i]  = timeval_current();
                                diff[i] = timeval_until(&snd[i], &rcv[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 - Asked to sleep for %u seconds (server replied with %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;
+                               rounded_tdiff = (int)(0.5 + diff[i].tv_sec + (1.0e-6*diff[i].tv_usec));
+                               status  = dcerpc_echo_TestSleep_recv(req[i]);
+                               torture_comment(tctx, "rounded_tdiff=%d\n", rounded_tdiff);
+                               torture_assert_ntstatus_ok(tctx, status, 
+                                                       talloc_asprintf(tctx, "TestSleep(%d) failed", i));
+                               torture_assert(tctx, r[i].out.result == r[i].in.seconds,
+                                       talloc_asprintf(tctx, "Failed - Asked to sleep for %u seconds (server replied with %u seconds and the reply takes only %u seconds)", 
+                                               r[i].out.result, r[i].in.seconds, (unsigned int)diff[i].tv_sec));
+                               torture_assert(tctx, r[i].out.result <= rounded_tdiff, 
+                                       talloc_asprintf(tctx, "Failed - Slept for %u seconds (but reply takes only %u.%06u seconds)", 
+                                               r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec));
+                               if (r[i].out.result+1 == rounded_tdiff) {
+                                       torture_comment(tctx, "Slept for %u seconds (but reply takes %u.%06u seconds - busy server?)\n", 
+                                                       r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
+                               } else if (r[i].out.result == rounded_tdiff) {
+                                       torture_comment(tctx, "Slept for %u seconds (reply takes %u.%06u seconds - ok)\n", 
+                                                       r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
                                } else {
-                                       if (r[i].out.result > diff[i].tv_sec) {
-                                               printf("Failed - Slept for %u seconds (but reply takes only %u.%06u seconds)\n", 
-                                                       r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec);
-                                       } else if (r[i].out.result+1 == diff[i].tv_sec) {
-                                               printf("Slept for %u seconds (but reply takes %u.%06u seconds - busy server?)\n", 
-                                                       r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec);
-                                       } else if (r[i].out.result == diff[i].tv_sec) {
-                                               printf("Slept for %u seconds (reply takes %u.%06u seconds - ok)\n", 
-                                                       r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec);
-                                       } else {
-                                               printf("(Failed) - Not async - Slept for %u seconds (but reply takes %u.%06u seconds)\n", 
-                                                       r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec);
-                                               /* TODO: let the test fail here, when we support async rpc on ncacn_np
-                                               ret = False;*/
-                                       }
+                                               torture_comment(tctx, "(Failed) - Not async - Slept for %u seconds (but reply takes %u.%06u seconds)", 
+                                                       r[i].out.result, (unsigned int)diff[i].tv_sec, (unsigned int)diff[i].tv_usec);
+                                       /* TODO: let the test fail here, when we support async rpc on ncacn_np */
                                }
                        }
                }
        }
-
-       return ret;
+       torture_comment(tctx, "\n");
+       return true;
 }
 
 /*
   test enum handling
 */
-static BOOL test_enum(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_enum(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct echo_TestEnum r;
-       BOOL ret = True;
        enum echo_Enum1 v = ECHO_ENUM1;
        struct echo_Enum2 e2;
        union echo_Enum3 e3;
@@ -328,56 +323,45 @@ static BOOL test_enum(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        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;
+       status = dcerpc_echo_TestEnum(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "TestEnum failed");
+       return true;
 }
 
 /*
   test surrounding conformant array handling
 */
-static BOOL test_surrounding(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_surrounding(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct echo_TestSurrounding r;
-       BOOL ret = True;
 
        ZERO_STRUCT(r);
-       r.in.data = talloc(mem_ctx, struct echo_Surrounding);
+       r.in.data = talloc(tctx, struct echo_Surrounding);
 
        r.in.data->x = 20;
-       r.in.data->surrounding = talloc_zero_array(mem_ctx, uint16_t, r.in.data->x);
+       r.in.data->surrounding = talloc_zero_array(tctx, uint16_t, r.in.data->x);
 
-       r.out.data = talloc(mem_ctx, struct echo_Surrounding);
+       r.out.data = talloc(tctx, struct echo_Surrounding);
 
-       printf("\nTesting TestSurrounding\n");
-       status = dcerpc_echo_TestSurrounding(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("TestSurrounding failed - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_echo_TestSurrounding(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "TestSurrounding failed");
        
-       if (r.out.data->x != 2 * r.in.data->x) {
-               printf("TestSurrounding did not make the array twice as large\n");
-               ret = False;
-       }
+       torture_assert(tctx, r.out.data->x == 2 * r.in.data->x,
+               "TestSurrounding did not make the array twice as large");
 
-       return ret;
+       return true;
 }
 
 /*
   test multiple levels of pointers
 */
-static BOOL test_doublepointer(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_doublepointer(struct torture_context *tctx,
+                                                          struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct echo_TestDoublePointer r;
-       BOOL ret = True;
        uint16_t value = 12;
        uint16_t *pvalue = &value;
        uint16_t **ppvalue = &pvalue;
@@ -385,112 +369,96 @@ static BOOL test_doublepointer(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        ZERO_STRUCT(r);
        r.in.data = &ppvalue;
 
-       printf("\nTesting TestDoublePointer\n");
-       status = dcerpc_echo_TestDoublePointer(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("TestDoublePointer failed - %s\n", nt_errstr(status));
-               ret = False;
-       }
-
-       if (value != r.out.result) {
-               printf("TestDoublePointer did not return original value (%d != %d)\n", value, r.out.result);
-               ret = False;
-       }
+       status = dcerpc_echo_TestDoublePointer(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "TestDoublePointer failed");
 
-       return ret;
+       torture_assert_int_equal(tctx, value, r.out.result, 
+                                       "TestDoublePointer did not return original value");
+       return true;
 }
 
 
 /*
   test request timeouts
 */
-static BOOL test_timeout(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+#if 0 /* this test needs fixing to work over ncacn_np */
+static bool test_timeout(struct torture_context *tctx,
+                                                struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct rpc_request *req;
        struct echo_TestSleep r;
        int timeout_saved = p->request_timeout;
 
-       if (lp_parm_bool(-1, "torture", "quick", False)) {
-               printf("timeout testing disabled - use \"torture:quick=no\" to enable\n");
-               return True;
+       if (torture_setting_bool(tctx, "quick", false)) {
+               torture_skip(tctx, "timeout testing disabled - use \"torture:quick=no\" to enable\n");
        }
 
-       printf("testing request timeouts\n");
+       torture_comment(tctx, "testing request timeouts\n");
        r.in.seconds = 2;
        p->request_timeout = 1;
 
-       req = dcerpc_echo_TestSleep_send(p, mem_ctx, &r);
+       req = dcerpc_echo_TestSleep_send(p, tctx, &r);
        if (!req) {
-               printf("Failed to send async sleep request\n");
+               torture_comment(tctx, "Failed to send async sleep request\n");
                goto failed;
        }
+       req->ignore_timeout = true;
 
-       status  = dcerpc_ndr_request_recv(req);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("request should have timed out - %s\n", nt_errstr(status));
-               goto failed;
-       }
+       status  = dcerpc_echo_TestSleep_recv(req);
+       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_IO_TIMEOUT, 
+                                                                 "request should have timed out");
 
-       printf("testing request destruction\n");
-       req = dcerpc_echo_TestSleep_send(p, mem_ctx, &r);
+       torture_comment(tctx, "testing request destruction\n");
+       req = dcerpc_echo_TestSleep_send(p, tctx, &r);
        if (!req) {
-               printf("Failed to send async sleep request\n");
+               torture_comment(tctx, "Failed to send async sleep request\n");
                goto failed;
        }
        talloc_free(req);
 
-       req = dcerpc_echo_TestSleep_send(p, mem_ctx, &r);
+       req = dcerpc_echo_TestSleep_send(p, tctx, &r);
        if (!req) {
-               printf("Failed to send async sleep request\n");
+               torture_comment(tctx, "Failed to send async sleep request\n");
                goto failed;
        }
-       status  = dcerpc_ndr_request_recv(req);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("request should have timed out - %s\n", nt_errstr(status));
-               goto failed;
-       }       
+       req->ignore_timeout = true;
+       status  = dcerpc_echo_TestSleep_recv(req);
+       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_IO_TIMEOUT, 
+               "request should have timed out");
 
        p->request_timeout = timeout_saved;
-       return test_addone(p, mem_ctx);
+       
+       return test_addone(tctx, p);
 
 failed:
        p->request_timeout = timeout_saved;
-       return False;
+       return false;
 }
+#endif
 
-
-BOOL torture_rpc_echo(void)
+struct torture_suite *torture_rpc_echo(TALLOC_CTX *mem_ctx)
 {
-       NTSTATUS status;
-       struct dcerpc_pipe *p;
-       TALLOC_CTX *mem_ctx;
-       BOOL ret = True;
-
-       mem_ctx = talloc_init("torture_rpc_echo");
-
-       status = torture_rpc_connection(mem_ctx, 
-                                       &p, 
-                                       &dcerpc_table_rpcecho);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
-
-       ret &= test_addone(p, mem_ctx);
-       ret &= test_sinkdata(p, mem_ctx);
-       ret &= test_echodata(p, mem_ctx);
-       ret &= test_sourcedata(p, mem_ctx);
-       ret &= test_testcall(p, mem_ctx);
-       ret &= test_testcall2(p, mem_ctx);
-       ret &= test_enum(p, mem_ctx);
-       ret &= test_surrounding(p, mem_ctx);
-       ret &= test_doublepointer(p, mem_ctx);
-       ret &= test_sleep(p, mem_ctx);
-       ret &= test_timeout(p, mem_ctx);
-
-       printf("\n");
-       
-       talloc_free(mem_ctx);
-
-       return ret;
+       struct torture_suite *suite = torture_suite_create(
+               mem_ctx, "ECHO");
+       struct torture_rpc_tcase *tcase;
+
+       tcase = torture_suite_add_rpc_iface_tcase(suite, "echo", 
+                                                 &ndr_table_rpcecho);
+
+       torture_rpc_tcase_add_test(tcase, "addone", test_addone);
+       torture_rpc_tcase_add_test(tcase, "sinkdata", test_sinkdata);
+       torture_rpc_tcase_add_test(tcase, "echodata", test_echodata);
+       torture_rpc_tcase_add_test(tcase, "sourcedata", test_sourcedata);
+       torture_rpc_tcase_add_test(tcase, "testcall", test_testcall);
+       torture_rpc_tcase_add_test(tcase, "testcall2", test_testcall2);
+       torture_rpc_tcase_add_test(tcase, "enum", test_enum);
+       torture_rpc_tcase_add_test(tcase, "surrounding", test_surrounding);
+       torture_rpc_tcase_add_test(tcase, "doublepointer", test_doublepointer);
+       torture_rpc_tcase_add_test(tcase, "sleep", test_sleep);
+#if 0 /* this test needs fixing to work over ncacn_np */
+       torture_rpc_tcase_add_test(tcase, "timeout", test_timeout);
+#endif
+
+       return suite;
 }