2 # (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3 # Published under the GNU General Public License
7 use Test
::More tests
=> 30;
8 use FindBin
qw($RealBin);
11 use Parse::Pidl::Util qw(MyDumper);
12 use Parse
::Pidl
::Samba4
::Header
qw(
13 GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
15 use Parse
::Pidl
::IDL
qw(parse_string);
21 my $idl = Parse
::Pidl
::IDL
::parse_string
($text, "nofile");
22 my $ndr = Parse
::Pidl
::NDR
::Parse
($idl);
23 return Parse
::Pidl
::Samba4
::Header
::Parse
($ndr);
26 sub load_and_parse_idl
($)
30 my $idl = Parse
::Pidl
::IDL
::parse_string
($text, "nofile");
31 Parse
::Pidl
::Typelist
::LoadIdl
($idl, "noname");
32 $ndr = Parse
::Pidl
::NDR
::Parse
($idl);
33 return Parse
::Pidl
::Samba4
::Header
::Parse
($ndr);
36 like
(parse_idl
(""), qr/\/\
* header auto
-generated by pidl \
*\
/\n/sm, "includes work");
37 like
(parse_idl
("interface x {}"), qr/\/\
* header auto
-generated by pidl \
*\
/\n/sm, "simple empty interface doesn't cause overhead");
38 like
(parse_idl
("interface p { typedef struct { int y; } x; };"),
39 qr/.*#ifndef _HEADER_p\n#define _HEADER_p\n.+\n#endif \/\
* _HEADER_p \
*\
/.*/ms, "ifdefs are created");
40 like
(parse_idl
("interface p { typedef struct { int y; } x; };"),
41 qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
42 like
(parse_idl
("interface x { void foo (void); };"),
43 qr/struct foo.*{\s+int _dummy_element;\s+};/sm, "void fn contains dummy element");
44 like
(parse_idl
("interface x { void foo ([in] uint32 x); };"),
45 qr/struct foo.*{\s+struct\s+{\s+uint32_t x;\s+} in;\s+};/sm, "fn in arg works");
46 like
(parse_idl
("interface x { void foo ([out] uint32 x); };"),
47 qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn out arg works");
48 like
(parse_idl
("interface x { void foo ([in,out] uint32 x); };"),
49 qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} in;\s+struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn in,out arg works");
50 like
(parse_idl
("interface x { void foo (uint32 x); };"), qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} in;\s+struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn with no props implies in,out");
51 like
(parse_idl
("interface p { struct x { int y; }; };"),
52 qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
54 like
(parse_idl
("interface p { struct x { struct y z; }; };"),
55 qr/struct x.*{.*struct y z;.*}.*;/sm, "tagged type struct member");
57 like
(parse_idl
("interface p { struct x { union y z; }; };"),
58 qr/struct x.*{.*union y z;.*}.*;/sm, "tagged type union member");
60 like
(parse_idl
("interface p { struct x { }; };"),
61 qr/struct x.*{.*char _empty_;.*}.*;/sm, "empty struct");
63 like
(parse_idl
("interface p { struct x; };"),
64 qr/struct x;/sm, "struct declaration");
66 like
(parse_idl
("interface p { typedef struct x { int p; } x; };"),
67 qr/struct x.*{.*int32_t p;.*};/sm, "double struct declaration");
69 like
(parse_idl
("cpp_quote(\"some-foo\")"),
70 qr/some-foo/sm, "cpp quote");
72 like
(load_and_parse_idl
("interface hang {typedef [public] struct { wsp_cbasestoragevariant a[SINGLE]; } foo; typedef [public,nodiscriminant,switch_type(uint16)] union { [case(VT_I1)] int8 vt_i1; [case(VT_VARIANT)] foo b; } variant_types; typedef [public] struct { [switch_is(vtype)] variant_types vvalue; } bar;};"),
73 qr/struct foo.*{.*struct wsp_cbasestoragevariant \*a.*struct bar \{.*union variant_types vvalue.*;/sm,"test for hang with nested struct with union");
75 like
(load_and_parse_idl
("interface hang { typedef struct { uint32 count; bar a[count];} foo ; typedef struct { foo b; } bar; };"),
76 qr/struct foo.*{.*struct bar \*a;/sm,"test for hang with nested struct");
78 like
(load_and_parse_idl
("interface hang { typedef struct { bar a; } foo ; typedef struct { foo b; } bar; };"),
79 qr/struct foo.*{.*struct bar a;/sm,"test for hang with uncompilable nested struct");
81 # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
82 my $fn = { ELEMENTS
=> [ { DIRECTION
=> ["in"], NAME
=> "foo" } ] };
83 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionInEnv
($fn));
85 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out"], NAME
=> "foo" } ] };
86 is_deeply
({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv
($fn));
88 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out", "in"], NAME
=> "foo" } ] };
89 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionInEnv
($fn));
91 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out", "in"], NAME
=> "foo" } ] };
92 is_deeply
({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv
($fn));
94 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["in"], NAME
=> "foo" } ] };
95 is_deeply
({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv
($fn));
97 $fn = { ELEMENTS
=> [ { DIRECTION
=> ["out"], NAME
=> "foo" } ] };
98 is_deeply
({ }, GenerateFunctionInEnv
($fn));
100 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
101 is_deeply
({ foo
=> "r->foo", bar
=> "r->bar", this
=> "r" },
102 GenerateStructEnv
($fn, "r"));
104 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
105 is_deeply
({ foo
=> "some->complex.variable->foo",
106 bar
=> "some->complex.variable->bar",
107 this
=> "some->complex.variable" },
108 GenerateStructEnv
($fn, "some->complex.variable"));
110 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 3 }} ] };
112 my $env = GenerateStructEnv
($fn, "r");
113 EnvSubstituteValue
($env, $fn);
114 is_deeply
($env, { foo
=> 3, this
=> "r" });
116 $fn = { ELEMENTS
=> [ { NAME
=> "foo" }, { NAME
=> "bar" } ] };
117 $env = GenerateStructEnv
($fn, "r");
118 EnvSubstituteValue
($env, $fn);
119 is_deeply
($env, { foo
=> 'r->foo', bar
=> 'r->bar', this
=> "r" });
121 $fn = { ELEMENTS
=> [ { NAME
=> "foo", PROPERTIES
=> { value
=> 0 }} ] };
123 $env = GenerateStructEnv
($fn, "r");
124 EnvSubstituteValue
($env, $fn);
125 is_deeply
($env, { foo
=> 0, this
=> "r" });