pidl:Samba3/ClientNDR: implement rpccli_ stubs on top of dcerpc_ stubs
[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         TALLOC_CTX *out_mem_ctx;
35 };
36
37 static void rpccli_bar_done(struct tevent_req *subreq);
38
39 struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
40                                    struct tevent_context *ev,
41                                    struct rpc_pipe_client *cli)
42 {
43         struct tevent_req *req;
44         struct rpccli_bar_state *state;
45         struct tevent_req *subreq;
46
47         req = tevent_req_create(mem_ctx, &state,
48                                 struct rpccli_bar_state);
49         if (req == NULL) {
50                 return NULL;
51         }
52         state->out_mem_ctx = NULL;
53
54         subreq = dcerpc_bar_send(state,
55                                  ev,
56                                  cli->binding_handle);
57         if (tevent_req_nomem(subreq, req)) {
58                 return tevent_req_post(req, ev);
59         }
60         tevent_req_set_callback(subreq, rpccli_bar_done, req);
61         return req;
62 }
63
64 static void rpccli_bar_done(struct tevent_req *subreq)
65 {
66         struct tevent_req *req = tevent_req_callback_data(
67                 subreq, struct tevent_req);
68         struct rpccli_bar_state *state = tevent_req_data(
69                 req, struct rpccli_bar_state);
70         NTSTATUS status;
71         TALLOC_CTX *mem_ctx;
72
73         if (state->out_mem_ctx) {
74                 mem_ctx = state->out_mem_ctx;
75         } else {
76                 mem_ctx = state;
77         }
78
79         status = dcerpc_bar_recv(subreq,
80                                  mem_ctx);
81         TALLOC_FREE(subreq);
82         if (!NT_STATUS_IS_OK(status)) {
83                 tevent_req_nterror(req, status);
84                 return;
85         }
86
87         tevent_req_done(req);
88 }
89
90 NTSTATUS rpccli_bar_recv(struct tevent_req *req,
91                          TALLOC_CTX *mem_ctx)
92 {
93         struct rpccli_bar_state *state = tevent_req_data(
94                 req, struct rpccli_bar_state);
95         NTSTATUS status;
96
97         if (tevent_req_is_nterror(req, &status)) {
98                 tevent_req_received(req);
99                 return status;
100         }
101
102         /* Steal possbile out parameters to the callers context */
103         talloc_steal(mem_ctx, state->out_mem_ctx);
104
105         tevent_req_received(req);
106         return NT_STATUS_OK;
107 }
108
109 NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
110                     TALLOC_CTX *mem_ctx)
111 {
112         NTSTATUS status;
113
114         status = dcerpc_bar(cli->binding_handle,
115                             mem_ctx);
116         if (!NT_STATUS_IS_OK(status)) {
117                 return status;
118         }
119
120         /* Return result */
121         return NT_STATUS_OK;
122 }
123
124 ");
125
126 $x = new Parse::Pidl::Samba3::ClientNDR();
127
128 $fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" };
129 $x->ParseFunction("foo", $fn);
130 is($x->{res}, 
131 "struct rpccli_bar_state {
132         TALLOC_CTX *out_mem_ctx;
133         WERROR result;
134 };
135
136 static void rpccli_bar_done(struct tevent_req *subreq);
137
138 struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
139                                    struct tevent_context *ev,
140                                    struct rpc_pipe_client *cli)
141 {
142         struct tevent_req *req;
143         struct rpccli_bar_state *state;
144         struct tevent_req *subreq;
145
146         req = tevent_req_create(mem_ctx, &state,
147                                 struct rpccli_bar_state);
148         if (req == NULL) {
149                 return NULL;
150         }
151         state->out_mem_ctx = NULL;
152
153         subreq = dcerpc_bar_send(state,
154                                  ev,
155                                  cli->binding_handle);
156         if (tevent_req_nomem(subreq, req)) {
157                 return tevent_req_post(req, ev);
158         }
159         tevent_req_set_callback(subreq, rpccli_bar_done, req);
160         return req;
161 }
162
163 static void rpccli_bar_done(struct tevent_req *subreq)
164 {
165         struct tevent_req *req = tevent_req_callback_data(
166                 subreq, struct tevent_req);
167         struct rpccli_bar_state *state = tevent_req_data(
168                 req, struct rpccli_bar_state);
169         NTSTATUS status;
170         TALLOC_CTX *mem_ctx;
171
172         if (state->out_mem_ctx) {
173                 mem_ctx = state->out_mem_ctx;
174         } else {
175                 mem_ctx = state;
176         }
177
178         status = dcerpc_bar_recv(subreq,
179                                  mem_ctx,
180                                  &state->result);
181         TALLOC_FREE(subreq);
182         if (!NT_STATUS_IS_OK(status)) {
183                 tevent_req_nterror(req, status);
184                 return;
185         }
186
187         tevent_req_done(req);
188 }
189
190 NTSTATUS rpccli_bar_recv(struct tevent_req *req,
191                          TALLOC_CTX *mem_ctx,
192                          WERROR *result)
193 {
194         struct rpccli_bar_state *state = tevent_req_data(
195                 req, struct rpccli_bar_state);
196         NTSTATUS status;
197
198         if (tevent_req_is_nterror(req, &status)) {
199                 tevent_req_received(req);
200                 return status;
201         }
202
203         /* Steal possbile out parameters to the callers context */
204         talloc_steal(mem_ctx, state->out_mem_ctx);
205
206         /* Return result */
207         *result = state->result;
208
209         tevent_req_received(req);
210         return NT_STATUS_OK;
211 }
212
213 NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
214                     TALLOC_CTX *mem_ctx,
215                     WERROR *werror)
216 {
217         WERROR result;
218         NTSTATUS status;
219
220         status = dcerpc_bar(cli->binding_handle,
221                             mem_ctx,
222                             &result);
223         if (!NT_STATUS_IS_OK(status)) {
224                 return status;
225         }
226
227         /* Return result */
228         if (werror) {
229                 *werror = result;
230         }
231
232         return werror_to_ntstatus(result);
233 }
234
235 ");
236
237 $x = new Parse::Pidl::Samba3::ClientNDR();
238
239 $fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" };
240 my $e = { NAME => "foo", ORIGINAL => { FILE => "f", LINE => -1 },
241           LEVELS => [ { TYPE => "ARRAY", SIZE_IS => "mysize" }, { TYPE => "DATA", DATA_TYPE => "int" } ]};
242
243 $x->ParseOutputArgument($fn, $e);
244 is($x->{res}, "memcpy(foo, r.out.foo, (mysize) * sizeof(*foo));\n");