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 => 31;
|
---|
8 | use FindBin qw($RealBin);
|
---|
9 | use lib "$RealBin";
|
---|
10 | use Util;
|
---|
11 | use strict;
|
---|
12 | use Parse::Pidl::Util qw(MyDumper);
|
---|
13 | use Parse::Pidl::Samba4::NDR::Parser qw(check_null_pointer
|
---|
14 | NeededFunction NeededElement NeededType
|
---|
15 | NeededInterface TypeFunctionName ParseElementPrint);
|
---|
16 |
|
---|
17 | my $output;
|
---|
18 | sub print_fn($) { my $x = shift; $output.=$x; }
|
---|
19 |
|
---|
20 | # Test case 1: Simple unique pointer dereference
|
---|
21 |
|
---|
22 | $output = "";
|
---|
23 | my $fn = check_null_pointer({
|
---|
24 | PARENT => {
|
---|
25 | ELEMENTS => [
|
---|
26 | {
|
---|
27 | NAME => "bla",
|
---|
28 | LEVELS => [
|
---|
29 | { TYPE => "POINTER",
|
---|
30 | POINTER_INDEX => 0,
|
---|
31 | POINTER_TYPE => "unique" },
|
---|
32 | { TYPE => "DATA" }
|
---|
33 | ],
|
---|
34 | },
|
---|
35 | ]
|
---|
36 | }
|
---|
37 | }, { bla => "r->in.bla" }, \&print_fn, "return;");
|
---|
38 |
|
---|
39 |
|
---|
40 | test_warnings("", sub { $fn->("r->in.bla"); });
|
---|
41 |
|
---|
42 | is($output, "if (r->in.bla == NULL) return;");
|
---|
43 |
|
---|
44 | # Test case 2: Simple ref pointer dereference
|
---|
45 |
|
---|
46 | $output = "";
|
---|
47 | $fn = check_null_pointer({
|
---|
48 | PARENT => {
|
---|
49 | ELEMENTS => [
|
---|
50 | {
|
---|
51 | NAME => "bla",
|
---|
52 | LEVELS => [
|
---|
53 | { TYPE => "POINTER",
|
---|
54 | POINTER_INDEX => 0,
|
---|
55 | POINTER_TYPE => "ref" },
|
---|
56 | { TYPE => "DATA" }
|
---|
57 | ],
|
---|
58 | },
|
---|
59 | ]
|
---|
60 | }
|
---|
61 | }, { bla => "r->in.bla" }, \&print_fn, undef);
|
---|
62 |
|
---|
63 | test_warnings("", sub { $fn->("r->in.bla"); });
|
---|
64 |
|
---|
65 | is($output, "");
|
---|
66 |
|
---|
67 | # Test case 3: Illegal dereference
|
---|
68 |
|
---|
69 | $output = "";
|
---|
70 | $fn = check_null_pointer({
|
---|
71 | FILE => "nofile",
|
---|
72 | LINE => 1,
|
---|
73 | PARENT => {
|
---|
74 | ELEMENTS => [
|
---|
75 | {
|
---|
76 | NAME => "bla",
|
---|
77 | LEVELS => [
|
---|
78 | { TYPE => "DATA" }
|
---|
79 | ],
|
---|
80 | },
|
---|
81 | ]
|
---|
82 | }
|
---|
83 | }, { bla => "r->in.bla" }, \&print_fn, undef);
|
---|
84 |
|
---|
85 | test_warnings("nofile:1: too much dereferences for `bla'\n",
|
---|
86 | sub { $fn->("r->in.bla"); });
|
---|
87 |
|
---|
88 | is($output, "");
|
---|
89 |
|
---|
90 | # Test case 4: Double pointer dereference
|
---|
91 |
|
---|
92 | $output = "";
|
---|
93 | $fn = check_null_pointer({
|
---|
94 | PARENT => {
|
---|
95 | ELEMENTS => [
|
---|
96 | {
|
---|
97 | NAME => "bla",
|
---|
98 | LEVELS => [
|
---|
99 | { TYPE => "POINTER",
|
---|
100 | POINTER_INDEX => 0,
|
---|
101 | POINTER_TYPE => "unique" },
|
---|
102 | { TYPE => "POINTER",
|
---|
103 | POINTER_INDEX => 1,
|
---|
104 | POINTER_TYPE => "unique" },
|
---|
105 | { TYPE => "DATA" }
|
---|
106 | ],
|
---|
107 | },
|
---|
108 | ]
|
---|
109 | }
|
---|
110 | }, { bla => "r->in.bla" }, \&print_fn, "return;");
|
---|
111 |
|
---|
112 | test_warnings("",
|
---|
113 | sub { $fn->("*r->in.bla"); });
|
---|
114 |
|
---|
115 | is($output, "if (*r->in.bla == NULL) return;");
|
---|
116 |
|
---|
117 | # Test case 5: Unknown variable
|
---|
118 |
|
---|
119 | $output = "";
|
---|
120 | $fn = check_null_pointer({
|
---|
121 | FILE => "nofile",
|
---|
122 | LINE => 2,
|
---|
123 | PARENT => {
|
---|
124 | ELEMENTS => [
|
---|
125 | {
|
---|
126 | NAME => "bla",
|
---|
127 | LEVELS => [
|
---|
128 | { TYPE => "DATA" }
|
---|
129 | ],
|
---|
130 | },
|
---|
131 | ]
|
---|
132 | }
|
---|
133 | }, { }, \&print_fn, "return;");
|
---|
134 |
|
---|
135 | test_warnings("nofile:2: unknown dereferenced expression `r->in.bla'\n",
|
---|
136 | sub { $fn->("r->in.bla"); });
|
---|
137 |
|
---|
138 | is($output, "if (r->in.bla == NULL) return;");
|
---|
139 |
|
---|
140 | my $needed = {};
|
---|
141 | NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
|
---|
142 | is_deeply($needed, { ndr_pull_foo => 1 });
|
---|
143 |
|
---|
144 | # old settings should be kept
|
---|
145 | $needed = { ndr_pull_foo => 0 };
|
---|
146 | NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
|
---|
147 | is_deeply($needed, { ndr_pull_foo => 0 });
|
---|
148 |
|
---|
149 | # print/pull/push are independent of each other
|
---|
150 | $needed = { ndr_pull_foo => 0 };
|
---|
151 | NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "print", $needed);
|
---|
152 | is_deeply($needed, { ndr_pull_foo => 0, ndr_print_foo => 1 });
|
---|
153 |
|
---|
154 | $needed = { };
|
---|
155 | NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
|
---|
156 | is_deeply($needed, { ndr_pull_foo => 1, ndr_print_foo => 1, ndr_push_foo => 1,
|
---|
157 | ndr_pull_bar => 1, ndr_print_bar => 1, ndr_push_bar => 1});
|
---|
158 |
|
---|
159 | # push/pull/print are always set for functions
|
---|
160 | $needed = { ndr_pull_foo => 0 };
|
---|
161 | NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
|
---|
162 | is_deeply($needed, { ndr_pull_foo => 1, ndr_print_foo => 1, ndr_push_foo => 1,
|
---|
163 | ndr_pull_bar => 1, ndr_push_bar => 1, ndr_print_bar => 1});
|
---|
164 |
|
---|
165 | # public structs are always needed
|
---|
166 | $needed = {};
|
---|
167 | NeededType({ NAME => "bla", TYPE => "TYPEDEF",
|
---|
168 | DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
|
---|
169 | $needed, "pull");
|
---|
170 | is_deeply($needed, { });
|
---|
171 |
|
---|
172 | $needed = {};
|
---|
173 | NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
|
---|
174 | TYPE => "TYPEDEF",
|
---|
175 | DATA => { TYPE => "STRUCT", ELEMENTS => [] } } ] },
|
---|
176 | $needed);
|
---|
177 | is_deeply($needed, { ndr_pull_bla => 1, ndr_push_bla => 1, ndr_print_bla => 1 });
|
---|
178 |
|
---|
179 | # make sure types for elements are set too
|
---|
180 | $needed = {};
|
---|
181 | NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
|
---|
182 | TYPE => "TYPEDEF",
|
---|
183 | DATA => { TYPE => "STRUCT",
|
---|
184 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
|
---|
185 | $needed);
|
---|
186 | is_deeply($needed, { ndr_pull_bla => 1, ndr_pull_bar => 1, ndr_push_bla => 1, ndr_push_bar => 1,
|
---|
187 | ndr_print_bla => 1, ndr_print_bar => 1});
|
---|
188 |
|
---|
189 | $needed = {};
|
---|
190 | NeededInterface({ TYPES => [ { PROPERTIES => { gensize => 1}, NAME => "bla",
|
---|
191 | TYPE => "TYPEDEF",
|
---|
192 | DATA => { TYPE => "STRUCT",
|
---|
193 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
|
---|
194 | $needed);
|
---|
195 | is_deeply($needed, { ndr_size_bla => 1 });
|
---|
196 |
|
---|
197 | # make sure types for elements are set too
|
---|
198 | $needed = { ndr_pull_bla => 1 };
|
---|
199 | NeededType({ NAME => "bla",
|
---|
200 | TYPE => "TYPEDEF",
|
---|
201 | DATA => { TYPE => "STRUCT",
|
---|
202 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
|
---|
203 | $needed, "pull");
|
---|
204 | is_deeply($needed, { ndr_pull_bla => 1, ndr_pull_bar => 1 });
|
---|
205 |
|
---|
206 | $needed = {};
|
---|
207 | NeededInterface({ TYPES => [ { PROPERTIES => { public => 1},
|
---|
208 | NAME => "bla",
|
---|
209 | TYPE => "TYPEDEF",
|
---|
210 | DATA => { TYPE => "STRUCT",
|
---|
211 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "rep" } ] } } ] }, $needed);
|
---|
212 | is_deeply($needed, { ndr_pull_bla => 1, ndr_push_bla => 1, ndr_print_bla => 1,
|
---|
213 | ndr_print_rep => 1,
|
---|
214 | ndr_pull_bar => 1, ndr_push_bar => 1,
|
---|
215 | ndr_bar_to_rep => 1, ndr_rep_to_bar => 1});
|
---|
216 |
|
---|
217 | my $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
218 | $generator->ParseStructPush({
|
---|
219 | NAME => "mystruct",
|
---|
220 | TYPE => "STRUCT",
|
---|
221 | PROPERTIES => {},
|
---|
222 | ALIGN => 4,
|
---|
223 | ELEMENTS => [ ]}, "ndr", "x");
|
---|
224 | is($generator->{res}, "if (ndr_flags & NDR_SCALARS) {
|
---|
225 | NDR_CHECK(ndr_push_align(ndr, 4));
|
---|
226 | }
|
---|
227 | if (ndr_flags & NDR_BUFFERS) {
|
---|
228 | }
|
---|
229 | ");
|
---|
230 |
|
---|
231 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
232 | my $e = {
|
---|
233 | NAME => "el1",
|
---|
234 | TYPE => "mytype",
|
---|
235 | REPRESENTATION_TYPE => "mytype",
|
---|
236 | PROPERTIES => {},
|
---|
237 | LEVELS => [
|
---|
238 | { LEVEL_INDEX => 0, TYPE => "DATA", DATA_TYPE => "mytype" }
|
---|
239 | ] };
|
---|
240 | $generator->ParseStructPush({
|
---|
241 | NAME => "mystruct",
|
---|
242 | TYPE => "STRUCT",
|
---|
243 | PROPERTIES => {},
|
---|
244 | ALIGN => 4,
|
---|
245 | SURROUNDING_ELEMENT => $e,
|
---|
246 | ELEMENTS => [ $e ]}, "ndr", "x");
|
---|
247 | is($generator->{res}, "if (ndr_flags & NDR_SCALARS) {
|
---|
248 | NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1)));
|
---|
249 | NDR_CHECK(ndr_push_align(ndr, 4));
|
---|
250 | NDR_CHECK(ndr_push_mytype(ndr, NDR_SCALARS, &x->el1));
|
---|
251 | }
|
---|
252 | if (ndr_flags & NDR_BUFFERS) {
|
---|
253 | }
|
---|
254 | ");
|
---|
255 |
|
---|
256 | is(TypeFunctionName("ndr_pull", "uint32"), "ndr_pull_uint32");
|
---|
257 | is(TypeFunctionName("ndr_pull", {TYPE => "ENUM", NAME => "bar"}), "ndr_pull_ENUM_bar");
|
---|
258 | is(TypeFunctionName("ndr_pull", {TYPE => "TYPEDEF", NAME => "bar", DATA => undef}), "ndr_pull_bar");
|
---|
259 | is(TypeFunctionName("ndr_push", {TYPE => "STRUCT", NAME => "bar"}), "ndr_push_STRUCT_bar");
|
---|
260 |
|
---|
261 | # check noprint works
|
---|
262 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
263 | $generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt",
|
---|
264 | PROPERTIES => { noprint => 1},
|
---|
265 | LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt"} ]},
|
---|
266 | "ndr", "var", { "x" => "r->foobar" } );
|
---|
267 | is($generator->{res}, "");
|
---|
268 |
|
---|
269 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
270 | $generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt",
|
---|
271 | PROPERTIES => {},
|
---|
272 | LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt" }]},
|
---|
273 | "ndr", "var", { "x" => "r->foobar" } );
|
---|
274 | is($generator->{res}, "ndr_print_rt(ndr, \"x\", &var);\n");
|
---|
275 |
|
---|
276 | # make sure that a print function for an element with value() set works
|
---|
277 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
278 | $generator->ParseElementPrint({ NAME => "x", TYPE => "uint32", REPRESENTATION_TYPE => "uint32",
|
---|
279 | PROPERTIES => { value => "23" },
|
---|
280 | LEVELS => [ { TYPE => "DATA", DATA_TYPE => "uint32"} ]},
|
---|
281 | "ndr", "var", { "x" => "r->foobar" } );
|
---|
282 | is($generator->{res}, "ndr_print_uint32(ndr, \"x\", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?23:var);\n");
|
---|
283 |
|
---|
284 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
285 | $generator->AuthServiceStruct("bridge", "\"rot13\",\"onetimepad\"");
|
---|
286 | is($generator->{res}, "static const char * const bridge_authservice_strings[] = {
|
---|
287 | \"rot13\",
|
---|
288 | \"onetimepad\",
|
---|
289 | };
|
---|
290 |
|
---|
291 | static const struct ndr_interface_string_array bridge_authservices = {
|
---|
292 | .count = 2,
|
---|
293 | .names = bridge_authservice_strings
|
---|
294 | };
|
---|
295 |
|
---|
296 | ");
|
---|