441a4835f2bf41e31f0c99b24d42f4b335460c23
[samba.git] / source4 / torture / rpc / echo.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for echo rpc operations
4
5    Copyright (C) Andrew Tridgell 2003
6    
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 2 of the License, or
10    (at your option) any later version.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23 #include "librpc/gen_ndr/ndr_echo.h"
24
25
26 /*
27   test the AddOne interface
28 */
29 static BOOL test_addone(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
30 {
31         int i;
32         NTSTATUS status;
33
34         printf("\nTesting AddOne\n");
35
36         for (i=0;i<10;i++) {
37                 uint32_t n = i;
38                 struct echo_AddOne r;
39                 r.in.v = &n;
40                 r.out.v = &n;
41                 status = dcerpc_echo_AddOne(p, mem_ctx, &r);
42                 if (!NT_STATUS_IS_OK(status)) {
43                         printf("AddOne(%d) failed - %s\n", i, nt_errstr(status));
44                         return False;
45                 }
46                 printf("%d + 1 = %u\n", i, n);
47         }
48
49         return True;
50 }
51
52 /*
53   test the EchoData interface
54 */
55 static BOOL test_echodata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
56 {
57         int i;
58         NTSTATUS status;
59         char *data_in, *data_out;
60         int len = 1 + (random() % 5000);
61         struct echo_EchoData r;
62
63         printf("\nTesting EchoData\n");
64
65         data_in = talloc(mem_ctx, len);
66         data_out = talloc(mem_ctx, len);
67         for (i=0;i<len;i++) {
68                 data_in[i] = i;
69         }
70         
71         r.in.len = len;
72         r.in.in_data = data_in;
73
74         status = dcerpc_echo_EchoData(p, mem_ctx, &r);
75         if (!NT_STATUS_IS_OK(status)) {
76                 printf("EchoData(%d) failed - %s\n", len, nt_errstr(status));
77                 return False;
78         }
79
80         data_out = r.out.out_data;
81
82         for (i=0;i<len;i++) {
83                 if (data_in[i] != data_out[i]) {
84                         printf("Bad data returned for len %d at offset %d\n", 
85                                len, i);
86                         printf("in:\n");
87                         dump_data(0, data_in+i, MIN(len-i, 16));
88                         printf("out:\n");
89                         dump_data(0, data_out+i, MIN(len-1, 16));
90                         return False;
91                 }
92         }
93
94
95         return True;
96 }
97
98
99 /*
100   test the SourceData interface
101 */
102 static BOOL test_sourcedata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
103 {
104         int i;
105         NTSTATUS status;
106         int len = 200000 + (random() % 5000);
107         char *data_out;
108         struct echo_SourceData r;
109
110         printf("\nTesting SourceData\n");
111
112         data_out = talloc(mem_ctx, len);
113
114         r.in.len = len;
115         r.out.data = data_out;
116
117         status = dcerpc_echo_SourceData(p, mem_ctx, &r);
118         if (!NT_STATUS_IS_OK(status)) {
119                 printf("SourceData(%d) failed - %s\n", len, nt_errstr(status));
120                 return False;
121         }
122
123         for (i=0;i<len;i++) {
124                 uint8_t *v = (uint8_t *)data_out;
125                 if (v[i] != (i & 0xFF)) {
126                         printf("bad data 0x%x at %d\n", (uint8_t)data_out[i], i);
127                         return False;
128                 }
129         }
130
131         return True;
132 }
133
134 /*
135   test the SinkData interface
136 */
137 static BOOL test_sinkdata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
138 {
139         int i;
140         NTSTATUS status;
141         char *data_in;
142         int len = 200000 + (random() % 5000);
143         struct echo_SinkData r;
144
145         printf("\nTesting SinkData\n");
146
147         data_in = talloc(mem_ctx, len);
148         for (i=0;i<len;i++) {
149                 data_in[i] = i+1;
150         }
151
152         r.in.len = len;
153         r.in.data = data_in;
154
155         status = dcerpc_echo_SinkData(p, mem_ctx, &r);
156         if (!NT_STATUS_IS_OK(status)) {
157                 printf("SinkData(%d) failed - %s\n", len, nt_errstr(status));
158                 return False;
159         }
160
161         printf("sunk %d bytes\n", len);
162
163         return True;
164 }
165
166
167 /*
168   test the testcall interface
169 */
170 static BOOL test_testcall(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
171 {
172         NTSTATUS status;
173         struct echo_TestCall r;
174
175         r.in.s1 = "input string";
176
177         printf("\nTesting TestCall\n");
178         status = dcerpc_echo_TestCall(p, mem_ctx, &r);
179         if (!NT_STATUS_IS_OK(status)) {
180                 printf("TestCall failed - %s\n", nt_errstr(status));
181                 return False;
182         }
183
184         return True;
185 }
186
187 /*
188   test the testcall interface
189 */
190 static BOOL test_testcall2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
191 {
192         NTSTATUS status;
193         struct echo_TestCall2 r;
194         int i;
195         BOOL ret = True;
196
197         for (i=1;i<=7;i++) {
198                 r.in.level = i;
199
200                 printf("\nTesting TestCall2 level %d\n", i);
201                 status = dcerpc_echo_TestCall2(p, mem_ctx, &r);
202                 if (!NT_STATUS_IS_OK(status)) {
203                         printf("TestCall2 failed - %s\n", nt_errstr(status));
204                         ret = False;
205                 }
206         }
207
208         return ret;
209 }
210
211 #if 0
212 /*
213   test the TestSleep interface
214 */
215 static BOOL test_sleep(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
216 {
217         int i;
218         NTSTATUS status;
219 #define ASYNC_COUNT 5
220         struct rpc_request *req[ASYNC_COUNT];
221         struct echo_TestSleep r[ASYNC_COUNT];
222         int done[ASYNC_COUNT];
223         struct event_context *ctx;
224         int total_done = 0;
225         BOOL ret = True;
226
227         printf("\nTesting TestSleep\n");
228
229         for (i=0;i<ASYNC_COUNT;i++) {
230                 done[i] = 0;
231                 r[i].in.seconds = ASYNC_COUNT-i;
232                 req[i] = dcerpc_echo_TestSleep_send(p, mem_ctx, &r[i]);
233                 if (!req[i]) {
234                         printf("Failed to send async sleep request\n");
235                         return False;
236                 }
237         }
238
239         ctx = dcerpc_event_context(p);
240         while (total_done < ASYNC_COUNT) {
241                 if (event_loop_once(ctx) != 0) {
242                         return False;
243                 }
244                 for (i=0;i<ASYNC_COUNT;i++) {
245                         if (done[i] == 0 && req[i]->state == RPC_REQUEST_DONE) {
246                                 total_done++;
247                                 done[i] = 1;
248                                 status = dcerpc_ndr_request_recv(req[i]);
249                                 if (!NT_STATUS_IS_OK(status)) {
250                                         printf("TestSleep(%d) failed - %s\n",
251                                                i, nt_errstr(status));
252                                         ret = False;
253                                 } else {
254                                         printf("Sleep for %d seconds\n", 
255                                                r[i].out.result);
256                                 }
257                         }
258                 }
259         }
260
261         return ret;
262 }
263 #endif
264
265 BOOL torture_rpc_echo(void)
266 {
267         NTSTATUS status;
268         struct dcerpc_pipe *p;
269         TALLOC_CTX *mem_ctx;
270         BOOL ret = True;
271
272         mem_ctx = talloc_init("torture_rpc_echo");
273
274         status = torture_rpc_connection(&p, 
275                                         DCERPC_RPCECHO_NAME,
276                                         DCERPC_RPCECHO_UUID,
277                                         DCERPC_RPCECHO_VERSION);
278         if (!NT_STATUS_IS_OK(status)) {
279                 return False;
280         }
281
282         if (!test_addone(p, mem_ctx)) {
283                 ret = False;
284         }
285
286         if (!test_sinkdata(p, mem_ctx)) {
287                 ret = False;
288         }
289
290         if (!test_echodata(p, mem_ctx)) {
291                 ret = False;
292         }
293
294         if (!test_sourcedata(p, mem_ctx)) {
295                 ret = False;
296         }
297
298         if (!test_testcall(p, mem_ctx)) {
299                 ret = False;
300         }
301
302         if (!test_testcall2(p, mem_ctx)) {
303                 ret = False;
304         }
305
306 /*
307         if (!test_sleep(p, mem_ctx)) {
308                 ret = False;
309         }
310 */
311         printf("\n");
312         
313         talloc_free(mem_ctx);
314
315         torture_rpc_close(p);
316         return ret;
317 }