[745] | 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;
|
---|
| 6 |
|
---|
| 7 | use Test::More tests => 31;
|
---|
| 8 | use FindBin qw($RealBin);
|
---|
| 9 | use lib "$RealBin";
|
---|
| 10 | use Util;
|
---|
| 11 | use strict;
|
---|
| 12 | use Parse::Pidl::Util qw(MyDumper);
|
---|
| 13 | use Parse::Pidl::Samba4::NDR::Parser qw(check_null_pointer
|
---|
| 14 | NeededFunction NeededElement NeededType
|
---|
| 15 | NeededInterface TypeFunctionName ParseElementPrint);
|
---|
| 16 |
|
---|
| 17 | my $output;
|
---|
| 18 | sub print_fn($) { my $x = shift; $output.=$x; }
|
---|
| 19 |
|
---|
| 20 | # Test case 1: Simple unique pointer dereference
|
---|
| 21 |
|
---|
| 22 | $output = "";
|
---|
| 23 | my $fn = check_null_pointer({
|
---|
| 24 | PARENT => {
|
---|
| 25 | ELEMENTS => [
|
---|
| 26 | {
|
---|
| 27 | NAME => "bla",
|
---|
| 28 | LEVELS => [
|
---|
| 29 | { TYPE => "POINTER",
|
---|
| 30 | POINTER_INDEX => 0,
|
---|
| 31 | POINTER_TYPE => "unique" },
|
---|
| 32 | { TYPE => "DATA" }
|
---|
| 33 | ],
|
---|
| 34 | },
|
---|
| 35 | ]
|
---|
| 36 | }
|
---|
| 37 | }, { bla => "r->in.bla" }, \&print_fn, "return;");
|
---|
| 38 |
|
---|
| 39 |
|
---|
| 40 | test_warnings("", sub { $fn->("r->in.bla"); });
|
---|
| 41 |
|
---|
| 42 | is($output, "if (r->in.bla == NULL) return;");
|
---|
| 43 |
|
---|
| 44 | # Test case 2: Simple ref pointer dereference
|
---|
| 45 |
|
---|
| 46 | $output = "";
|
---|
| 47 | $fn = check_null_pointer({
|
---|
| 48 | PARENT => {
|
---|
| 49 | ELEMENTS => [
|
---|
| 50 | {
|
---|
| 51 | NAME => "bla",
|
---|
| 52 | LEVELS => [
|
---|
| 53 | { TYPE => "POINTER",
|
---|
| 54 | POINTER_INDEX => 0,
|
---|
| 55 | POINTER_TYPE => "ref" },
|
---|
| 56 | { TYPE => "DATA" }
|
---|
| 57 | ],
|
---|
| 58 | },
|
---|
| 59 | ]
|
---|
| 60 | }
|
---|
| 61 | }, { bla => "r->in.bla" }, \&print_fn, undef);
|
---|
| 62 |
|
---|
| 63 | test_warnings("", sub { $fn->("r->in.bla"); });
|
---|
| 64 |
|
---|
| 65 | is($output, "");
|
---|
| 66 |
|
---|
| 67 | # Test case 3: Illegal dereference
|
---|
| 68 |
|
---|
| 69 | $output = "";
|
---|
| 70 | $fn = check_null_pointer({
|
---|
| 71 | FILE => "nofile",
|
---|
| 72 | LINE => 1,
|
---|
| 73 | PARENT => {
|
---|
| 74 | ELEMENTS => [
|
---|
| 75 | {
|
---|
| 76 | NAME => "bla",
|
---|
| 77 | LEVELS => [
|
---|
| 78 | { TYPE => "DATA" }
|
---|
| 79 | ],
|
---|
| 80 | },
|
---|
| 81 | ]
|
---|
| 82 | }
|
---|
| 83 | }, { bla => "r->in.bla" }, \&print_fn, undef);
|
---|
| 84 |
|
---|
| 85 | test_warnings("nofile:1: too much dereferences for `bla'\n",
|
---|
| 86 | sub { $fn->("r->in.bla"); });
|
---|
| 87 |
|
---|
| 88 | is($output, "");
|
---|
| 89 |
|
---|
| 90 | # Test case 4: Double pointer dereference
|
---|
| 91 |
|
---|
| 92 | $output = "";
|
---|
| 93 | $fn = check_null_pointer({
|
---|
| 94 | PARENT => {
|
---|
| 95 | ELEMENTS => [
|
---|
| 96 | {
|
---|
| 97 | NAME => "bla",
|
---|
| 98 | LEVELS => [
|
---|
| 99 | { TYPE => "POINTER",
|
---|
| 100 | POINTER_INDEX => 0,
|
---|
| 101 | POINTER_TYPE => "unique" },
|
---|
| 102 | { TYPE => "POINTER",
|
---|
| 103 | POINTER_INDEX => 1,
|
---|
| 104 | POINTER_TYPE => "unique" },
|
---|
| 105 | { TYPE => "DATA" }
|
---|
| 106 | ],
|
---|
| 107 | },
|
---|
| 108 | ]
|
---|
| 109 | }
|
---|
| 110 | }, { bla => "r->in.bla" }, \&print_fn, "return;");
|
---|
| 111 |
|
---|
| 112 | test_warnings("",
|
---|
| 113 | sub { $fn->("*r->in.bla"); });
|
---|
| 114 |
|
---|
| 115 | is($output, "if (*r->in.bla == NULL) return;");
|
---|
| 116 |
|
---|
| 117 | # Test case 5: Unknown variable
|
---|
| 118 |
|
---|
| 119 | $output = "";
|
---|
| 120 | $fn = check_null_pointer({
|
---|
| 121 | FILE => "nofile",
|
---|
| 122 | LINE => 2,
|
---|
| 123 | PARENT => {
|
---|
| 124 | ELEMENTS => [
|
---|
| 125 | {
|
---|
| 126 | NAME => "bla",
|
---|
| 127 | LEVELS => [
|
---|
| 128 | { TYPE => "DATA" }
|
---|
| 129 | ],
|
---|
| 130 | },
|
---|
| 131 | ]
|
---|
| 132 | }
|
---|
| 133 | }, { }, \&print_fn, "return;");
|
---|
| 134 |
|
---|
| 135 | test_warnings("nofile:2: unknown dereferenced expression `r->in.bla'\n",
|
---|
| 136 | sub { $fn->("r->in.bla"); });
|
---|
| 137 |
|
---|
| 138 | is($output, "if (r->in.bla == NULL) return;");
|
---|
| 139 |
|
---|
| 140 | my $needed = {};
|
---|
| 141 | NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
|
---|
| 142 | is_deeply($needed, { ndr_pull_foo => 1 });
|
---|
| 143 |
|
---|
| 144 | # old settings should be kept
|
---|
| 145 | $needed = { ndr_pull_foo => 0 };
|
---|
| 146 | NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
|
---|
| 147 | is_deeply($needed, { ndr_pull_foo => 0 });
|
---|
| 148 |
|
---|
| 149 | # print/pull/push are independent of each other
|
---|
| 150 | $needed = { ndr_pull_foo => 0 };
|
---|
| 151 | NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "print", $needed);
|
---|
| 152 | is_deeply($needed, { ndr_pull_foo => 0, ndr_print_foo => 1 });
|
---|
| 153 |
|
---|
| 154 | $needed = { };
|
---|
| 155 | NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
|
---|
| 156 | is_deeply($needed, { ndr_pull_foo => 1, ndr_print_foo => 1, ndr_push_foo => 1,
|
---|
| 157 | ndr_pull_bar => 1, ndr_print_bar => 1, ndr_push_bar => 1});
|
---|
| 158 |
|
---|
| 159 | # push/pull/print are always set for functions
|
---|
| 160 | $needed = { ndr_pull_foo => 0 };
|
---|
| 161 | NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
|
---|
| 162 | is_deeply($needed, { ndr_pull_foo => 1, ndr_print_foo => 1, ndr_push_foo => 1,
|
---|
| 163 | ndr_pull_bar => 1, ndr_push_bar => 1, ndr_print_bar => 1});
|
---|
| 164 |
|
---|
| 165 | # public structs are always needed
|
---|
| 166 | $needed = {};
|
---|
| 167 | NeededType({ NAME => "bla", TYPE => "TYPEDEF",
|
---|
| 168 | DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
|
---|
| 169 | $needed, "pull");
|
---|
| 170 | is_deeply($needed, { });
|
---|
| 171 |
|
---|
| 172 | $needed = {};
|
---|
| 173 | NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
|
---|
| 174 | TYPE => "TYPEDEF",
|
---|
| 175 | DATA => { TYPE => "STRUCT", ELEMENTS => [] } } ] },
|
---|
| 176 | $needed);
|
---|
| 177 | is_deeply($needed, { ndr_pull_bla => 1, ndr_push_bla => 1, ndr_print_bla => 1 });
|
---|
| 178 |
|
---|
| 179 | # make sure types for elements are set too
|
---|
| 180 | $needed = {};
|
---|
| 181 | NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
|
---|
| 182 | TYPE => "TYPEDEF",
|
---|
| 183 | DATA => { TYPE => "STRUCT",
|
---|
| 184 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
|
---|
| 185 | $needed);
|
---|
| 186 | is_deeply($needed, { ndr_pull_bla => 1, ndr_pull_bar => 1, ndr_push_bla => 1, ndr_push_bar => 1,
|
---|
| 187 | ndr_print_bla => 1, ndr_print_bar => 1});
|
---|
| 188 |
|
---|
| 189 | $needed = {};
|
---|
| 190 | NeededInterface({ TYPES => [ { PROPERTIES => { gensize => 1}, NAME => "bla",
|
---|
| 191 | TYPE => "TYPEDEF",
|
---|
| 192 | DATA => { TYPE => "STRUCT",
|
---|
| 193 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
|
---|
| 194 | $needed);
|
---|
| 195 | is_deeply($needed, { ndr_size_bla => 1 });
|
---|
| 196 |
|
---|
| 197 | # make sure types for elements are set too
|
---|
| 198 | $needed = { ndr_pull_bla => 1 };
|
---|
| 199 | NeededType({ NAME => "bla",
|
---|
| 200 | TYPE => "TYPEDEF",
|
---|
| 201 | DATA => { TYPE => "STRUCT",
|
---|
| 202 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
|
---|
| 203 | $needed, "pull");
|
---|
| 204 | is_deeply($needed, { ndr_pull_bla => 1, ndr_pull_bar => 1 });
|
---|
| 205 |
|
---|
| 206 | $needed = {};
|
---|
| 207 | NeededInterface({ TYPES => [ { PROPERTIES => { public => 1},
|
---|
| 208 | NAME => "bla",
|
---|
| 209 | TYPE => "TYPEDEF",
|
---|
| 210 | DATA => { TYPE => "STRUCT",
|
---|
| 211 | ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "rep" } ] } } ] }, $needed);
|
---|
| 212 | is_deeply($needed, { ndr_pull_bla => 1, ndr_push_bla => 1, ndr_print_bla => 1,
|
---|
| 213 | ndr_print_rep => 1,
|
---|
| 214 | ndr_pull_bar => 1, ndr_push_bar => 1,
|
---|
| 215 | ndr_bar_to_rep => 1, ndr_rep_to_bar => 1});
|
---|
| 216 |
|
---|
| 217 | my $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
| 218 | $generator->ParseStructPush({
|
---|
| 219 | NAME => "mystruct",
|
---|
| 220 | TYPE => "STRUCT",
|
---|
| 221 | PROPERTIES => {},
|
---|
| 222 | ALIGN => 4,
|
---|
| 223 | ELEMENTS => [ ]}, "ndr", "x");
|
---|
| 224 | is($generator->{res}, "if (ndr_flags & NDR_SCALARS) {
|
---|
| 225 | NDR_CHECK(ndr_push_align(ndr, 4));
|
---|
| 226 | NDR_CHECK(ndr_push_trailer_align(ndr, 4));
|
---|
| 227 | }
|
---|
| 228 | if (ndr_flags & NDR_BUFFERS) {
|
---|
| 229 | }
|
---|
| 230 | ");
|
---|
| 231 |
|
---|
| 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}, "if (ndr_flags & NDR_SCALARS) {
|
---|
| 249 | NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1)));
|
---|
| 250 | NDR_CHECK(ndr_push_align(ndr, 4));
|
---|
| 251 | NDR_CHECK(ndr_push_mytype(ndr, NDR_SCALARS, &x->el1));
|
---|
| 252 | NDR_CHECK(ndr_push_trailer_align(ndr, 4));
|
---|
| 253 | }
|
---|
| 254 | if (ndr_flags & NDR_BUFFERS) {
|
---|
| 255 | }
|
---|
| 256 | ");
|
---|
| 257 |
|
---|
| 258 | is(TypeFunctionName("ndr_pull", "uint32"), "ndr_pull_uint32");
|
---|
| 259 | is(TypeFunctionName("ndr_pull", {TYPE => "ENUM", NAME => "bar"}), "ndr_pull_ENUM_bar");
|
---|
| 260 | is(TypeFunctionName("ndr_pull", {TYPE => "TYPEDEF", NAME => "bar", DATA => undef}), "ndr_pull_bar");
|
---|
| 261 | is(TypeFunctionName("ndr_push", {TYPE => "STRUCT", NAME => "bar"}), "ndr_push_STRUCT_bar");
|
---|
| 262 |
|
---|
| 263 | # check noprint works
|
---|
| 264 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
| 265 | $generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt",
|
---|
| 266 | PROPERTIES => { noprint => 1},
|
---|
| 267 | LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt"} ]},
|
---|
| 268 | "ndr", "var", { "x" => "r->foobar" } );
|
---|
| 269 | is($generator->{res}, "");
|
---|
| 270 |
|
---|
| 271 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
| 272 | $generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt",
|
---|
| 273 | PROPERTIES => {},
|
---|
| 274 | LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt" }]},
|
---|
| 275 | "ndr", "var", { "x" => "r->foobar" } );
|
---|
| 276 | is($generator->{res}, "ndr_print_rt(ndr, \"x\", &var);\n");
|
---|
| 277 |
|
---|
| 278 | # make sure that a print function for an element with value() set works
|
---|
| 279 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
| 280 | $generator->ParseElementPrint({ NAME => "x", TYPE => "uint32", REPRESENTATION_TYPE => "uint32",
|
---|
| 281 | PROPERTIES => { value => "23" },
|
---|
| 282 | LEVELS => [ { TYPE => "DATA", DATA_TYPE => "uint32"} ]},
|
---|
| 283 | "ndr", "var", { "x" => "r->foobar" } );
|
---|
| 284 | is($generator->{res}, "ndr_print_uint32(ndr, \"x\", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?23:var);\n");
|
---|
| 285 |
|
---|
| 286 | $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
---|
| 287 | $generator->AuthServiceStruct("bridge", "\"rot13\",\"onetimepad\"");
|
---|
| 288 | is($generator->{res}, "static const char * const bridge_authservice_strings[] = {
|
---|
| 289 | \"rot13\",
|
---|
| 290 | \"onetimepad\",
|
---|
| 291 | };
|
---|
| 292 |
|
---|
| 293 | static const struct ndr_interface_string_array bridge_authservices = {
|
---|
| 294 | .count = 2,
|
---|
| 295 | .names = bridge_authservice_strings
|
---|
| 296 | };
|
---|
| 297 |
|
---|
| 298 | ");
|
---|