2 # (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3 # Published under the GNU General Public License
7 use Test
::More tests
=> 31;
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 NeededTypedef);
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" }, GenerateStructEnv
($fn));
161 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 3 }} ] };
163 my $env = GenerateStructEnv
($fn);
164 EnvSubstituteValue
($env, $fn);
165 is_deeply
($env, { foo
=> 3, this
=> "r" });
167 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
168 $env = GenerateStructEnv
($fn);
169 EnvSubstituteValue
($env, $fn);
170 is_deeply
($env, { foo
=> 'r->foo', bar
=> 'r->bar', this
=> "r" });
172 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 0 }} ] };
174 $env = GenerateStructEnv
($fn);
175 EnvSubstituteValue
($env, $fn);
176 is_deeply
($env, { foo
=> 0, this
=> "r" });
179 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "pull", $needed);
180 is_deeply
($needed, { pull_foo
=> 1 });
182 # old settings should be kept
183 $needed = { pull_foo
=> 0 };
184 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "pull", $needed);
185 is_deeply
($needed, { pull_foo
=> 0 });
187 # print/pull/push are independent of each other
188 $needed = { pull_foo
=> 0 };
189 NeededElement
({ TYPE
=> "foo", REPRESENTATION_TYPE
=> "foo" }, "print", $needed);
190 is_deeply
($needed, { pull_foo
=> 0, print_foo
=> 1 });
193 NeededFunction
({ NAME
=> "foo", ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] }, $needed);
194 is_deeply
($needed, { pull_foo
=> 1, print_foo
=> 1, push_foo
=> 1,
195 pull_bar
=> 1, print_bar
=> 1, push_bar
=> 1});
197 # push/pull/print are always set for functions
198 $needed = { pull_foo
=> 0 };
199 NeededFunction
({ NAME
=> "foo", ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] }, $needed);
200 is_deeply
($needed, { pull_foo
=> 1, print_foo
=> 1, push_foo
=> 1,
201 pull_bar
=> 1, push_bar
=> 1, print_bar
=> 1});
203 # public structs are always needed
205 NeededTypedef
({ NAME
=> "bla", DATA
=> { TYPE
=> "STRUCT", ELEMENTS
=> [] } },
207 is_deeply
($needed, { });
210 NeededTypedef
({ PROPERTIES
=> { public
=> 1 }, NAME
=> "bla",
211 DATA
=> { TYPE
=> "STRUCT", ELEMENTS
=> [] } },
213 is_deeply
($needed, { pull_bla
=> 1, print_bla
=> 1, push_bla
=> 1 });
215 # make sure types for elements are set too
217 NeededTypedef
({ PROPERTIES
=> { public
=> 1 }, NAME
=> "bla",
218 DATA
=> { TYPE
=> "STRUCT",
219 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } },
221 is_deeply
($needed, { pull_bla
=> 1, print_bla
=> 1, push_bla
=> 1,
222 pull_bar
=> 1, print_bar
=> 1, push_bar
=> 1});
225 NeededTypedef
({ PROPERTIES
=> { gensize
=> 1}, NAME
=> "bla",
226 DATA
=> { TYPE
=> "STRUCT",
227 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } },
229 is_deeply
($needed, { ndr_size_bla
=> 1 });
231 # make sure types for elements are set too
232 $needed = { pull_bla
=> 1 };
233 NeededTypedef
({ NAME
=> "bla",
234 DATA
=> { TYPE
=> "STRUCT",
235 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "bar" } ] } },
237 is_deeply
($needed, { pull_bla
=> 1, pull_bar
=> 1 });
240 NeededTypedef
({ PROPERTIES
=> { public
=> 1},
242 DATA
=> { TYPE
=> "STRUCT",
243 ELEMENTS
=> [ { TYPE
=> "bar", REPRESENTATION_TYPE
=> "rep" } ] } },
245 is_deeply
($needed, { pull_bla
=> 1, push_bla
=> 1, print_bla
=> 1, print_rep
=> 1,
246 pull_bar
=> 1, push_bar
=> 1,
247 ndr_bar_to_rep
=> 1, ndr_rep_to_bar
=> 1});