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 => 27;
8use FindBin qw($RealBin);
9use lib "$RealBin";
10use Util;
11use Parse::Pidl::Util qw(MyDumper);
12use Parse::Pidl::Samba4::Header qw(
13	GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
14	EnvSubstituteValue);
15use Parse::Pidl::IDL qw(parse_string);
16use Parse::Pidl::NDR;
17
18sub parse_idl($)
19{
20	my $text = shift;
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);
24}
25
26like(parse_idl(""), qr/\/\* header auto-generated by pidl \*\/\n/sm, "includes work");
27like(parse_idl("interface x {}"), qr/\/\* header auto-generated by pidl \*\/\n/sm,  "simple empty interface doesn't cause overhead");
28like(parse_idl("interface p { typedef struct { int y; } x; };"),
29     qr/.*#ifndef _HEADER_p\n#define _HEADER_p\n.+\n#endif \/\* _HEADER_p \*\/.*/ms, "ifdefs are created");
30like(parse_idl("interface p { typedef struct { int y; } x; };"),
31     qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
32like(parse_idl("interface x { void foo (void); };"),
33     qr/struct foo.*{\s+int _dummy_element;\s+};/sm, "void fn contains dummy element");
34like(parse_idl("interface x { void foo ([in] uint32 x); };"),
35     qr/struct foo.*{\s+struct\s+{\s+uint32_t x;\s+} in;\s+};/sm, "fn in arg works");
36like(parse_idl("interface x { void foo ([out] uint32 x); };"),
37     qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn out arg works");
38like(parse_idl("interface x { void foo ([in,out] uint32 x); };"),
39     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");
40like(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");
41like(parse_idl("interface p { struct x { int y; }; };"),
42     qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
43
44like(parse_idl("interface p { struct x { struct y z; }; };"),
45     qr/struct x.*{.*struct y z;.*}.*;/sm, "tagged type struct member");
46
47like(parse_idl("interface p { struct x { union y z; }; };"),
48     qr/struct x.*{.*union y z;.*}.*;/sm, "tagged type union member");
49
50like(parse_idl("interface p { struct x { }; };"),
51     qr/struct x.*{.*char _empty_;.*}.*;/sm, "empty struct");
52
53like(parse_idl("interface p { struct x; };"),
54     qr/struct x;/sm, "struct declaration");
55
56like(parse_idl("interface p { typedef struct x { int p; } x; };"),
57     qr/struct x.*{.*int32_t p;.*};/sm, "double struct declaration");
58
59like(parse_idl("cpp_quote(\"some-foo\")"),
60	qr/some-foo/sm, "cpp quote");
61
62# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
63my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
64is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
65
66$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
67is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
68
69$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
70is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
71
72$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
73is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
74
75$fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
76is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv($fn));
77
78$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
79is_deeply({ }, GenerateFunctionInEnv($fn));
80
81$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
82is_deeply({ foo => "r->foo", bar => "r->bar", this => "r" },
83		GenerateStructEnv($fn, "r"));
84
85$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
86is_deeply({ foo => "some->complex.variable->foo",
87		    bar => "some->complex.variable->bar",
88			this => "some->complex.variable" },
89		GenerateStructEnv($fn, "some->complex.variable"));
90
91$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 3 }} ] };
92
93my $env = GenerateStructEnv($fn, "r");
94EnvSubstituteValue($env, $fn);
95is_deeply($env, { foo => 3, this => "r" });
96
97$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
98$env = GenerateStructEnv($fn, "r");
99EnvSubstituteValue($env, $fn);
100is_deeply($env, { foo => 'r->foo', bar => 'r->bar', this => "r" });
101
102$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 0 }} ] };
103
104$env = GenerateStructEnv($fn, "r");
105EnvSubstituteValue($env, $fn);
106is_deeply($env, { foo => 0, this => "r" });
107
108
109