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