Merge branch 'master' of ssh://git.samba.org/data/git/samba into regsrv
[kai/samba.git] / pidl / tests / ndr.pl
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 => 46;
8 use FindBin qw($RealBin);
9 use lib "$RealBin";
10 use Util;
11 use Parse::Pidl::Util qw(MyDumper);
12 use Parse::Pidl::NDR qw(GetElementLevelTable ParseElement align_type mapToScalar ParseType can_contain_deferred);
13
14 # Case 1
15
16 my $e = {
17         'FILE' => 'foo.idl',
18         'NAME' => 'v',
19         'PROPERTIES' => {},
20         'POINTERS' => 0,
21         'TYPE' => 'uint8',
22         'PARENT' => { TYPE => 'STRUCT' },
23         'LINE' => 42 };
24
25 is_deeply(GetElementLevelTable($e, "unique"), [
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
36 my $ne = ParseElement($e, "unique");
37 is($ne->{ORIGINAL}, $e);
38 is($ne->{NAME}, "v");
39 is($ne->{ALIGN}, 1);
40 is($ne->{TYPE}, "uint8");
41 is_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
63 is_deeply(GetElementLevelTable($e, "unique"), [
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
93 is_deeply(GetElementLevelTable($e, "unique"), [
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
131 is_deeply(GetElementLevelTable($e, "unique"), [
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
161 is_deeply(GetElementLevelTable($e, "unique"), [
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
207 is_deeply(GetElementLevelTable($e, "ref"), [
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
253 is_deeply(GetElementLevelTable($e, "unique"), [
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
283 is_deeply(GetElementLevelTable($e, "unique"), [
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
329 is_deeply(GetElementLevelTable($e, "unique"), [
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
375 is_deeply(GetElementLevelTable($e, "ref"), [
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
421 is_deeply(GetElementLevelTable($e, "ref"), [
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);
467 is($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);
480 is($ne->{REPRESENTATION_TYPE}, "uint8");
481
482 is(align_type("hyper"), 8);
483 is(align_type("uint32"), 4);
484 is(align_type("uint16"), 2);
485 is(align_type("uint8"), 1);
486 is(align_type({ TYPE => "STRUCT", "NAME" => "bla", 
487                             ELEMENTS => [ { TYPE => "uint16" } ] }), 4);
488 is(align_type({ TYPE => "STRUCT", 
489                             ELEMENTS => [ { TYPE => "hyper" } ] }), 8);
490 is(align_type({ TYPE => "TYPEDEF", DATA => { 
491                                 TYPE => "STRUCT", 
492                             ELEMENTS => [ { TYPE => "hyper" } ] }}), 8);
493 # typedef of struct without body
494 is(align_type({ TYPE => "TYPEDEF", DATA => { 
495                                 TYPE => "STRUCT", ELEMENTS => undef }}), 4);
496 # struct without body
497 is(align_type({ TYPE => "STRUCT", ELEMENTS => undef }), 4);
498 # empty struct
499 is(align_type({ TYPE => "STRUCT", ELEMENTS => [] }), 1);
500 is(align_type({ TYPE => "STRUCT", "NAME" => "bla", 
501                             ELEMENTS => [ { TYPE => "uint8" } ] }), 4);
502
503 is(mapToScalar("someverymuchnotexistingtype"), undef);
504 is(mapToScalar("uint32"), "uint32");
505 is(mapToScalar({TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }), "uint8");
506 is(mapToScalar({TYPE => "BITMAP", PROPERTIES => { bitmap64bit => 1 } }),
507         "hyper");
508 is(mapToScalar({TYPE => "TYPEDEF", DATA => {TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }}), "uint8");
509
510 my $t;
511 $t = {
512         TYPE => "STRUCT",
513         NAME => "foo",
514         SURROUNDING_ELEMENT => undef,
515         ELEMENTS => undef,
516         PROPERTIES => undef,
517         ORIGINAL => {
518                 TYPE => "STRUCT",
519                 NAME => "foo"
520         },
521         ALIGN => undef
522 };
523 is_deeply(ParseType($t->{ORIGINAL}, "ref"), $t); 
524
525 $t = {
526         TYPE => "UNION",
527         NAME => "foo",
528         SWITCH_TYPE => "uint32",
529         ELEMENTS => undef,
530         PROPERTIES => undef,
531         HAS_DEFAULT => 0,
532         ORIGINAL => {
533                 TYPE => "UNION",
534                 NAME => "foo"
535         }
536 };
537 is_deeply(ParseType($t->{ORIGINAL}, "ref"), $t); 
538
539 ok(not can_contain_deferred("uint32"));
540 ok(can_contain_deferred("some_unknown_type"));
541 ok(can_contain_deferred({ TYPE => "STRUCT", 
542                 ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}));
543 ok(can_contain_deferred({ TYPE => "TYPEDEF", 
544                         DATA => { TYPE => "STRUCT", 
545                 ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}}));
546 ok(not can_contain_deferred({ TYPE => "STRUCT", 
547                 ELEMENTS => [ { TYPE => "uint32" } ]}));
548 ok(not can_contain_deferred({ TYPE => "TYPEDEF",
549                         DATA => { TYPE => "STRUCT", 
550                 ELEMENTS => [ { TYPE => "uint32" } ]}}));
551 ok(can_contain_deferred({ TYPE => "STRUCT", 
552                 ELEMENTS => [ { TYPE => "someunknowntype" } ]}));
553 # Make sure the elements for a enum without body aren't filled in
554 ok(not defined(ParseType({TYPE => "ENUM", NAME => "foo" }, "ref")->{ELEMENTS}));
555 # Make sure the elements for a bitmap without body aren't filled in
556 ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref")->{ELEMENTS}));
557 # Make sure the elements for a union without body aren't filled in
558 ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref")->{ELEMENTS}));