Move pidl to top-level directory.
[ira/wip.git] / pidl / tests / ndr.pl
diff --git a/pidl/tests/ndr.pl b/pidl/tests/ndr.pl
new file mode 100755 (executable)
index 0000000..504b7ec
--- /dev/null
@@ -0,0 +1,558 @@
+#!/usr/bin/perl
+# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
+# Published under the GNU General Public License
+use strict;
+use warnings;
+
+use Test::More tests => 46;
+use FindBin qw($RealBin);
+use lib "$RealBin";
+use Util;
+use Parse::Pidl::Util qw(MyDumper);
+use Parse::Pidl::NDR qw(GetElementLevelTable ParseElement align_type mapToScalar ParseType can_contain_deferred);
+
+# Case 1
+
+my $e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {},
+       'POINTERS' => 0,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               'IS_DEFERRED' => 0,
+               'LEVEL_INDEX' => 0,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+my $ne = ParseElement($e, "unique");
+is($ne->{ORIGINAL}, $e);
+is($ne->{NAME}, "v");
+is($ne->{ALIGN}, 1);
+is($ne->{TYPE}, "uint8");
+is_deeply($ne->{LEVELS},  [
+       {
+               'IS_DEFERRED' => 0,
+               'LEVEL_INDEX' => 0,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 2 : pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"unique" => 1},
+       'POINTERS' => 1,
+       'PARENT' => { TYPE => 'STRUCT' },
+       'TYPE' => 'uint8',
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 0,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 1,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 3 : double pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"unique" => 1},
+       'POINTERS' => 2,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 0,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 2,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 3 : ref pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 1,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 1,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 3 : ref pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 3 : ref pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "ref"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level ref pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 1,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               'IS_DEFERRED' => 0,
+               'LEVEL_INDEX' => 1,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level ref pointers, triple with pointer_default("unique")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level unique pointers, triple with pointer_default("unique")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"unique" => 1, "in" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level unique pointers, triple with pointer_default("ref")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"unique" => 1, "in" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "ref"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level ref pointers, triple with pointer_default("ref")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "ref"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# representation_type
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => { represent_as => "bar" },
+       'POINTERS' => 0,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+$ne = ParseElement($e, undef);
+is($ne->{REPRESENTATION_TYPE}, "bar");
+
+# representation_type
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => { },
+       'POINTERS' => 0,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+$ne = ParseElement($e, undef);
+is($ne->{REPRESENTATION_TYPE}, "uint8");
+
+is(align_type("hyper"), 8);
+is(align_type("uint32"), 4);
+is(align_type("uint16"), 2);
+is(align_type("uint8"), 1);
+is(align_type({ TYPE => "STRUCT", "NAME" => "bla", 
+                           ELEMENTS => [ { TYPE => "uint16" } ] }), 4);
+is(align_type({ TYPE => "STRUCT", 
+                           ELEMENTS => [ { TYPE => "hyper" } ] }), 8);
+is(align_type({ TYPE => "TYPEDEF", DATA => { 
+                               TYPE => "STRUCT", 
+                           ELEMENTS => [ { TYPE => "hyper" } ] }}), 8);
+# typedef of struct without body
+is(align_type({ TYPE => "TYPEDEF", DATA => { 
+                               TYPE => "STRUCT", ELEMENTS => undef }}), 4);
+# struct without body
+is(align_type({ TYPE => "STRUCT", ELEMENTS => undef }), 4);
+# empty struct
+is(align_type({ TYPE => "STRUCT", ELEMENTS => [] }), 1);
+is(align_type({ TYPE => "STRUCT", "NAME" => "bla", 
+                           ELEMENTS => [ { TYPE => "uint8" } ] }), 4);
+
+is(mapToScalar("someverymuchnotexistingtype"), undef);
+is(mapToScalar("uint32"), "uint32");
+is(mapToScalar({TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }), "uint8");
+is(mapToScalar({TYPE => "BITMAP", PROPERTIES => { bitmap64bit => 1 } }),
+       "hyper");
+is(mapToScalar({TYPE => "TYPEDEF", DATA => {TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }}), "uint8");
+
+my $t;
+$t = {
+       TYPE => "STRUCT",
+       NAME => "foo",
+       SURROUNDING_ELEMENT => undef,
+       ELEMENTS => undef,
+       PROPERTIES => undef,
+       ORIGINAL => {
+               TYPE => "STRUCT",
+               NAME => "foo"
+       },
+       ALIGN => undef
+};
+is_deeply(ParseType($t->{ORIGINAL}, "ref"), $t); 
+
+$t = {
+       TYPE => "UNION",
+       NAME => "foo",
+       SWITCH_TYPE => "uint32",
+       ELEMENTS => undef,
+       PROPERTIES => undef,
+       HAS_DEFAULT => 0,
+       ORIGINAL => {
+               TYPE => "UNION",
+               NAME => "foo"
+       }
+};
+is_deeply(ParseType($t->{ORIGINAL}, "ref"), $t); 
+
+ok(not can_contain_deferred("uint32"));
+ok(can_contain_deferred("some_unknown_type"));
+ok(can_contain_deferred({ TYPE => "STRUCT", 
+               ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}));
+ok(can_contain_deferred({ TYPE => "TYPEDEF", 
+                       DATA => { TYPE => "STRUCT", 
+               ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}}));
+ok(not can_contain_deferred({ TYPE => "STRUCT", 
+               ELEMENTS => [ { TYPE => "uint32" } ]}));
+ok(not can_contain_deferred({ TYPE => "TYPEDEF",
+                       DATA => { TYPE => "STRUCT", 
+               ELEMENTS => [ { TYPE => "uint32" } ]}}));
+ok(can_contain_deferred({ TYPE => "STRUCT", 
+               ELEMENTS => [ { TYPE => "someunknowntype" } ]}));
+# Make sure the elements for a enum without body aren't filled in
+ok(not defined(ParseType({TYPE => "ENUM", NAME => "foo" }, "ref")->{ELEMENTS}));
+# Make sure the elements for a bitmap without body aren't filled in
+ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref")->{ELEMENTS}));
+# Make sure the elements for a union without body aren't filled in
+ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref")->{ELEMENTS}));