2 # (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3 # Published under the GNU General Public License
7 use Test
::More tests
=> 41;
8 use FindBin
qw($RealBin);
12 use Parse::Pidl::Util qw(MyDumper);
13 use Parse
::Pidl
::Samba4
::NDR
::Parser
qw(check_null_pointer
14 GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
15 EnvSubstituteValue NeededFunction NeededElement NeededType
16 NeededInterface TypeFunctionName ParseElementPrint);
19 sub print_fn
($) { my $x = shift; $output.=$x; }
21 # Test case 1: Simple unique pointer dereference
24 my $fn = check_null_pointer
({
32 POINTER_TYPE
=> "unique" },
38 }, { bla
=> "r->in.bla" }, \
&print_fn
, "return;");
41 test_warnings
("", sub { $fn->("r->in.bla"); });
43 is
($output, "if (r->in.bla == NULL) return;");
45 # Test case 2: Simple ref pointer dereference
48 $fn = check_null_pointer
({
56 POINTER_TYPE
=> "ref" },
62 }, { bla
=> "r->in.bla" }, \
&print_fn
, undef);
64 test_warnings
("", sub { $fn->("r->in.bla"); });
68 # Test case 3: Illegal dereference
71 $fn = check_null_pointer
({
84 }, { bla
=> "r->in.bla" }, \
&print_fn
, undef);
86 test_warnings
("nofile:1: too much dereferences for `bla'\n",
87 sub { $fn->("r->in.bla"); });
91 # Test case 4: Double pointer dereference
94 $fn = check_null_pointer
({
102 POINTER_TYPE
=> "unique" },
105 POINTER_TYPE
=> "unique" },
111 }, { bla
=> "r->in.bla" }, \
&print_fn
, "return;");
114 sub { $fn->("*r->in.bla"); });
116 is
($output, "if (*r->in.bla == NULL) return;");
118 # Test case 5: Unknown variable
121 $fn = check_null_pointer
({
134 }, { }, \
&print_fn
, "return;");
136 test_warnings
("nofile:2: unknown dereferenced expression `r->in.bla'\n",
137 sub { $fn->("r->in.bla"); });
139 is
($output, "if (r->in.bla == NULL) return;");
141 # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
142 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["in"], NAME
=> "foo" } ] };
143 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionInEnv
($fn));
145 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out"], NAME
=> "foo" } ] };
146 is_deeply
({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv
($fn));
148 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out", "in"], NAME
=> "foo" } ] };
149 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionInEnv
($fn));
151 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out", "in"], NAME
=> "foo" } ] };
152 is_deeply
({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv
($fn));
154 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["in"], NAME
=> "foo" } ] };
155 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv
($fn));
157 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out"], NAME
=> "foo" } ] };
158 is_deeply
({ }, GenerateFunctionInEnv
($fn));
160 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
161 is_deeply
({ foo
=> "r->foo", bar
=> "r->bar", this
=> "r" },
162 GenerateStructEnv
($fn, "r"));
164 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
165 is_deeply
({ foo
=> "some->complex.variable->foo",
166 bar
=> "some->complex.variable->bar",
167 this
=> "some->complex.variable" },
168 GenerateStructEnv
($fn, "some->complex.variable"));
170 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 3 }} ] };
172 my $env = GenerateStructEnv
($fn, "r");
173 EnvSubstituteValue
($env, $fn);
174 is_deeply
($env, { foo
=> 3, this
=> "r" });
176 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
177 $env = GenerateStructEnv
($fn, "r");
178 EnvSubstituteValue
($env, $fn);
179 is_deeply
($env, { foo
=> 'r->foo', bar
=> 'r->bar', this
=> "r" });
181 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 0 }} ] };
183 $env = GenerateStructEnv
($fn, "r");
184 EnvSubstituteValue
($env, $fn);
185 is_deeply
($env, { foo
=> 0, this
=> "r" });
188 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "pull", $needed);
189 is_deeply
($needed, { ndr_pull_foo
=> 1 });
191 # old settings should be kept
192 $needed = { ndr_pull_foo
=> 0 };
193 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "pull", $needed);
194 is_deeply
($needed, { ndr_pull_foo
=> 0 });
196 # print/pull/push are independent of each other
197 $needed = { ndr_pull_foo
=> 0 };
198 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "print", $needed);
199 is_deeply
($needed, { ndr_pull_foo
=> 0, ndr_print_foo
=> 1 });
202 NeededFunction
({ NAME
=> "foo", ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] }, $needed);
203 is_deeply
($needed, { ndr_pull_foo
=> 1, ndr_print_foo
=> 1, ndr_push_foo
=> 1,
204 ndr_pull_bar
=> 1, ndr_print_bar
=> 1, ndr_push_bar
=> 1});
206 # push/pull/print are always set for functions
207 $needed = { ndr_pull_foo
=> 0 };
208 NeededFunction
({ NAME
=> "foo", ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] }, $needed);
209 is_deeply
($needed, { ndr_pull_foo
=> 1, ndr_print_foo
=> 1, ndr_push_foo
=> 1,
210 ndr_pull_bar
=> 1, ndr_push_bar
=> 1, ndr_print_bar
=> 1});
212 # public structs are always needed
214 NeededType
({ NAME
=> "bla", TYPE
=> "TYPEDEF",
215 DATA
=> { TYPE
=> "STRUCT", ELEMENTS
=> [] } },
217 is_deeply
($needed, { });
220 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { public
=> 1 }, NAME
=> "bla",
222 DATA
=> { TYPE
=> "STRUCT", ELEMENTS
=> [] } } ] },
224 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_push_bla
=> 1, ndr_print_bla
=> 1 });
226 # make sure types for elements are set too
228 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { public
=> 1 }, NAME
=> "bla",
230 DATA
=> { TYPE
=> "STRUCT",
231 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } } ] },
233 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_pull_bar
=> 1, ndr_push_bla
=> 1, ndr_push_bar
=> 1,
234 ndr_print_bla
=> 1, ndr_print_bar
=> 1});
237 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { gensize
=> 1}, NAME
=> "bla",
239 DATA
=> { TYPE
=> "STRUCT",
240 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } } ] },
242 is_deeply
($needed, { ndr_size_bla
=> 1 });
244 # make sure types for elements are set too
245 $needed = { ndr_pull_bla
=> 1 };
246 NeededType
({ NAME
=> "bla",
248 DATA
=> { TYPE
=> "STRUCT",
249 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } },
251 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_pull_bar
=> 1 });
254 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { public
=> 1},
257 DATA
=> { TYPE
=> "STRUCT",
258 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "rep" } ] } } ] }, $needed);
259 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_push_bla
=> 1, ndr_print_bla
=> 1,
261 ndr_pull_bar
=> 1, ndr_push_bar
=> 1,
262 ndr_bar_to_rep
=> 1, ndr_rep_to_bar
=> 1});
264 my $generator = new Parse
::Pidl
::Samba4
::NDR
::Parser
();
265 $generator->ParseStructPush({
270 ELEMENTS
=> [ ]}, "x");
271 is
($generator->{res
}, "if (ndr_flags & NDR_SCALARS) {
272 NDR_CHECK(ndr_push_align(ndr, 4));
274 if (ndr_flags & NDR_BUFFERS) {
278 $generator = new Parse
::Pidl
::Samba4
::NDR
::Parser
();
282 REPRESENTATION_TYPE
=> "mytype",
285 { LEVEL_INDEX
=> 0, TYPE
=> "DATA", DATA_TYPE
=> "mytype" }
287 $generator->ParseStructPush({
292 SURROUNDING_ELEMENT
=> $e,
293 ELEMENTS
=> [ $e ]}, "x");
294 is
($generator->{res
}, "if (ndr_flags & NDR_SCALARS) {
295 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1)));
296 NDR_CHECK(ndr_push_align(ndr, 4));
297 NDR_CHECK(ndr_push_mytype(ndr, NDR_SCALARS, &x->el1));
299 if (ndr_flags & NDR_BUFFERS) {
303 is
(TypeFunctionName
("ndr_pull", "uint32"), "ndr_pull_uint32");
304 is
(TypeFunctionName
("ndr_pull", {TYPE
=> "ENUM", NAME
=> "bar"}), "ndr_pull_ENUM_bar");
305 is
(TypeFunctionName
("ndr_pull", {TYPE
=> "TYPEDEF", NAME
=> "bar", DATA
=> undef}), "ndr_pull_bar");
306 is
(TypeFunctionName
("ndr_push", {TYPE
=> "STRUCT", NAME
=> "bar"}), "ndr_push_STRUCT_bar");
308 # check noprint works
309 $generator = new Parse
::Pidl
::Samba4
::NDR
::Parser
();
310 $generator->ParseElementPrint({ NAME
=> "x", TYPE
=> "rt", REPRESENTATION_TYPE
=> "rt",
311 PROPERTIES
=> { noprint
=> 1},
312 LEVELS
=> [ { TYPE
=> "DATA", DATA_TYPE
=> "rt"} ]}, "var", { "x" => "r->foobar" } );
313 is
($generator->{res
}, "");
315 $generator = new Parse
::Pidl
::Samba4
::NDR
::Parser
();
316 $generator->ParseElementPrint({ NAME
=> "x", TYPE
=> "rt", REPRESENTATION_TYPE
=> "rt",
318 LEVELS
=> [ { TYPE
=> "DATA", DATA_TYPE
=> "rt" }]}, "var", { "x" => "r->foobar" } );
319 is
($generator->{res
}, "ndr_print_rt(ndr, \"x\", &var);\n");
321 # make sure that a print function for an element with value() set works
322 $generator = new Parse
::Pidl
::Samba4
::NDR
::Parser
();
323 $generator->ParseElementPrint({ NAME
=> "x", TYPE
=> "uint32", REPRESENTATION_TYPE
=> "uint32",
324 PROPERTIES
=> { value
=> "23" },
325 LEVELS
=> [ { TYPE
=> "DATA", DATA_TYPE
=> "uint32"} ]}, "var", { "x" => "r->foobar" } );
326 is
($generator->{res
}, "ndr_print_uint32(ndr, \"x\", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?23:var);\n");