1#!/usr/bin/perl 2# (C) 2007 Jelmer Vernooij <jelmer@samba.org> 3# Published under the GNU General Public License 4use strict; 5use warnings; 6 7use Test::More tests => 47; 8use FindBin qw($RealBin); 9use lib "$RealBin"; 10use Util; 11use Parse::Pidl::Util qw(MyDumper); 12use Parse::Pidl::NDR qw(GetElementLevelTable ParseElement align_type mapToScalar ParseType can_contain_deferred); 13 14# Case 1 15 16my $e = { 17 'FILE' => 'foo.idl', 18 'NAME' => 'v', 19 'PROPERTIES' => {}, 20 'POINTERS' => 0, 21 'TYPE' => 'uint8', 22 'PARENT' => { TYPE => 'STRUCT' }, 23 'LINE' => 42 }; 24 25is_deeply(GetElementLevelTable($e, "unique", 0), [ 26 { 27 'IS_DEFERRED' => 0, 28 'LEVEL_INDEX' => 0, 29 'DATA_TYPE' => 'uint8', 30 'CONTAINS_DEFERRED' => 0, 31 'TYPE' => 'DATA', 32 'IS_SURROUNDING' => 0, 33 } 34]); 35 36my $ne = ParseElement($e, "unique", 0); 37is($ne->{ORIGINAL}, $e); 38is($ne->{NAME}, "v"); 39is($ne->{ALIGN}, 1); 40is($ne->{TYPE}, "uint8"); 41is_deeply($ne->{LEVELS}, [ 42 { 43 'IS_DEFERRED' => 0, 44 'LEVEL_INDEX' => 0, 45 'DATA_TYPE' => 'uint8', 46 'CONTAINS_DEFERRED' => 0, 47 'TYPE' => 'DATA', 48 'IS_SURROUNDING' => 0, 49 } 50]); 51 52# Case 2 : pointers 53# 54$e = { 55 'FILE' => 'foo.idl', 56 'NAME' => 'v', 57 'PROPERTIES' => {"unique" => 1}, 58 'POINTERS' => 1, 59 'PARENT' => { TYPE => 'STRUCT' }, 60 'TYPE' => 'uint8', 61 'LINE' => 42 }; 62 63is_deeply(GetElementLevelTable($e, "unique", 0), [ 64 { 65 LEVEL_INDEX => 0, 66 IS_DEFERRED => 0, 67 TYPE => 'POINTER', 68 POINTER_TYPE => "unique", 69 POINTER_INDEX => 0, 70 LEVEL => 'EMBEDDED' 71 }, 72 { 73 'IS_DEFERRED' => 1, 74 'LEVEL_INDEX' => 1, 75 'DATA_TYPE' => 'uint8', 76 'CONTAINS_DEFERRED' => 0, 77 'TYPE' => 'DATA', 78 'IS_SURROUNDING' => 0, 79 } 80]); 81 82# Case 3 : double pointers 83# 84$e = { 85 'FILE' => 'foo.idl', 86 'NAME' => 'v', 87 'PROPERTIES' => {"unique" => 1}, 88 'POINTERS' => 2, 89 'TYPE' => 'uint8', 90 'PARENT' => { TYPE => 'STRUCT' }, 91 'LINE' => 42 }; 92 93is_deeply(GetElementLevelTable($e, "unique", 0), [ 94 { 95 LEVEL_INDEX => 0, 96 IS_DEFERRED => 0, 97 TYPE => 'POINTER', 98 POINTER_TYPE => "unique", 99 POINTER_INDEX => 0, 100 LEVEL => 'EMBEDDED' 101 }, 102 { 103 LEVEL_INDEX => 1, 104 IS_DEFERRED => 1, 105 TYPE => 'POINTER', 106 POINTER_TYPE => "unique", 107 POINTER_INDEX => 1, 108 LEVEL => 'EMBEDDED' 109 }, 110 { 111 'IS_DEFERRED' => 1, 112 'LEVEL_INDEX' => 2, 113 'DATA_TYPE' => 'uint8', 114 'CONTAINS_DEFERRED' => 0, 115 'TYPE' => 'DATA', 116 'IS_SURROUNDING' => 0, 117 } 118]); 119 120# Case 3 : ref pointers 121# 122$e = { 123 'FILE' => 'foo.idl', 124 'NAME' => 'v', 125 'PROPERTIES' => {"ref" => 1}, 126 'POINTERS' => 1, 127 'TYPE' => 'uint8', 128 'PARENT' => { TYPE => 'STRUCT' }, 129 'LINE' => 42 }; 130 131is_deeply(GetElementLevelTable($e, "unique", 0), [ 132 { 133 LEVEL_INDEX => 0, 134 IS_DEFERRED => 0, 135 TYPE => 'POINTER', 136 POINTER_TYPE => "ref", 137 POINTER_INDEX => 0, 138 LEVEL => 'EMBEDDED' 139 }, 140 { 141 'IS_DEFERRED' => 1, 142 'LEVEL_INDEX' => 1, 143 'DATA_TYPE' => 'uint8', 144 'CONTAINS_DEFERRED' => 0, 145 'TYPE' => 'DATA', 146 'IS_SURROUNDING' => 0, 147 } 148]); 149 150# Case 3 : ref pointers 151# 152$e = { 153 'FILE' => 'foo.idl', 154 'NAME' => 'v', 155 'PROPERTIES' => {"ref" => 1}, 156 'POINTERS' => 3, 157 'TYPE' => 'uint8', 158 'PARENT' => { TYPE => 'STRUCT' }, 159 'LINE' => 42 }; 160 161is_deeply(GetElementLevelTable($e, "unique", 0), [ 162 { 163 LEVEL_INDEX => 0, 164 IS_DEFERRED => 0, 165 TYPE => 'POINTER', 166 POINTER_TYPE => "ref", 167 POINTER_INDEX => 0, 168 LEVEL => 'EMBEDDED' 169 }, 170 { 171 LEVEL_INDEX => 1, 172 IS_DEFERRED => 1, 173 TYPE => 'POINTER', 174 POINTER_TYPE => "unique", 175 POINTER_INDEX => 1, 176 LEVEL => 'EMBEDDED' 177 }, 178 { 179 LEVEL_INDEX => 2, 180 IS_DEFERRED => 1, 181 TYPE => 'POINTER', 182 POINTER_TYPE => "unique", 183 POINTER_INDEX => 2, 184 LEVEL => 'EMBEDDED' 185 }, 186 { 187 'IS_DEFERRED' => 1, 188 'LEVEL_INDEX' => 3, 189 'DATA_TYPE' => 'uint8', 190 'CONTAINS_DEFERRED' => 0, 191 'TYPE' => 'DATA', 192 'IS_SURROUNDING' => 0, 193 } 194]); 195 196# Case 3 : ref pointers 197# 198$e = { 199 'FILE' => 'foo.idl', 200 'NAME' => 'v', 201 'PROPERTIES' => {"ref" => 1}, 202 'POINTERS' => 3, 203 'TYPE' => 'uint8', 204 'PARENT' => { TYPE => 'STRUCT' }, 205 'LINE' => 42 }; 206 207is_deeply(GetElementLevelTable($e, "ref", 0), [ 208 { 209 LEVEL_INDEX => 0, 210 IS_DEFERRED => 0, 211 TYPE => 'POINTER', 212 POINTER_TYPE => "ref", 213 POINTER_INDEX => 0, 214 LEVEL => 'EMBEDDED' 215 }, 216 { 217 LEVEL_INDEX => 1, 218 IS_DEFERRED => 1, 219 TYPE => 'POINTER', 220 POINTER_TYPE => "ref", 221 POINTER_INDEX => 1, 222 LEVEL => 'EMBEDDED' 223 }, 224 { 225 LEVEL_INDEX => 2, 226 IS_DEFERRED => 1, 227 TYPE => 'POINTER', 228 POINTER_TYPE => "ref", 229 POINTER_INDEX => 2, 230 LEVEL => 'EMBEDDED' 231 }, 232 { 233 'IS_DEFERRED' => 1, 234 'LEVEL_INDEX' => 3, 235 'DATA_TYPE' => 'uint8', 236 'CONTAINS_DEFERRED' => 0, 237 'TYPE' => 'DATA', 238 'IS_SURROUNDING' => 0, 239 } 240]); 241 242# Case 4 : top-level ref pointers 243# 244$e = { 245 'FILE' => 'foo.idl', 246 'NAME' => 'v', 247 'PROPERTIES' => {"ref" => 1}, 248 'POINTERS' => 1, 249 'TYPE' => 'uint8', 250 'PARENT' => { TYPE => 'FUNCTION' }, 251 'LINE' => 42 }; 252 253is_deeply(GetElementLevelTable($e, "unique", 0), [ 254 { 255 LEVEL_INDEX => 0, 256 IS_DEFERRED => 0, 257 TYPE => 'POINTER', 258 POINTER_TYPE => "ref", 259 POINTER_INDEX => 0, 260 LEVEL => 'TOP' 261 }, 262 { 263 'IS_DEFERRED' => 0, 264 'LEVEL_INDEX' => 1, 265 'DATA_TYPE' => 'uint8', 266 'CONTAINS_DEFERRED' => 0, 267 'TYPE' => 'DATA', 268 'IS_SURROUNDING' => 0, 269 } 270]); 271 272# Case 4 : top-level ref pointers, triple with pointer_default("unique") 273# 274$e = { 275 'FILE' => 'foo.idl', 276 'NAME' => 'v', 277 'PROPERTIES' => {"ref" => 1}, 278 'POINTERS' => 3, 279 'TYPE' => 'uint8', 280 'PARENT' => { TYPE => 'FUNCTION' }, 281 'LINE' => 42 }; 282 283is_deeply(GetElementLevelTable($e, "unique", 0), [ 284 { 285 LEVEL_INDEX => 0, 286 IS_DEFERRED => 0, 287 TYPE => 'POINTER', 288 POINTER_TYPE => "ref", 289 POINTER_INDEX => 0, 290 LEVEL => 'TOP' 291 }, 292 { 293 LEVEL_INDEX => 1, 294 IS_DEFERRED => 0, 295 TYPE => 'POINTER', 296 POINTER_TYPE => "unique", 297 POINTER_INDEX => 1, 298 LEVEL => 'EMBEDDED' 299 }, 300 { 301 LEVEL_INDEX => 2, 302 IS_DEFERRED => 1, 303 TYPE => 'POINTER', 304 POINTER_TYPE => "unique", 305 POINTER_INDEX => 2, 306 LEVEL => 'EMBEDDED' 307 }, 308 { 309 'IS_DEFERRED' => 1, 310 'LEVEL_INDEX' => 3, 311 'DATA_TYPE' => 'uint8', 312 'CONTAINS_DEFERRED' => 0, 313 'TYPE' => 'DATA', 314 'IS_SURROUNDING' => 0, 315 } 316]); 317 318# Case 4 : top-level unique pointers, triple with pointer_default("unique") 319# 320$e = { 321 'FILE' => 'foo.idl', 322 'NAME' => 'v', 323 'PROPERTIES' => {"unique" => 1, "in" => 1}, 324 'POINTERS' => 3, 325 'TYPE' => 'uint8', 326 'PARENT' => { TYPE => 'FUNCTION' }, 327 'LINE' => 42 }; 328 329is_deeply(GetElementLevelTable($e, "unique", 0), [ 330 { 331 LEVEL_INDEX => 0, 332 IS_DEFERRED => 0, 333 TYPE => 'POINTER', 334 POINTER_TYPE => "unique", 335 POINTER_INDEX => 0, 336 LEVEL => 'TOP' 337 }, 338 { 339 LEVEL_INDEX => 1, 340 IS_DEFERRED => 1, 341 TYPE => 'POINTER', 342 POINTER_TYPE => "unique", 343 POINTER_INDEX => 1, 344 LEVEL => 'EMBEDDED' 345 }, 346 { 347 LEVEL_INDEX => 2, 348 IS_DEFERRED => 1, 349 TYPE => 'POINTER', 350 POINTER_TYPE => "unique", 351 POINTER_INDEX => 2, 352 LEVEL => 'EMBEDDED' 353 }, 354 { 355 'IS_DEFERRED' => 1, 356 'LEVEL_INDEX' => 3, 357 'DATA_TYPE' => 'uint8', 358 'CONTAINS_DEFERRED' => 0, 359 'TYPE' => 'DATA', 360 'IS_SURROUNDING' => 0, 361 } 362]); 363 364# Case 4 : top-level unique pointers, triple with pointer_default("ref") 365# 366$e = { 367 'FILE' => 'foo.idl', 368 'NAME' => 'v', 369 'PROPERTIES' => {"unique" => 1, "in" => 1}, 370 'POINTERS' => 3, 371 'TYPE' => 'uint8', 372 'PARENT' => { TYPE => 'FUNCTION' }, 373 'LINE' => 42 }; 374 375is_deeply(GetElementLevelTable($e, "ref", 0), [ 376 { 377 LEVEL_INDEX => 0, 378 IS_DEFERRED => 0, 379 TYPE => 'POINTER', 380 POINTER_TYPE => "unique", 381 POINTER_INDEX => 0, 382 LEVEL => 'TOP' 383 }, 384 { 385 LEVEL_INDEX => 1, 386 IS_DEFERRED => 1, 387 TYPE => 'POINTER', 388 POINTER_TYPE => "ref", 389 POINTER_INDEX => 1, 390 LEVEL => 'EMBEDDED' 391 }, 392 { 393 LEVEL_INDEX => 2, 394 IS_DEFERRED => 1, 395 TYPE => 'POINTER', 396 POINTER_TYPE => "ref", 397 POINTER_INDEX => 2, 398 LEVEL => 'EMBEDDED' 399 }, 400 { 401 'IS_DEFERRED' => 1, 402 'LEVEL_INDEX' => 3, 403 'DATA_TYPE' => 'uint8', 404 'CONTAINS_DEFERRED' => 0, 405 'TYPE' => 'DATA', 406 'IS_SURROUNDING' => 0, 407 } 408]); 409 410# Case 4 : top-level ref pointers, triple with pointer_default("ref") 411# 412$e = { 413 'FILE' => 'foo.idl', 414 'NAME' => 'v', 415 'PROPERTIES' => {"ref" => 1}, 416 'POINTERS' => 3, 417 'TYPE' => 'uint8', 418 'PARENT' => { TYPE => 'FUNCTION' }, 419 'LINE' => 42 }; 420 421is_deeply(GetElementLevelTable($e, "ref", 0), [ 422 { 423 LEVEL_INDEX => 0, 424 IS_DEFERRED => 0, 425 TYPE => 'POINTER', 426 POINTER_TYPE => "ref", 427 POINTER_INDEX => 0, 428 LEVEL => 'TOP' 429 }, 430 { 431 LEVEL_INDEX => 1, 432 IS_DEFERRED => 0, 433 TYPE => 'POINTER', 434 POINTER_TYPE => "ref", 435 POINTER_INDEX => 1, 436 LEVEL => 'EMBEDDED' 437 }, 438 { 439 LEVEL_INDEX => 2, 440 IS_DEFERRED => 1, 441 TYPE => 'POINTER', 442 POINTER_TYPE => "ref", 443 POINTER_INDEX => 2, 444 LEVEL => 'EMBEDDED' 445 }, 446 { 447 'IS_DEFERRED' => 1, 448 'LEVEL_INDEX' => 3, 449 'DATA_TYPE' => 'uint8', 450 'CONTAINS_DEFERRED' => 0, 451 'TYPE' => 'DATA', 452 'IS_SURROUNDING' => 0, 453 } 454]); 455 456# representation_type 457$e = { 458 'FILE' => 'foo.idl', 459 'NAME' => 'v', 460 'PROPERTIES' => { represent_as => "bar" }, 461 'POINTERS' => 0, 462 'TYPE' => 'uint8', 463 'PARENT' => { TYPE => 'STRUCT' }, 464 'LINE' => 42 }; 465 466$ne = ParseElement($e, undef, 0); 467is($ne->{REPRESENTATION_TYPE}, "bar"); 468 469# representation_type 470$e = { 471 'FILE' => 'foo.idl', 472 'NAME' => 'v', 473 'PROPERTIES' => { }, 474 'POINTERS' => 0, 475 'TYPE' => 'uint8', 476 'PARENT' => { TYPE => 'STRUCT' }, 477 'LINE' => 42 }; 478 479$ne = ParseElement($e, undef, 0); 480is($ne->{REPRESENTATION_TYPE}, "uint8"); 481 482is(align_type("hyper"), 8); 483is(align_type("double"), 8); 484is(align_type("uint32"), 4); 485is(align_type("uint16"), 2); 486is(align_type("uint8"), 1); 487is(align_type({ TYPE => "STRUCT", "NAME" => "bla", 488 ELEMENTS => [ { TYPE => "uint16" } ] }), 4); 489is(align_type({ TYPE => "STRUCT", 490 ELEMENTS => [ { TYPE => "hyper" } ] }), 8); 491is(align_type({ TYPE => "TYPEDEF", DATA => { 492 TYPE => "STRUCT", 493 ELEMENTS => [ { TYPE => "hyper" } ] }}), 8); 494# typedef of struct without body 495is(align_type({ TYPE => "TYPEDEF", DATA => { 496 TYPE => "STRUCT", ELEMENTS => undef }}), 4); 497# struct without body 498is(align_type({ TYPE => "STRUCT", ELEMENTS => undef }), 4); 499# empty struct 500is(align_type({ TYPE => "STRUCT", ELEMENTS => [] }), 1); 501is(align_type({ TYPE => "STRUCT", "NAME" => "bla", 502 ELEMENTS => [ { TYPE => "uint8" } ] }), 4); 503 504is(mapToScalar("someverymuchnotexistingtype"), undef); 505is(mapToScalar("uint32"), "uint32"); 506is(mapToScalar({TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }), "uint8"); 507is(mapToScalar({TYPE => "BITMAP", PROPERTIES => { bitmap64bit => 1 } }), 508 "hyper"); 509is(mapToScalar({TYPE => "TYPEDEF", DATA => {TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }}), "uint8"); 510 511my $t; 512$t = { 513 TYPE => "STRUCT", 514 NAME => "foo", 515 SURROUNDING_ELEMENT => undef, 516 ELEMENTS => undef, 517 PROPERTIES => undef, 518 ORIGINAL => { 519 TYPE => "STRUCT", 520 NAME => "foo" 521 }, 522 ALIGN => undef 523}; 524is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t); 525 526$t = { 527 TYPE => "UNION", 528 NAME => "foo", 529 SWITCH_TYPE => "uint32", 530 ELEMENTS => undef, 531 PROPERTIES => undef, 532 HAS_DEFAULT => 0, 533 IS_MS_UNION => 0, 534 ORIGINAL => { 535 TYPE => "UNION", 536 NAME => "foo" 537 }, 538 ALIGN => undef 539}; 540is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t); 541 542ok(not can_contain_deferred("uint32")); 543ok(can_contain_deferred("some_unknown_type")); 544ok(can_contain_deferred({ TYPE => "STRUCT", 545 ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]})); 546ok(can_contain_deferred({ TYPE => "TYPEDEF", 547 DATA => { TYPE => "STRUCT", 548 ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}})); 549ok(not can_contain_deferred({ TYPE => "STRUCT", 550 ELEMENTS => [ { TYPE => "uint32" } ]})); 551ok(not can_contain_deferred({ TYPE => "TYPEDEF", 552 DATA => { TYPE => "STRUCT", 553 ELEMENTS => [ { TYPE => "uint32" } ]}})); 554ok(can_contain_deferred({ TYPE => "STRUCT", 555 ELEMENTS => [ { TYPE => "someunknowntype" } ]})); 556# Make sure the elements for a enum without body aren't filled in 557ok(not defined(ParseType({TYPE => "ENUM", NAME => "foo" }, "ref", 0)->{ELEMENTS})); 558# Make sure the elements for a bitmap without body aren't filled in 559ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref", 0)->{ELEMENTS})); 560# Make sure the elements for a union without body aren't filled in 561ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref", 0)->{ELEMENTS})); 562