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