2 # (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3 # Published under the GNU General Public License
7 use Test
::More tests
=> 38;
8 use FindBin
qw($RealBin);
11 use Parse::Pidl::Util qw(MyDumper);
12 use Parse
::Pidl
::Samba4
::NDR
::Parser
qw(check_null_pointer
13 GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
14 EnvSubstituteValue NeededFunction NeededElement NeededType $res
15 NeededInterface TypeFunctionName);
18 sub print_fn
($) { my $x = shift; $output.=$x; }
20 # Test case 1: Simple unique pointer dereference
23 my $fn = check_null_pointer
({
31 POINTER_TYPE
=> "unique" },
37 }, { bla
=> "r->in.bla" }, \
&print_fn
, "return;");
40 test_warnings
("", sub { $fn->("r->in.bla"); });
42 is
($output, "if (r->in.bla == NULL) return;");
44 # Test case 2: Simple ref pointer dereference
47 $fn = check_null_pointer
({
55 POINTER_TYPE
=> "ref" },
61 }, { bla
=> "r->in.bla" }, \
&print_fn
, undef);
63 test_warnings
("", sub { $fn->("r->in.bla"); });
67 # Test case 3: Illegal dereference
70 $fn = check_null_pointer
({
83 }, { bla
=> "r->in.bla" }, \
&print_fn
, undef);
85 test_warnings
("nofile:1: too much dereferences for `bla'\n",
86 sub { $fn->("r->in.bla"); });
90 # Test case 4: Double pointer dereference
93 $fn = check_null_pointer
({
101 POINTER_TYPE
=> "unique" },
104 POINTER_TYPE
=> "unique" },
110 }, { bla
=> "r->in.bla" }, \
&print_fn
, "return;");
113 sub { $fn->("*r->in.bla"); });
115 is
($output, "if (*r->in.bla == NULL) return;");
117 # Test case 5: Unknown variable
120 $fn = check_null_pointer
({
133 }, { }, \
&print_fn
, "return;");
135 test_warnings
("nofile:2: unknown dereferenced expression `r->in.bla'\n",
136 sub { $fn->("r->in.bla"); });
138 is
($output, "if (r->in.bla == NULL) return;");
140 # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
141 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["in"], NAME
=> "foo" } ] };
142 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionInEnv
($fn));
144 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out"], NAME
=> "foo" } ] };
145 is_deeply
({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv
($fn));
147 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out", "in"], NAME
=> "foo" } ] };
148 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionInEnv
($fn));
150 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out", "in"], NAME
=> "foo" } ] };
151 is_deeply
({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv
($fn));
153 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["in"], NAME
=> "foo" } ] };
154 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv
($fn));
156 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out"], NAME
=> "foo" } ] };
157 is_deeply
({ }, GenerateFunctionInEnv
($fn));
159 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
160 is_deeply
({ foo
=> "r->foo", bar
=> "r->bar", this
=> "r" },
161 GenerateStructEnv
($fn, "r"));
163 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
164 is_deeply
({ foo
=> "some->complex.variable->foo",
165 bar
=> "some->complex.variable->bar",
166 this
=> "some->complex.variable" },
167 GenerateStructEnv
($fn, "some->complex.variable"));
169 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 3 }} ] };
171 my $env = GenerateStructEnv
($fn, "r");
172 EnvSubstituteValue
($env, $fn);
173 is_deeply
($env, { foo
=> 3, this
=> "r" });
175 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
176 $env = GenerateStructEnv
($fn, "r");
177 EnvSubstituteValue
($env, $fn);
178 is_deeply
($env, { foo
=> 'r->foo', bar
=> 'r->bar', this
=> "r" });
180 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 0 }} ] };
182 $env = GenerateStructEnv
($fn, "r");
183 EnvSubstituteValue
($env, $fn);
184 is_deeply
($env, { foo
=> 0, this
=> "r" });
187 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "pull", $needed);
188 is_deeply
($needed, { ndr_pull_foo
=> 1 });
190 # old settings should be kept
191 $needed = { ndr_pull_foo
=> 0 };
192 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "pull", $needed);
193 is_deeply
($needed, { ndr_pull_foo
=> 0 });
195 # print/pull/push are independent of each other
196 $needed = { ndr_pull_foo
=> 0 };
197 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "print", $needed);
198 is_deeply
($needed, { ndr_pull_foo
=> 0, ndr_print_foo
=> 1 });
201 NeededFunction
({ NAME
=> "foo", ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] }, $needed);
202 is_deeply
($needed, { ndr_pull_foo
=> 1, ndr_print_foo
=> 1, ndr_push_foo
=> 1,
203 ndr_pull_bar
=> 1, ndr_print_bar
=> 1, ndr_push_bar
=> 1});
205 # push/pull/print are always set for functions
206 $needed = { ndr_pull_foo
=> 0 };
207 NeededFunction
({ NAME
=> "foo", ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] }, $needed);
208 is_deeply
($needed, { ndr_pull_foo
=> 1, ndr_print_foo
=> 1, ndr_push_foo
=> 1,
209 ndr_pull_bar
=> 1, ndr_push_bar
=> 1, ndr_print_bar
=> 1});
211 # public structs are always needed
213 NeededType
({ NAME
=> "bla", TYPE
=> "TYPEDEF",
214 DATA
=> { TYPE
=> "STRUCT", ELEMENTS
=> [] } },
216 is_deeply
($needed, { });
219 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { public
=> 1 }, NAME
=> "bla",
221 DATA
=> { TYPE
=> "STRUCT", ELEMENTS
=> [] } } ] },
223 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_push_bla
=> 1, ndr_print_bla
=> 1 });
225 # make sure types for elements are set too
227 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { public
=> 1 }, NAME
=> "bla",
229 DATA
=> { TYPE
=> "STRUCT",
230 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } } ] },
232 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_pull_bar
=> 1, ndr_push_bla
=> 1, ndr_push_bar
=> 1,
233 ndr_print_bla
=> 1, ndr_print_bar
=> 1});
236 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { gensize
=> 1}, NAME
=> "bla",
238 DATA
=> { TYPE
=> "STRUCT",
239 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } } ] },
241 is_deeply
($needed, { ndr_size_bla
=> 1 });
243 # make sure types for elements are set too
244 $needed = { ndr_pull_bla
=> 1 };
245 NeededType
({ NAME
=> "bla",
247 DATA
=> { TYPE
=> "STRUCT",
248 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } },
250 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_pull_bar
=> 1 });
253 NeededInterface
({ TYPES
=> [ { PROPERTIES
=> { public
=> 1},
256 DATA
=> { TYPE
=> "STRUCT",
257 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "rep" } ] } } ] }, $needed);
258 is_deeply
($needed, { ndr_pull_bla
=> 1, ndr_push_bla
=> 1, ndr_print_bla
=> 1,
260 ndr_pull_bar
=> 1, ndr_push_bar
=> 1,
261 ndr_bar_to_rep
=> 1, ndr_rep_to_bar
=> 1});
264 Parse
::Pidl
::Samba4
::NDR
::Parser
::ParseStructPush
({
269 ELEMENTS
=> [ ]}, "x");
270 is
($res, "if (ndr_flags & NDR_SCALARS) {
271 NDR_CHECK(ndr_push_align(ndr, 4));
273 if (ndr_flags & NDR_BUFFERS) {
281 REPRESENTATION_TYPE
=> "mytype",
284 { LEVEL_INDEX
=> 0, TYPE
=> "DATA", DATA_TYPE
=> "mytype" }
286 Parse
::Pidl
::Samba4
::NDR
::Parser
::ParseStructPush
({
291 SURROUNDING_ELEMENT
=> $e,
292 ELEMENTS
=> [ $e ]}, "x");
293 is
($res, "if (ndr_flags & NDR_SCALARS) {
294 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1)));
295 NDR_CHECK(ndr_push_align(ndr, 4));
296 NDR_CHECK(ndr_push_mytype(ndr, NDR_SCALARS, &x->el1));
298 if (ndr_flags & NDR_BUFFERS) {
302 is
(TypeFunctionName
("ndr_pull", "uint32"), "ndr_pull_uint32");
303 is
(TypeFunctionName
("ndr_pull", {TYPE
=> "ENUM", NAME
=> "bar"}), "ndr_pull_ENUM_bar");
304 is
(TypeFunctionName
("ndr_pull", {TYPE
=> "TYPEDEF", NAME
=> "bar", DATA
=> undef}), "ndr_pull_bar");
305 is
(TypeFunctionName
("ndr_push", {TYPE
=> "STRUCT", NAME
=> "bar"}), "ndr_push_STRUCT_bar");