pidl:Samba3/ClientNDR: $size can be 'foo / 2' so we need to add '(' and ')'
[kai/samba.git] / pidl / tests / samba3-cli.pl
1 #!/usr/bin/perl
2 # (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3 # Published under the GNU General Public License
4 use strict;
5 use warnings;
6
7 use Test::More tests => 9;
8 use FindBin qw($RealBin);
9 use lib "$RealBin";
10 use Util;
11 use Parse::Pidl::Util qw(MyDumper);
12 use Parse::Pidl::Samba3::ClientNDR qw(ParseFunction ParseOutputArgument);
13 use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
14
15 # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
16 my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
17 is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn, "r."));
18 is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionOutEnv($fn, "r."));
19
20 $fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
21 is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn, "r."));
22 is_deeply({ "foo" => "r.out.foo" }, GenerateFunctionOutEnv($fn, "r."));
23
24 $fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
25 is_deeply({ }, GenerateFunctionInEnv($fn, "r."));
26 is_deeply({ "foo" => "r.out.foo" }, GenerateFunctionOutEnv($fn, "r."));
27
28 my $x = new Parse::Pidl::Samba3::ClientNDR();
29
30 $fn = { NAME => "bar", ELEMENTS => [ ] };
31 $x->ParseFunction("foo", $fn);
32 is($x->{res}, 
33 "struct rpccli_bar_state {
34         struct bar orig;
35         struct bar tmp;
36         TALLOC_CTX *out_mem_ctx;
37         NTSTATUS (*dispatch_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx);
38 };
39
40 static void rpccli_bar_done(struct tevent_req *subreq);
41
42 struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
43                                    struct tevent_context *ev,
44                                    struct rpc_pipe_client *cli)
45 {
46         struct tevent_req *req;
47         struct rpccli_bar_state *state;
48         struct tevent_req *subreq;
49
50         req = tevent_req_create(mem_ctx, &state,
51                                 struct rpccli_bar_state);
52         if (req == NULL) {
53                 return NULL;
54         }
55         state->out_mem_ctx = NULL;
56         state->dispatch_recv = cli->dispatch_recv;
57
58         /* In parameters */
59
60         /* Out parameters */
61
62         /* make a temporary copy, that we pass to the dispatch function */
63         state->tmp = state->orig;
64
65         subreq = cli->dispatch_send(state, ev, cli,
66                                     &ndr_table_foo,
67                                     NDR_BAR,
68                                     &state->tmp);
69         if (tevent_req_nomem(subreq, req)) {
70                 return tevent_req_post(req, ev);
71         }
72         tevent_req_set_callback(subreq, rpccli_bar_done, req);
73         return req;
74 }
75
76 static void rpccli_bar_done(struct tevent_req *subreq)
77 {
78         struct tevent_req *req = tevent_req_callback_data(
79                 subreq, struct tevent_req);
80         struct rpccli_bar_state *state = tevent_req_data(
81                 req, struct rpccli_bar_state);
82         NTSTATUS status;
83         TALLOC_CTX *mem_ctx;
84
85         if (state->out_mem_ctx) {
86                 mem_ctx = state->out_mem_ctx;
87         } else {
88                 mem_ctx = state;
89         }
90
91         status = state->dispatch_recv(subreq, mem_ctx);
92         TALLOC_FREE(subreq);
93         if (!NT_STATUS_IS_OK(status)) {
94                 tevent_req_nterror(req, status);
95                 return;
96         }
97
98         /* Copy out parameters */
99
100         /* Reset temporary structure */
101         ZERO_STRUCT(state->tmp);
102
103         tevent_req_done(req);
104 }
105
106 NTSTATUS rpccli_bar_recv(struct tevent_req *req,
107                          TALLOC_CTX *mem_ctx)
108 {
109         struct rpccli_bar_state *state = tevent_req_data(
110                 req, struct rpccli_bar_state);
111         NTSTATUS status;
112
113         if (tevent_req_is_nterror(req, &status)) {
114                 tevent_req_received(req);
115                 return status;
116         }
117
118         /* Steal possbile out parameters to the callers context */
119         talloc_steal(mem_ctx, state->out_mem_ctx);
120
121         tevent_req_received(req);
122         return NT_STATUS_OK;
123 }
124
125 NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
126                     TALLOC_CTX *mem_ctx)
127 {
128         struct bar r;
129         NTSTATUS status;
130
131         /* In parameters */
132
133         status = cli->dispatch(cli,
134                                 mem_ctx,
135                                 &ndr_table_foo,
136                                 NDR_BAR,
137                                 &r);
138
139         if (!NT_STATUS_IS_OK(status)) {
140                 return status;
141         }
142
143         if (NT_STATUS_IS_ERR(status)) {
144                 return status;
145         }
146
147         /* Return variables */
148
149         /* Return result */
150         return NT_STATUS_OK;
151 }
152
153 ");
154
155 $x = new Parse::Pidl::Samba3::ClientNDR();
156
157 $fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" };
158 $x->ParseFunction("foo", $fn);
159 is($x->{res}, 
160 "struct rpccli_bar_state {
161         struct bar orig;
162         struct bar tmp;
163         TALLOC_CTX *out_mem_ctx;
164         NTSTATUS (*dispatch_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx);
165 };
166
167 static void rpccli_bar_done(struct tevent_req *subreq);
168
169 struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
170                                    struct tevent_context *ev,
171                                    struct rpc_pipe_client *cli)
172 {
173         struct tevent_req *req;
174         struct rpccli_bar_state *state;
175         struct tevent_req *subreq;
176
177         req = tevent_req_create(mem_ctx, &state,
178                                 struct rpccli_bar_state);
179         if (req == NULL) {
180                 return NULL;
181         }
182         state->out_mem_ctx = NULL;
183         state->dispatch_recv = cli->dispatch_recv;
184
185         /* In parameters */
186
187         /* Out parameters */
188
189         /* Result */
190         ZERO_STRUCT(state->orig.out.result);
191
192         /* make a temporary copy, that we pass to the dispatch function */
193         state->tmp = state->orig;
194
195         subreq = cli->dispatch_send(state, ev, cli,
196                                     &ndr_table_foo,
197                                     NDR_BAR,
198                                     &state->tmp);
199         if (tevent_req_nomem(subreq, req)) {
200                 return tevent_req_post(req, ev);
201         }
202         tevent_req_set_callback(subreq, rpccli_bar_done, req);
203         return req;
204 }
205
206 static void rpccli_bar_done(struct tevent_req *subreq)
207 {
208         struct tevent_req *req = tevent_req_callback_data(
209                 subreq, struct tevent_req);
210         struct rpccli_bar_state *state = tevent_req_data(
211                 req, struct rpccli_bar_state);
212         NTSTATUS status;
213         TALLOC_CTX *mem_ctx;
214
215         if (state->out_mem_ctx) {
216                 mem_ctx = state->out_mem_ctx;
217         } else {
218                 mem_ctx = state;
219         }
220
221         status = state->dispatch_recv(subreq, mem_ctx);
222         TALLOC_FREE(subreq);
223         if (!NT_STATUS_IS_OK(status)) {
224                 tevent_req_nterror(req, status);
225                 return;
226         }
227
228         /* Copy out parameters */
229
230         /* Copy result */
231         state->orig.out.result = state->tmp.out.result;
232
233         /* Reset temporary structure */
234         ZERO_STRUCT(state->tmp);
235
236         tevent_req_done(req);
237 }
238
239 NTSTATUS rpccli_bar_recv(struct tevent_req *req,
240                          TALLOC_CTX *mem_ctx,
241                          WERROR *result)
242 {
243         struct rpccli_bar_state *state = tevent_req_data(
244                 req, struct rpccli_bar_state);
245         NTSTATUS status;
246
247         if (tevent_req_is_nterror(req, &status)) {
248                 tevent_req_received(req);
249                 return status;
250         }
251
252         /* Steal possbile out parameters to the callers context */
253         talloc_steal(mem_ctx, state->out_mem_ctx);
254
255         /* Return result */
256         *result = state->orig.out.result;
257
258         tevent_req_received(req);
259         return NT_STATUS_OK;
260 }
261
262 NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
263                     TALLOC_CTX *mem_ctx,
264                     WERROR *werror)
265 {
266         struct bar r;
267         NTSTATUS status;
268
269         /* In parameters */
270
271         status = cli->dispatch(cli,
272                                 mem_ctx,
273                                 &ndr_table_foo,
274                                 NDR_BAR,
275                                 &r);
276
277         if (!NT_STATUS_IS_OK(status)) {
278                 return status;
279         }
280
281         if (NT_STATUS_IS_ERR(status)) {
282                 return status;
283         }
284
285         /* Return variables */
286
287         /* Return result */
288         if (werror) {
289                 *werror = r.out.result;
290         }
291
292         return werror_to_ntstatus(r.out.result);
293 }
294
295 ");
296
297 $x = new Parse::Pidl::Samba3::ClientNDR();
298
299 $fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" };
300 my $e = { NAME => "foo", ORIGINAL => { FILE => "f", LINE => -1 },
301           LEVELS => [ { TYPE => "ARRAY", SIZE_IS => "mysize" }, { TYPE => "DATA", DATA_TYPE => "int" } ]};
302
303 $x->ParseOutputArgument($fn, $e);
304 is($x->{res}, "memcpy(foo, r.out.foo, (mysize) * sizeof(*foo));\n");