2 # (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3 # Published under the GNU General Public License
7 use Test
::More tests
=> 34;
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);
17 sub print_fn($) { my $x = shift; $output.=$x; }
19 # Test case 1: Simple unique pointer dereference
22 my $fn = check_null_pointer({
30 POINTER_TYPE => "unique" },
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
46 $fn = check_null_pointer({
54 POINTER_TYPE => "ref" },
60 }, { bla => "r->in.bla" }, \&print_fn, undef);
62 test_warnings("", sub { $fn->("r->in.bla"); });
66 # Test case 3: Illegal dereference
69 $fn = check_null_pointer({
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"); });
89 # Test case 4: Double pointer dereference
92 $fn = check_null_pointer({
100 POINTER_TYPE => "unique" },
103 POINTER_TYPE => "unique" },
109 }, { bla => "r->in.bla" }, \&print_fn, "return;");
112 sub { $fn->("*r->in.bla"); });
114 is($output, "if (*r->in.bla == NULL) return;");
116 # Test case 5: Unknown variable
119 $fn = check_null_pointer({
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 # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
140 $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
141 is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
143 $fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
144 is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
146 $fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
147 is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
149 $fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
150 is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
152 $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
153 is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv($fn));
155 $fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
156 is_deeply({ }, GenerateFunctionInEnv($fn));
158 $fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
159 is_deeply({ foo => "r->foo", bar => "r->bar", this => "r" },
160 GenerateStructEnv($fn, "r"));
162 $fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
163 is_deeply({ foo => "some->complex.variable->foo",
164 bar => "some->complex.variable->bar",
165 this => "some->complex.variable" },
166 GenerateStructEnv($fn, "some->complex.variable"));
168 $fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 3 }} ] };
170 my $env = GenerateStructEnv($fn, "r");
171 EnvSubstituteValue($env, $fn);
172 is_deeply($env, { foo => 3, this => "r" });
174 $fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
175 $env = GenerateStructEnv($fn, "r");
176 EnvSubstituteValue($env, $fn);
177 is_deeply($env, { foo => 'r->foo', bar => 'r->bar', this => "r" });
179 $fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 0 }} ] };
181 $env = GenerateStructEnv($fn, "r");
182 EnvSubstituteValue($env, $fn);
183 is_deeply($env, { foo => 0, this => "r" });
186 NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
187 is_deeply($needed, { pull_foo => 1 });
189 # old settings should be kept
190 $needed = { pull_foo => 0 };
191 NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
192 is_deeply($needed, { pull_foo => 0 });
194 # print/pull/push are independent of each other
195 $needed = { pull_foo => 0 };
196 NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "print", $needed);
197 is_deeply($needed, { pull_foo => 0, print_foo => 1 });
200 NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
201 is_deeply($needed, { pull_foo => 1, print_foo => 1, push_foo => 1,
202 pull_bar => 1, print_bar => 1, push_bar => 1});
204 # push/pull/print are always set for functions
205 $needed = { pull_foo => 0 };
206 NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
207 is_deeply($needed, { pull_foo => 1, print_foo => 1, push_foo => 1,
208 pull_bar => 1, push_bar => 1, print_bar => 1});
210 # public structs are always needed
212 NeededType({ NAME => "bla", DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
214 is_deeply($needed, { });
217 NeededType({ PROPERTIES => { public => 1 }, NAME => "bla",
218 DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
220 is_deeply($needed, { pull_bla => 1, print_bla => 1, push_bla => 1 });
222 # make sure types for elements are set too
224 NeededType({ PROPERTIES => { public => 1 }, NAME => "bla",
225 DATA => { TYPE => "STRUCT",
226 ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
228 is_deeply($needed, { pull_bla => 1, print_bla => 1, push_bla => 1,
229 pull_bar => 1, print_bar => 1, push_bar => 1});
232 NeededType({ PROPERTIES => { gensize => 1}, NAME => "bla",
233 DATA => { TYPE => "STRUCT",
234 ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
236 is_deeply($needed, { ndr_size_bla => 1 });
238 # make sure types for elements are set too
239 $needed = { pull_bla => 1 };
240 NeededType({ NAME => "bla",
241 DATA => { TYPE => "STRUCT",
242 ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
244 is_deeply($needed, { pull_bla => 1, pull_bar => 1 });
247 NeededType({ PROPERTIES => { public => 1},
249 DATA => { TYPE => "STRUCT",
250 ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "rep" } ] } },
252 is_deeply($needed, { pull_bla => 1, push_bla => 1, print_bla => 1, print_rep => 1,
253 pull_bar => 1, push_bar => 1,
254 ndr_bar_to_rep => 1, ndr_rep_to_bar => 1});
257 Parse::Pidl::Samba4::NDR::Parser::ParseStructPush({
262 ELEMENTS => [ ]}, "x");
263 is($res, "if (ndr_flags & NDR_SCALARS) {
264 NDR_CHECK(ndr_push_align(ndr, 4));
266 if (ndr_flags & NDR_BUFFERS) {
274 REPRESENTATION_TYPE => "mytype",
277 { LEVEL_INDEX => 0, TYPE => "DATA", DATA_TYPE => "mytype" }
279 Parse::Pidl::Samba4::NDR::Parser::ParseStructPush({
284 SURROUNDING_ELEMENT => $e,
285 ELEMENTS => [ $e ]}, "x");
286 is($res, "if (ndr_flags & NDR_SCALARS) {
287 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1)));
288 NDR_CHECK(ndr_push_align(ndr, 4));
289 NDR_CHECK(ndr_push_mytype(ndr, NDR_SCALARS, &x->el1));
291 if (ndr_flags & NDR_BUFFERS) {