Refactor build system to use waf. Waf is better at handling dependency paths which I need for IDL support

This commit is contained in:
Wilco Baan Hofman 2012-08-04 22:18:52 +02:00
parent df7f98bc6f
commit 9fd10dec9c
77 changed files with 312 additions and 86 deletions

181
bin/pidl/tests/Util.pm Normal file
View file

@ -0,0 +1,181 @@
# Some simple utility functions for pidl tests
# Copyright (C) 2005-2006 Jelmer Vernooij
# Published under the GNU General Public License
package Util;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(test_samba4_ndr test_warnings test_errors);
use strict;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Parse::Pidl::Samba4 qw(is_intree);
use Parse::Pidl;
my $warnings = "";
undef &Parse::Pidl::warning;
*Parse::Pidl::warning = sub {
my ($e, $l) = @_;
if (defined($e)) {
$warnings .= "$e->{FILE}:$e->{LINE}: $l\n";
} else {
$warnings .= "$l\n";
}
};
my $errors = "";
undef &Parse::Pidl::error;
*Parse::Pidl::error = sub {
my ($e, $l) = @_;
if (defined($e)) {
$errors .= "$e->{FILE}:$e->{LINE}: $l\n";
} else {
$errors .= "$l\n";
}
};
use Test::More;
use Parse::Pidl::IDL;
use Parse::Pidl::NDR;
use Parse::Pidl::Samba4::NDR::Parser;
use Parse::Pidl::Samba4::Header;
# Generate a Samba4 parser for an IDL fragment and run it with a specified
# piece of code to check whether the parser works as expected
sub test_samba4_ndr
{
my ($name,$idl,$c,$extra) = @_;
$extra = "" unless defined($extra);
my $pidl = Parse::Pidl::IDL::parse_string("interface echo { $idl }; ", "<$name>");
ok(defined($pidl), "($name) parse idl");
my $pndr = Parse::Pidl::NDR::Parse($pidl);
ok(defined($pndr), "($name) generate NDR tree");
my $header = Parse::Pidl::Samba4::Header::Parse($pndr);
ok(defined($header), "($name) generate generic header");
my $generator = new Parse::Pidl::Samba4::NDR::Parser();
my ($ndrheader,$ndrparser) = $generator->Parse($pndr, undef, undef);
ok(defined($ndrparser), "($name) generate NDR parser");
ok(defined($ndrheader), "($name) generate NDR header");
SKIP: {
my $flags;
if (system("pkg-config --exists ndr") == 0 and !is_intree()) {
$flags = `pkg-config --libs --cflags ndr`;
} else {
skip "no samba environment available, skipping compilation", 3;
}
my $main = "
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <util/data_blob.h>
/* header start */
$header
/* header end */
/* ndrheader start */
$ndrheader
/* ndrheader end */
/* extra start */
$extra
/* extra end */
/* ndrparser start */
$ndrparser
/* ndrparser end */
/* main start */
int main(int argc, const char **argv)
{
TALLOC_CTX *mem_ctx = talloc_init(NULL);
$c
talloc_free(mem_ctx);
return 0;
}
/* main end */
\n";
my $main_debug = "# ".join("\n# ", split("\n", $main));
my $test_data_prefix = $ENV{TEST_DATA_PREFIX};
my $outfile;
if (defined($test_data_prefix)) {
$outfile = "$test_data_prefix/test-$name";
} else {
$outfile = "./test-$name";
}
my $cflags = $ENV{CFLAGS};
unless (defined($cflags)) {
$cflags = "";
}
my $ldflags = $ENV{LDFLAGS};
unless (defined($ldflags)) {
$ldflags = "";
}
my $cc = $ENV{CC};
unless (defined($cc)) {
$cc = "cc";
}
my $cmd = "$cc $cflags -x c - -o $outfile $flags $ldflags";
$cmd =~ s/\n//g;
open CC, "|$cmd";
print CC $main;
close CC;
ok(-f $outfile, "($name) compile");
my $ret = system($outfile, ()) >> 8;
print "# code:\n#\n$main_debug\n" if ($ret != 0);
print "# cmd: $cmd\n" if ($ret != 0);
print "# return code: $ret\n" if ($ret != 0);
ok($ret == 0, "($name) run");
ok(unlink($outfile), "($name) remove");
}
}
sub test_warnings($$)
{
my ($exp, $code) = @_;
$warnings = "";
$code->();
is($warnings, $exp);
}
sub test_errors($$)
{
my ($exp, $code) = @_;
$errors = "";
$code->();
is($errors, $exp);
}
1;

21
bin/pidl/tests/cutil.pl Executable file
View file

@ -0,0 +1,21 @@
#!/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 => 7;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper);
use Parse::Pidl::CUtil qw(get_pointer_to get_value_of);
is("&foo", get_pointer_to("foo"));
is("&(&foo)", get_pointer_to(get_pointer_to("foo")));
is("*foo", get_pointer_to("**foo"));
is("foo", get_pointer_to("*foo"));
is("foo", get_value_of("&foo"));
is("*foo", get_value_of("foo"));
is("**foo", get_value_of("*foo"));

15
bin/pidl/tests/dump.pl Executable file
View file

@ -0,0 +1,15 @@
#!/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 => 1;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Dump qw(DumpStruct);
is (DumpStruct({ NAME => "foo", ELEMENTS => []}),
"struct foo {\n}");

108
bin/pidl/tests/header.pl Executable file
View file

@ -0,0 +1,108 @@
#!/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 => 27;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper);
use Parse::Pidl::Samba4::Header qw(
GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
EnvSubstituteValue);
use Parse::Pidl::IDL qw(parse_string);
use Parse::Pidl::NDR;
sub parse_idl($)
{
my $text = shift;
my $idl = Parse::Pidl::IDL::parse_string($text, "nofile");
my $ndr = Parse::Pidl::NDR::Parse($idl);
return Parse::Pidl::Samba4::Header::Parse($ndr);
}
like(parse_idl(""), qr/\/\* header auto-generated by pidl \*\/\n/sm, "includes work");
like(parse_idl("interface x {}"), qr/\/\* header auto-generated by pidl \*\/\n/sm, "simple empty interface doesn't cause overhead");
like(parse_idl("interface p { typedef struct { int y; } x; };"),
qr/.*#ifndef _HEADER_p\n#define _HEADER_p\n.+\n#endif \/\* _HEADER_p \*\/.*/ms, "ifdefs are created");
like(parse_idl("interface p { typedef struct { int y; } x; };"),
qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
like(parse_idl("interface x { void foo (void); };"),
qr/struct foo.*{\s+int _dummy_element;\s+};/sm, "void fn contains dummy element");
like(parse_idl("interface x { void foo ([in] uint32 x); };"),
qr/struct foo.*{\s+struct\s+{\s+uint32_t x;\s+} in;\s+};/sm, "fn in arg works");
like(parse_idl("interface x { void foo ([out] uint32 x); };"),
qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn out arg works");
like(parse_idl("interface x { void foo ([in,out] uint32 x); };"),
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");
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");
like(parse_idl("interface p { struct x { int y; }; };"),
qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
like(parse_idl("interface p { struct x { struct y z; }; };"),
qr/struct x.*{.*struct y z;.*}.*;/sm, "tagged type struct member");
like(parse_idl("interface p { struct x { union y z; }; };"),
qr/struct x.*{.*union y z;.*}.*;/sm, "tagged type union member");
like(parse_idl("interface p { struct x { }; };"),
qr/struct x.*{.*char _empty_;.*}.*;/sm, "empty struct");
like(parse_idl("interface p { struct x; };"),
qr/struct x;/sm, "struct declaration");
like(parse_idl("interface p { typedef struct x { int p; } x; };"),
qr/struct x.*{.*int32_t p;.*};/sm, "double struct declaration");
like(parse_idl("cpp_quote(\"some-foo\")"),
qr/some-foo/sm, "cpp quote");
# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
$fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv($fn));
$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
is_deeply({ }, GenerateFunctionInEnv($fn));
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
is_deeply({ foo => "r->foo", bar => "r->bar", this => "r" },
GenerateStructEnv($fn, "r"));
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
is_deeply({ foo => "some->complex.variable->foo",
bar => "some->complex.variable->bar",
this => "some->complex.variable" },
GenerateStructEnv($fn, "some->complex.variable"));
$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 3 }} ] };
my $env = GenerateStructEnv($fn, "r");
EnvSubstituteValue($env, $fn);
is_deeply($env, { foo => 3, this => "r" });
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
$env = GenerateStructEnv($fn, "r");
EnvSubstituteValue($env, $fn);
is_deeply($env, { foo => 'r->foo', bar => 'r->bar', this => "r" });
$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 0 }} ] };
$env = GenerateStructEnv($fn, "r");
EnvSubstituteValue($env, $fn);
is_deeply($env, { foo => 0, this => "r" });

561
bin/pidl/tests/ndr.pl Executable file
View file

@ -0,0 +1,561 @@
#!/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 => 47;
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", 0), [
{
'IS_DEFERRED' => 0,
'LEVEL_INDEX' => 0,
'DATA_TYPE' => 'uint8',
'CONTAINS_DEFERRED' => 0,
'TYPE' => 'DATA',
'IS_SURROUNDING' => 0,
}
]);
my $ne = ParseElement($e, "unique", 0);
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", 0), [
{
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", 0), [
{
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", 0), [
{
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", 0), [
{
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", 0), [
{
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", 0), [
{
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", 0), [
{
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", 0), [
{
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", 0), [
{
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", 0), [
{
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, 0);
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, 0);
is($ne->{REPRESENTATION_TYPE}, "uint8");
is(align_type("hyper"), 8);
is(align_type("double"), 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", 0), $t);
$t = {
TYPE => "UNION",
NAME => "foo",
SWITCH_TYPE => "uint32",
ELEMENTS => undef,
PROPERTIES => undef,
HAS_DEFAULT => 0,
IS_MS_UNION => 0,
ORIGINAL => {
TYPE => "UNION",
NAME => "foo"
},
ALIGN => undef
};
is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $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", 0)->{ELEMENTS}));
# Make sure the elements for a bitmap without body aren't filled in
ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref", 0)->{ELEMENTS}));
# Make sure the elements for a union without body aren't filled in
ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref", 0)->{ELEMENTS}));

143
bin/pidl/tests/ndr_align.pl Executable file
View file

@ -0,0 +1,143 @@
#!/usr/bin/perl
# NDR alignment tests
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
use strict;
use Test::More tests => 5 * 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
test_samba4_ndr('align-uint8-uint16',
'
typedef [public] struct {
uint8 x;
uint16 y;
} bla;
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct bla r;
uint8_t expected[] = { 0x0D, 0x00, 0xef, 0xbe };
DATA_BLOB expected_blob = { expected, 4 };
DATA_BLOB result_blob;
r.x = 13;
r.y = 0xbeef;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');
test_samba4_ndr('align-uint8-uint32',
'
typedef [public] struct {
uint8 x;
uint32 y;
} bla;
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct bla r;
uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xef, 0xbe };
DATA_BLOB expected_blob = { expected, 8 };
DATA_BLOB result_blob;
r.x = 13;
r.y = 0xbeefbeef;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');
test_samba4_ndr('align-uint8-hyper',
'
typedef [public] struct {
uint8 x;
hyper y;
} bla;
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct bla r;
uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe };
DATA_BLOB expected_blob = { expected, 16 };
DATA_BLOB result_blob;
r.x = 13;
r.y = 0xbeefbeefbeefbeefLLU;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');
test_samba4_ndr('noalignflag-uint8-uint16',
'
typedef [public] struct {
uint8 x;
uint16 y;
} bla;
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct bla r;
uint8_t expected[] = { 0x0D, 0xef, 0xbe };
DATA_BLOB expected_blob = { expected, 3 };
DATA_BLOB result_blob;
ndr->flags |= LIBNDR_FLAG_NOALIGN;
r.x = 13;
r.y = 0xbeef;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');
test_samba4_ndr('align-blob-align2',
'
typedef [public] struct {
uint8 x;
[flag(LIBNDR_FLAG_ALIGN2)] DATA_BLOB data;
uint8 y;
} blie;
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct blie r;
uint8_t data[] = { 0x01, 0x02 };
uint8_t expected[] = { 0x0D, 0x00, 0x0E };
DATA_BLOB expected_blob = { expected, 3 };
DATA_BLOB result_blob;
r.x = 13;
r.y = 14;
r.data.data = data;
r.data.length = 2;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_blie(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');

118
bin/pidl/tests/ndr_alloc.pl Executable file
View file

@ -0,0 +1,118 @@
#!/usr/bin/perl
# NDR allocation tests
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
use strict;
use Test::More tests => 5 * 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
# Check that an outgoing scalar pointer is allocated correctly
test_samba4_ndr("alloc-scalar",
'
typedef struct {
uint8 *x;
} bla;
[public] void TestAlloc([in] bla foo);
','
uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef, 0x03 };
DATA_BLOB b = { data, 5 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct TestAlloc r;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
return 1;
if (r.in.foo.x == NULL)
return 2;
if (*r.in.foo.x != 0x03)
return 3;
'
);
# Check that an outgoing buffer pointer is allocated correctly
test_samba4_ndr("alloc-buffer",
'
typedef struct { uint8 data; } blie;
typedef struct { blie *x; } bla;
[public] void TestAlloc([in] bla foo);
','
uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef, 0x03 };
DATA_BLOB b = { data, 5 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct TestAlloc r;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
return 1;
if (r.in.foo.x == NULL)
return 2;
if (r.in.foo.x->data != 0x03)
return 3;
'
);
# Check that ref pointers aren't allocated by default
test_samba4_ndr("ref-noalloc-null",
'
[public] void TestAlloc([in,ref] uint8 *t);
','
uint8_t data[] = { 0x03 };
DATA_BLOB b = { data, 1 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct TestAlloc r;
r.in.t = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
return 1;
'
);
# Check that ref pointers aren't allocated by default
test_samba4_ndr("ref-noalloc",
'
[public] void TestAlloc([in,ref] uint8 *t);
','
uint8_t data[] = { 0x03 };
DATA_BLOB b = { data, 1 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct TestAlloc r;
uint8_t x;
r.in.t = &x;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
return 1;
if (*r.in.t != 0x03)
return 2;
'
);
# Check that an outgoing ref pointer is allocated correctly
test_samba4_ndr("ref-alloc",
'
[public] void TestAlloc([in,ref] uint8 *t);
','
uint8_t data[] = { 0x03 };
DATA_BLOB b = { data, 1 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct TestAlloc r;
ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
r.in.t = NULL;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
return 1;
if (r.in.t == NULL)
return 2;
if (*r.in.t != 0x03)
return 3;
'
);

37
bin/pidl/tests/ndr_array.pl Executable file
View file

@ -0,0 +1,37 @@
#!/usr/bin/perl
# Array testing
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict;
use Test::More tests => 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
test_samba4_ndr(
'Fixed-Array',
'[public] void Test([in] uint8 x[10]);',
'
uint8_t data[] = {1,2,3,4,5,6,7,8,9,10};
int i;
DATA_BLOB b;
struct ndr_pull *ndr;
struct Test r;
b.data = data;
b.length = 10;
ndr = ndr_pull_init_blob(&b, mem_ctx, NULL);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_Test(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 10)
return 2;
for (i = 0; i < 10; i++) {
if (r.in.x[i] != i+1) return 3;
}
');

21
bin/pidl/tests/ndr_compat.pl Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/perl
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict;
use Test::More tests => 2;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl;
use Parse::Pidl::IDL;
sub parse_idl($)
{
my $idl = shift;
my $pidl = Parse::Pidl::IDL::parse_string("interface echo { $idl }; ", "nofile");
Parse::Pidl::NDR::Parse($pidl);
}
test_warnings("", sub {parse_idl("void x();"); });
test_warnings("nofile:0: top-level [out] pointer `x' is not a [ref] pointer\n", sub {parse_idl("void x([out,unique] int *x);"); });

View file

@ -0,0 +1,26 @@
#!/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 => 1;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper);
use Parse::Pidl::NDR qw(ValidElement);
# Case 1
my $e = {
'FILE' => 'foo.idl',
'NAME' => 'v',
'PROPERTIES' => {"subcontext" => 1},
'POINTERS' => 0,
'TYPE' => 'uint8',
'PARENT' => { TYPE => 'STRUCT' },
'LINE' => 42 };
test_warnings("foo.idl:42: subcontext() is deprecated. Use represent_as() or transmit_as() instead\n",
sub { ValidElement($e); });

44
bin/pidl/tests/ndr_fullptr.pl Executable file
View file

@ -0,0 +1,44 @@
#!/usr/bin/perl
# Simple tests for unique pointers
# (C) 2006 Jelmer Vernooij <jelmer@samba.org>.
# Published under the GNU General Public License.
use strict;
use Test::More tests => 1 * 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
SKIP: {
skip "full pointers not supported yet", 8;
test_samba4_ndr("fullptr-push-dup",
'
[public] uint16 echo_TestFull([in,ptr] uint32 *x, [in,ptr] uint32 *y);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
uint32_t v = 13;
struct echo_TestFull r;
r.in.x = &v;
r.in.y = &v;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestFull(ndr, NDR_IN, &r))) {
fprintf(stderr, "push failed\n");
return 1;
}
if (ndr->offset != 12) {
fprintf(stderr, "Offset(%d) != 12\n", ndr->offset);
return 2;
}
if (ndr->data[0] != ndr->data[8] ||
ndr->data[1] != ndr->data[9] ||
ndr->data[2] != ndr->data[10] ||
ndr->data[3] != ndr->data[11]) {
fprintf(stderr, "Data incorrect\n");
return 3;
}
');
}

526
bin/pidl/tests/ndr_refptr.pl Executable file
View file

@ -0,0 +1,526 @@
#!/usr/bin/perl
# Simple tests for pidl's handling of ref pointers, based
# on tridge's ref_notes.txt
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>.
# Published under the GNU General Public License.
use strict;
use Test::More tests => 22 * 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
test_samba4_ndr("noptr-push",
' typedef struct {
uint16 x;
} xstruct;
[public] uint16 echo_TestRef([in] xstruct foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
uint16_t v = 13;
struct echo_TestRef r;
r.in.foo.x = v;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r))) {
fprintf(stderr, "push failed\n");
return 1;
}
if (ndr->offset != 2) {
fprintf(stderr, "Offset(%d) != 2\n", ndr->offset);
return 2;
}
if (ndr->data[0] != 13 || ndr->data[1] != 0) {
fprintf(stderr, "Data incorrect\n");
return 3;
}
');
test_samba4_ndr("ptr-embedded-push",
' typedef struct {
uint16 *x;
} xstruct;
[public] uint16 echo_TestRef([in] xstruct foo);
',
'
uint16_t v = 13;
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo.x = &v;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 6)
return 2;
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
ndr->data[2] == 0 && ndr->data[3] == 0)
return 3;
if (ndr->data[4] != 13 || ndr->data[5] != 0)
return 4;
');
test_samba4_ndr("ptr-embedded-push-null",
' typedef struct {
uint16 *x;
} xstruct;
[public] uint16 echo_TestRef([in] xstruct foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo.x = NULL;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 4)
return 2;
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
ndr->data[2] != 0 || ndr->data[3] != 0)
return 3;
');
test_samba4_ndr("refptr-embedded-push",
'
typedef struct {
[ref] uint16 *x;
} xstruct;
[public] uint16 echo_TestRef([in] xstruct foo);
',
'
uint16_t v = 13;
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo.x = &v;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 6)
return 2;
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
ndr->data[2] == 0 && ndr->data[3] == 0)
return 3;
if (ndr->data[4] != 13 || ndr->data[5] != 0)
return 4;
');
test_samba4_ndr("refptr-embedded-push-null",
'
typedef struct {
[ref] uint16 *x;
} xstruct;
[public] uint16 echo_TestRef([in] xstruct foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo.x = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
/* Windows gives [client runtime error 0x6f4] */
');
test_samba4_ndr("ptr-top-push",
'
typedef struct {
uint16 x;
} xstruct;
[public] uint16 echo_TestRef([in] xstruct *foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
struct xstruct s;
s.x = 13;
r.in.foo = &s;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 2)
return 2;
if (ndr->data[0] != 13 || ndr->data[1] != 0)
return 3;
');
test_samba4_ndr("ptr-top-push-null",
'
typedef struct {
uint16 x;
} xstruct;
[public] uint16 echo_TestRef([in] xstruct *foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
/* Windows gives [client runtime error 0x6f4] */
');
test_samba4_ndr("refptr-top-push",
'
typedef struct {
uint16 x;
} xstruct;
[public] uint16 echo_TestRef([in,ref] xstruct *foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
struct xstruct s;
s.x = 13;
r.in.foo = &s;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 2)
return 2;
if (ndr->data[0] != 13 || ndr->data[1] != 0)
return 3;
');
test_samba4_ndr("refptr-top-push-null",
'
typedef struct {
uint16 x;
} xstruct;
[public] uint16 echo_TestRef([in,ref] xstruct *foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
/* Windows gives [client runtime error 0x6f4] */
');
test_samba4_ndr("uniqueptr-top-push",
' typedef struct {
uint16 x;
} xstruct;
[public] uint16 echo_TestRef([in,unique] xstruct *foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
struct xstruct s;
s.x = 13;
r.in.foo = &s;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 6)
return 2;
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
ndr->data[2] == 0 && ndr->data[3] == 0)
return 3;
if (ndr->data[4] != 13 || ndr->data[5] != 0)
return 4;
');
test_samba4_ndr("uniqueptr-top-push-null",
' typedef struct {
uint16 x;
} xstruct;
[public] uint16 echo_TestRef([in,unique] xstruct *foo);
',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo = NULL;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 4)
return 2;
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
ndr->data[2] != 0 || ndr->data[3] != 0)
return 3;
');
test_samba4_ndr("ptr-top-out-pull",
'
typedef struct {
uint16 x;
} xstruct;
[public] void echo_TestRef([out] xstruct *foo);
',
'
uint8_t data[] = { 0x0D, 0x00 };
DATA_BLOB b = { data, 2 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct xstruct s;
struct echo_TestRef r;
r.out.foo = &s;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
return 1;
if (!r.out.foo)
return 2;
if (r.out.foo->x != 13)
return 3;
');
test_samba4_ndr("ptr-top-out-pull-null",
'
typedef struct {
uint16 x;
} xstruct;
[public] void echo_TestRef([out] xstruct *foo);
',
'
uint8_t data[] = { 0x0D, 0x00 };
DATA_BLOB b = { data, 2 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct echo_TestRef r;
r.out.foo = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
return 1;
/* Windows gives [client runtime error 0x6f4] */
');
test_samba4_ndr("refptr-top-out-pull",
'
typedef struct {
uint16 x;
} xstruct;
[public] void echo_TestRef([out,ref] xstruct *foo);
',
'
uint8_t data[] = { 0x0D, 0x00 };
DATA_BLOB b = { data, 2 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct xstruct s;
struct echo_TestRef r;
r.out.foo = &s;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
return 1;
if (!r.out.foo)
return 2;
if (r.out.foo->x != 13)
return 3;
');
test_samba4_ndr("refptr-top-out-pull-null",
'
typedef struct {
uint16 x;
} xstruct;
[public] void echo_TestRef([out,ref] xstruct *foo);
',
'
uint8_t data[] = { 0x0D, 0x00 };
DATA_BLOB b = { data, 2 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
struct echo_TestRef r;
r.out.foo = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
return 1;
/* Windows gives [client runtime error 0x6f4] */
');
test_samba4_ndr("ptr-top-push-double",
'
[public] void echo_TestRef([in] uint16 **foo);
',
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
uint16_t v = 13;
uint16_t *pv = &v;
r.in.foo = &pv;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 6)
return 2;
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
ndr->data[2] == 0 && ndr->data[3] == 0)
return 3;
if (ndr->data[4] != 0x0D || ndr->data[5] != 0x00)
return 4;
');
SKIP: {
skip "ptr-top-push-double-sndnull is known to fail", 8;
test_samba4_ndr("ptr-top-push-double-sndnull",
'
[public] void echo_TestRef([in] uint16 **foo);
',
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
uint16_t *pv = NULL;
r.in.foo = &pv;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 4)
return 2;
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
ndr->data[2] != 0 || ndr->data[3] != 0)
return 3;
');
}
test_samba4_ndr("ptr-top-push-double-fstnull",
'
[public] void echo_TestRef([in] uint16 **foo);
',
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
/* Windows gives [client runtime error 0x6f4] */
');
test_samba4_ndr("refptr-top-push-double",
'
[public] void echo_TestRef([in,ref] uint16 **foo);
',
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
uint16_t v = 13;
uint16_t *pv = &v;
r.in.foo = &pv;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 6)
return 2;
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
ndr->data[2] == 0 && ndr->data[3] == 0)
return 3;
if (ndr->data[4] != 0x0D || ndr->data[5] != 0x00)
return 4;
');
SKIP: {
skip "refptr-top-push-double-sndnull is known to fail", 8;
test_samba4_ndr("refptr-top-push-double-sndnull",
'
[public] void echo_TestRef([in,ref] uint16 **foo);
',
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
uint16_t *pv = NULL;
r.in.foo = &pv;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 4)
return 2;
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
ndr->data[2] != 0 || ndr->data[3] != 0)
return 3;
');
}
test_samba4_ndr("refptr-top-push-double-fstnull",
'
[public] void echo_TestRef([in,ref] uint16 **foo);
',
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
r.in.foo = NULL;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
/* Windows gives [client runtime error 0x6f4] */
');
SKIP: {
skip "ignore-ptrs are not supported yet", 8;
test_samba4_ndr("ignore-ptr",
'
[public] void echo_TestRef([in,ignore] uint16 *foo, [in] uint16 *bar);
',
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct echo_TestRef r;
uint16_t v = 10;
r.in.foo = &v;
r.in.bar = &v;
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
return 1;
if (ndr->offset != 4)
return 2;
');
}

71
bin/pidl/tests/ndr_represent.pl Executable file
View file

@ -0,0 +1,71 @@
#!/usr/bin/perl
# NDR represent_as() / transmit_as() tests
# (C) 2006 Jelmer Vernooij. Published under the GNU GPL
use strict;
use Test::More tests => 2 * 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
test_samba4_ndr('represent_as-simple',
'
void bla([in,represent_as(uint32)] uint8 x);
',
'
uint8_t expected[] = { 0x0D };
DATA_BLOB in_blob = { expected, 1 };
struct ndr_pull *ndr = ndr_pull_init_blob(&in_blob, NULL, NULL);
struct bla r;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
if (r.in.x != 13)
return 2;
',
'
enum ndr_err_code ndr_uint8_to_uint32(uint8_t from, uint32_t *to)
{
*to = from;
return NDR_ERR_SUCCESS;
}
enum ndr_err_code ndr_uint32_to_uint8(uint32_t from, uint8_t *to)
{
*to = from;
return NDR_ERR_SUCCESS;
}
'
);
test_samba4_ndr('transmit_as-simple',
'
void bla([in,transmit_as(uint32)] uint8 x);
',
'
uint8_t expected[] = { 0x0D };
DATA_BLOB in_blob = { expected, 1 };
struct ndr_pull *ndr = ndr_pull_init_blob(&in_blob, NULL, NULL);
struct bla r;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
if (r.in.x != 13)
return 2;
',
'
enum ndr_err_code ndr_uint8_to_uint32(uint8_t from, uint32_t *to)
{
*to = from;
return NDR_ERR_SUCCESS;
}
enum ndr_err_code ndr_uint32_to_uint8(uint32_t from, uint8_t *to)
{
*to = from;
return NDR_ERR_SUCCESS;
}
'
);

28
bin/pidl/tests/ndr_simple.pl Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/perl
# Some simple tests for pidl
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict;
use Test::More tests => 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
test_samba4_ndr("simple", "void Test(); ",
"
uint8_t data[] = { 0x02 };
uint8_t result;
DATA_BLOB b;
struct ndr_pull *ndr;
b.data = data;
b.length = 1;
ndr = ndr_pull_init_blob(&b, mem_ctx, NULL);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_uint8(ndr, NDR_SCALARS, &result)))
return 1;
if (result != 0x02)
return 2;
");

192
bin/pidl/tests/ndr_string.pl Executable file
View file

@ -0,0 +1,192 @@
#!/usr/bin/perl
# String tests for pidl
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict;
use Test::More tests => 6 * 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
test_samba4_ndr("string-pull-empty",
' [public] void TestString([in,flag(STR_ASCII|LIBNDR_FLAG_STR_SIZE4)] string data);',
'
uint8_t data[] = { 0x00, 0x00, 0x00, 0x00 };
DATA_BLOB b = { data, 4 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
struct TestString r;
r.in.data = NULL;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
return 1;
if (r.in.data == NULL)
return 2;
if (r.in.data[0] != 0)
return 3;
');
test_samba4_ndr("string-ascii-pull",
'
[public] void TestString([in,flag(STR_ASCII|LIBNDR_FLAG_STR_SIZE4)] string data);
',
'
uint8_t data[] = { 0x03, 0x00, 0x00, 0x00,
\'f\', \'o\', \'o\', 0 };
DATA_BLOB b = { data, 8 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
struct TestString r;
r.in.data = NULL;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
return 1;
if (r.in.data == NULL)
return 2;
if (strncmp(r.in.data, "foo", 3) != 0)
return 3;
if (r.in.data[4] != 0)
return 4;
');
test_samba4_ndr("string-wchar-fixed-array-01",
'
typedef struct {
uint32 l1;
[string,charset(UTF16)] uint16 str[6];
uint32 l2;
} TestStringStruct;
[public] void TestString([in,ref] TestStringStruct *str);
',
'
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
\'f\', 0x00, \'o\', 0x00,
\'o\', 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00
};
DATA_BLOB b = { data, sizeof(data) };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
struct TestString r;
struct TestStringStruct str;
r.in.str = &str;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
return 1;
if (r.in.str == NULL)
return 2;
if (r.in.str->l1 != 0x00000001)
return 3;
if (strncmp(str.str, "foo", 3) != 0)
return 4;
if (r.in.str->str[4] != 0)
return 5;
if (r.in.str->l2 != 0x00000002)
return 6;
');
test_samba4_ndr("string-wchar-fixed-array-02",
'
typedef struct {
uint32 l1;
[string,charset(UTF16)] uint16 str[6];
uint32 l2;
} TestStringStruct;
[public] void TestString([in,ref] TestStringStruct *str);
',
'
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00,
\'f\', 0x00, \'o\', 0x00,
\'o\', 0x00, \'b\', 0x00,
\'a\', 0x00, \'r\', 0x00,
0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00
};
DATA_BLOB b = { data, sizeof(data) };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
struct TestString r;
struct TestStringStruct str;
r.in.str = &str;
/* the string terminator is wrong */
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
return 1;
');
test_samba4_ndr("string-wchar-fixed-array-03",
'
typedef struct {
uint32 l1;
[string,charset(UTF16)] uint16 str[6];
uint32 l2;
} TestStringStruct;
[public] void TestString([in,ref] TestStringStruct *str);
',
'
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00,
\'f\', 0x00, \'o\', 0x00,
\'o\', 0x00, \'b\', 0x00,
\'a\', 0x00, \'r\', 0x00,
0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00
};
DATA_BLOB b = { data, sizeof(data) };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
struct TestString r;
struct TestStringStruct str;
r.in.str = &str;
/* the length 0x07 is to large */
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
return 1;
');
SKIP: {
skip "doesn't seem to work yet", 8;
test_samba4_ndr("string-out",
'
[public] void TestString([out,string,charset(UNIX)] uint8 **data);
',
'
uint8_t data[] = { 0x03, 0x00, 0x00, 0x00,
\'f\', \'o\', \'o\', 0 };
DATA_BLOB b = { data, 8 };
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
struct TestString r;
char *str = NULL;
r.out.data = &str;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
return 1;
if (r.out.data == NULL)
return 2;
if (*r.out.data == NULL)
return 3;
if (strncmp(r.out.data, "foo", 3) != 0)
return 4;
if (r.out.data[4] != 0)
return 5;
');
}

66
bin/pidl/tests/ndr_tagtype.pl Executable file
View file

@ -0,0 +1,66 @@
#!/usr/bin/perl
# Support for tagged types
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
use strict;
use Test::More tests => 3 * 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_samba4_ndr);
test_samba4_ndr('struct-notypedef', '[public] struct bla { uint8 x; }; ',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct bla r;
uint8_t expected[] = { 0x0D };
DATA_BLOB expected_blob = { expected, 1 };
DATA_BLOB result_blob;
r.x = 13;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_STRUCT_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');
test_samba4_ndr('struct-notypedef-used', '[public] struct bla { uint8 x; };
[public] void myfn([in] struct bla r); ',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct myfn fn;
uint8_t expected[] = { 0x0D };
DATA_BLOB expected_blob = { expected, 1 };
DATA_BLOB result_blob;
fn.in.r.x = 13;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_myfn(ndr, NDR_IN, &fn)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');
test_samba4_ndr('struct-notypedef-embedded', 'struct bla { uint8 x; };
[public] struct myst { struct bla r; }; ',
'
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
struct myst st;
uint8_t expected[] = { 0x0D };
DATA_BLOB expected_blob = { expected, 1 };
DATA_BLOB result_blob;
st.r.x = 13;
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_STRUCT_myst(ndr, NDR_IN, &st)))
return 1;
result_blob = ndr_push_blob(ndr);
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
return 2;
');

243
bin/pidl/tests/parse_idl.pl Executable file
View file

@ -0,0 +1,243 @@
#!/usr/bin/perl
# Some simple tests for pidls parsing routines
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict;
use Test::More tests => 65 * 2 + 7;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_errors);
use Parse::Pidl::IDL;
use Parse::Pidl::NDR;
sub testok($$)
{
my ($name, $data) = @_;
test_errors("", sub {
my $pidl = Parse::Pidl::IDL::parse_string($data, "<$name>");
ok (defined($pidl), $name);
});
}
sub testfail($$$)
{
my ($name, $data, $error) = @_;
test_errors($error, sub {
my $pidl = Parse::Pidl::IDL::parse_string($data, "<$name>");
ok ((not defined $pidl), $name);
});
}
testfail "unknowntag", "bla test {};",
"<unknowntag>:0: Syntax error near 'bla'\n";
testok "test1", "interface test { void Test(); }; ";
testok "voidtest", "interface test { int Testx(void); }; ";
testfail "voidtest", "interface test { Test(); }; ",
"<voidtest>:0: Syntax error near '('\n";
testok "argtest", "interface test { int Test(int a, long b, uint32 c); }; ";
testok "array1", "interface test { int Test(int a[]); };";
testok "array2", "interface test { int Test(int a[2]); };";
testok "array3", "interface test { int Test(int a[b]); };";
testfail "array4", "interface test { int Test(int[] a); };",
"<array4>:0: Syntax error near '['\n";
testok "ptr1", "interface test { int Test(int *a); };";
testok "ptr2", "interface test { int Test(int **a); };";
testok "ptr3", "interface test { int Test(int ***a); };";
testfail "empty1", "interface test { };", "<empty1>:0: Syntax error near '}'\n";
testfail "empty2", "", "";
testok "attr1", "[uuid(\"myuuid\"),attr] interface test { int Test(int ***a); };";
testok "attr2", "interface test { [public] int Test(); };";
testok "attr3", "[attr1] [attr2] interface test { [public] int Test(); };";
testok "multfn", "interface test { int test1(); int test2(); };";
testok "multif", "interface test { int test1(); }; interface test2 { int test2(); };";
testok "tdstruct1", "interface test { typedef struct { } foo; };";
testok "tdstruct2", "interface test { typedef struct { int a; } foo; };";
testok "tdstruct3", "interface test { typedef struct { int a; int b; } foo; };";
testfail "tdstruct4", "interface test { typedef struct { int a, int b; } foo; };",
"<tdstruct4>:0: Syntax error near ','\n";
testok "struct1", "interface test { struct x { }; };";
testok "struct2", "interface test { struct x { int a; }; };";
testok "struct3", "interface test { struct x { int a; int b; }; };";
testfail "struct4", "interface test { struct x { int a, int b; }; };",
"<struct4>:0: Syntax error near ','\n";
testfail "struct5", "interface test { struct { int a; } x; };",
"<struct5>:0: Syntax error near 'x'\n";
testok "tdunion1", "interface test { typedef union { } a; };";
testok "tdunion2", "interface test { typedef union { int a; } a; };";
testok "union1", "interface test { union a { }; };";
testok "union2", "interface test { union x { int a; }; };";
testfail "union3", "interface test { union { int a; } x; };",
"<union3>:0: Syntax error near 'x'\n";
testok "typedef1", "interface test { typedef int a; };";
testfail "typedef2", "interface test { typedef x; };",
"<typedef2>:0: Syntax error near ';'\n";
testok "tdenum1", "interface test { typedef enum { A=1, B=2, C} a; };";
testok "enum1", "interface test { enum a { A=1, B=2, C}; };";
testfail "enum2", "interface test { enum { A=1, B=2, C} a; };",
"<enum2>:0: Syntax error near 'a'\n";
testok "nested1", "interface test { struct x { struct { int a; } z; }; };";
testok "nested2", "interface test { struct x { struct y { int a; } z; }; };";
testok "bitmap1", "interface test { bitmap x { a=1 }; };";
testok "unsigned", "interface test { struct x { unsigned short y; }; };";
testok "struct-property", "interface test { [public] struct x { short y; }; };";
testok "signed", "interface test { struct x { signed short y; }; };";
testok "declarg", "interface test { void test(struct { int x; } a); };";
testok "structarg", "interface test { void test(struct a b); };";
testfail "structargmissing", "interface test { void test(struct a); };",
"<structargmissing>:0: Syntax error near ')'\n";
testok "structqual", "interface test { struct x { struct y z; }; };";
testok "unionqual", "interface test { struct x { union y z; }; };";
testok "enumqual", "interface test { struct x { enum y z; }; };";
testok "bitmapqual", "interface test { struct x { bitmap y z; }; };";
testok "emptystructdecl", "interface test { struct x; };";
testok "emptyenumdecl", "interface test { enum x; };";
testok "emptytdstructdecl", "interface test { typedef struct x y; };";
testok "import", "import \"foo.idl\";";
testok "include", "include \"foo.h\";";
testfail "import-noquotes", "import foo.idl;",
"<import-noquotes>:0: Syntax error near 'foo'\n";
testfail "include-noquotes", "include foo.idl;",
"<include-noquotes>:0: Syntax error near 'foo'\n";
testok "importlib", "importlib \"foo.idl\";";
testfail "import-nosemicolon", "import \"foo.idl\"",
"<import-nosemicolon>:0: Syntax error near 'foo.idl'\n";
testok "import-multiple", "import \"foo.idl\", \"bar.idl\";";
testok "include-multiple", "include \"foo.idl\", \"bar.idl\";";
testok "empty-struct", "interface test { struct foo { }; }";
testok "typedef-double", "interface test { typedef struct foo { } foo; }";
testok "cpp-quote", "cpp_quote(\"bla\")";
my $x = Parse::Pidl::IDL::parse_string("interface foo { struct x {}; }", "<foo>");
is_deeply($x, [ {
'TYPE' => 'INTERFACE',
'NAME' => 'foo',
'DATA' => [ {
'TYPE' => 'STRUCT',
'NAME' => 'x',
'ELEMENTS' => [],
'FILE' => '<foo>',
'LINE' => 0
} ],
'FILE' => '<foo>',
'LINE' => 0
}]);
$x = Parse::Pidl::IDL::parse_string("interface foo { struct x; }", "<foo>");
is_deeply($x, [ {
'TYPE' => 'INTERFACE',
'NAME' => 'foo',
'DATA' => [ {
'TYPE' => 'STRUCT',
'NAME' => 'x',
'FILE' => '<foo>',
'LINE' => 0
} ],
'FILE' => '<foo>',
'LINE' => 0
}]);
$x = Parse::Pidl::IDL::parse_string("cpp_quote(\"foobar\")", "<quote>");
is_deeply($x, [ {
'TYPE' => 'CPP_QUOTE',
'DATA' => '"foobar"',
'FILE' => '<quote>',
'LINE' => 0
}]);
# A typedef of a struct without body
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef struct x y; }", "<foo>");
is_deeply($x, [ {
'TYPE' => 'INTERFACE',
'NAME' => 'foo',
'DATA' => [ {
'TYPE' => 'TYPEDEF',
'NAME' => 'y',
'POINTERS' => 0,
'DATA' => {
'TYPE' => 'STRUCT',
'NAME' => 'x',
'FILE' => '<foo>',
'LINE' => 0,
},
'FILE' => '<foo>',
'LINE' => 0,
} ],
'FILE' => '<foo>',
'LINE' => 0
}]);
# A typedef of a struct with empty body
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef struct {} y; }", "<foo>");
is_deeply($x, [ {
'TYPE' => 'INTERFACE',
'NAME' => 'foo',
'DATA' => [ {
'TYPE' => 'TYPEDEF',
'NAME' => 'y',
'POINTERS' => 0,
'DATA' => {
'TYPE' => 'STRUCT',
'ELEMENTS' => [],
'FILE' => '<foo>',
'LINE' => 0
},
'FILE' => '<foo>',
'LINE' => 0
} ],
'FILE' => '<foo>',
'LINE' => 0
}]);
# A typedef of a bitmap with no body
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef bitmap x y; }", "<foo>");
is_deeply($x, [ {
'TYPE' => 'INTERFACE',
'NAME' => 'foo',
'DATA' => [ {
'TYPE' => 'TYPEDEF',
'NAME' => 'y',
'POINTERS' => 0,
'DATA' => {
'TYPE' => 'BITMAP',
'NAME' => 'x',
'FILE' => '<foo>',
'LINE' => 0
},
'FILE' => '<foo>',
'LINE' => 0
} ],
'FILE' => '<foo>',
'LINE' => 0
}]);
# A typedef of a union with no body
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef union x y; }", "<foo>");
is_deeply($x, [ {
'TYPE' => 'INTERFACE',
'NAME' => 'foo',
'DATA' => [ {
'TYPE' => 'TYPEDEF',
'NAME' => 'y',
'POINTERS' => 0,
'DATA' => {
'TYPE' => 'UNION',
'NAME' => 'x',
'FILE' => '<foo>',
'LINE' => 0
},
'FILE' => '<foo>',
'LINE' => 0
} ],
'FILE' => '<foo>',
'LINE' => 0
}]);

300
bin/pidl/tests/samba-ndr.pl Executable file
View file

@ -0,0 +1,300 @@
#!/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 => 31;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use strict;
use Parse::Pidl::Util qw(MyDumper);
use Parse::Pidl::Samba4::NDR::Parser qw(check_null_pointer
NeededFunction NeededElement NeededType
NeededInterface TypeFunctionName ParseElementPrint);
my $output;
sub print_fn($) { my $x = shift; $output.=$x; }
# Test case 1: Simple unique pointer dereference
$output = "";
my $fn = check_null_pointer({
PARENT => {
ELEMENTS => [
{
NAME => "bla",
LEVELS => [
{ TYPE => "POINTER",
POINTER_INDEX => 0,
POINTER_TYPE => "unique" },
{ TYPE => "DATA" }
],
},
]
}
}, { bla => "r->in.bla" }, \&print_fn, "return;");
test_warnings("", sub { $fn->("r->in.bla"); });
is($output, "if (r->in.bla == NULL) return;");
# Test case 2: Simple ref pointer dereference
$output = "";
$fn = check_null_pointer({
PARENT => {
ELEMENTS => [
{
NAME => "bla",
LEVELS => [
{ TYPE => "POINTER",
POINTER_INDEX => 0,
POINTER_TYPE => "ref" },
{ TYPE => "DATA" }
],
},
]
}
}, { bla => "r->in.bla" }, \&print_fn, undef);
test_warnings("", sub { $fn->("r->in.bla"); });
is($output, "");
# Test case 3: Illegal dereference
$output = "";
$fn = check_null_pointer({
FILE => "nofile",
LINE => 1,
PARENT => {
ELEMENTS => [
{
NAME => "bla",
LEVELS => [
{ TYPE => "DATA" }
],
},
]
}
}, { bla => "r->in.bla" }, \&print_fn, undef);
test_warnings("nofile:1: too much dereferences for `bla'\n",
sub { $fn->("r->in.bla"); });
is($output, "");
# Test case 4: Double pointer dereference
$output = "";
$fn = check_null_pointer({
PARENT => {
ELEMENTS => [
{
NAME => "bla",
LEVELS => [
{ TYPE => "POINTER",
POINTER_INDEX => 0,
POINTER_TYPE => "unique" },
{ TYPE => "POINTER",
POINTER_INDEX => 1,
POINTER_TYPE => "unique" },
{ TYPE => "DATA" }
],
},
]
}
}, { bla => "r->in.bla" }, \&print_fn, "return;");
test_warnings("",
sub { $fn->("*r->in.bla"); });
is($output, "if (*r->in.bla == NULL) return;");
# Test case 5: Unknown variable
$output = "";
$fn = check_null_pointer({
FILE => "nofile",
LINE => 2,
PARENT => {
ELEMENTS => [
{
NAME => "bla",
LEVELS => [
{ TYPE => "DATA" }
],
},
]
}
}, { }, \&print_fn, "return;");
test_warnings("nofile:2: unknown dereferenced expression `r->in.bla'\n",
sub { $fn->("r->in.bla"); });
is($output, "if (r->in.bla == NULL) return;");
my $needed = {};
NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
is_deeply($needed, { ndr_pull_foo => 1 });
# old settings should be kept
$needed = { ndr_pull_foo => 0 };
NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "pull", $needed);
is_deeply($needed, { ndr_pull_foo => 0 });
# print/pull/push are independent of each other
$needed = { ndr_pull_foo => 0 };
NeededElement({ TYPE => "foo", REPRESENTATION_TYPE => "foo" }, "print", $needed);
is_deeply($needed, { ndr_pull_foo => 0, ndr_print_foo => 1 });
$needed = { };
NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
is_deeply($needed, { ndr_pull_foo => 1, ndr_print_foo => 1, ndr_push_foo => 1,
ndr_pull_bar => 1, ndr_print_bar => 1, ndr_push_bar => 1});
# push/pull/print are always set for functions
$needed = { ndr_pull_foo => 0 };
NeededFunction({ NAME => "foo", ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] }, $needed);
is_deeply($needed, { ndr_pull_foo => 1, ndr_print_foo => 1, ndr_push_foo => 1,
ndr_pull_bar => 1, ndr_push_bar => 1, ndr_print_bar => 1});
# public structs are always needed
$needed = {};
NeededType({ NAME => "bla", TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
$needed, "pull");
is_deeply($needed, { });
$needed = {};
NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT", ELEMENTS => [] } } ] },
$needed);
is_deeply($needed, { ndr_pull_bla => 1, ndr_push_bla => 1, ndr_print_bla => 1 });
# make sure types for elements are set too
$needed = {};
NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
$needed);
is_deeply($needed, { ndr_pull_bla => 1, ndr_pull_bar => 1, ndr_push_bla => 1, ndr_push_bar => 1,
ndr_print_bla => 1, ndr_print_bar => 1});
$needed = {};
NeededInterface({ TYPES => [ { PROPERTIES => { gensize => 1}, NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
$needed);
is_deeply($needed, { ndr_size_bla => 1 });
# make sure types for elements are set too
$needed = { ndr_pull_bla => 1 };
NeededType({ NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
$needed, "pull");
is_deeply($needed, { ndr_pull_bla => 1, ndr_pull_bar => 1 });
$needed = {};
NeededInterface({ TYPES => [ { PROPERTIES => { public => 1},
NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "rep" } ] } } ] }, $needed);
is_deeply($needed, { ndr_pull_bla => 1, ndr_push_bla => 1, ndr_print_bla => 1,
ndr_print_rep => 1,
ndr_pull_bar => 1, ndr_push_bar => 1,
ndr_bar_to_rep => 1, ndr_rep_to_bar => 1});
my $generator = new Parse::Pidl::Samba4::NDR::Parser();
$generator->ParseStructPush({
NAME => "mystruct",
TYPE => "STRUCT",
PROPERTIES => {},
ALIGN => 4,
ELEMENTS => [ ]}, "ndr", "x");
is($generator->{res}, "NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_push_align(ndr, 4));
NDR_CHECK(ndr_push_trailer_align(ndr, 4));
}
if (ndr_flags & NDR_BUFFERS) {
}
");
$generator = new Parse::Pidl::Samba4::NDR::Parser();
my $e = {
NAME => "el1",
TYPE => "mytype",
REPRESENTATION_TYPE => "mytype",
PROPERTIES => {},
LEVELS => [
{ LEVEL_INDEX => 0, TYPE => "DATA", DATA_TYPE => "mytype" }
] };
$generator->ParseStructPush({
NAME => "mystruct",
TYPE => "STRUCT",
PROPERTIES => {},
ALIGN => 4,
SURROUNDING_ELEMENT => $e,
ELEMENTS => [ $e ]}, "ndr", "x");
is($generator->{res}, "NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1)));
NDR_CHECK(ndr_push_align(ndr, 4));
NDR_CHECK(ndr_push_mytype(ndr, NDR_SCALARS, &x->el1));
NDR_CHECK(ndr_push_trailer_align(ndr, 4));
}
if (ndr_flags & NDR_BUFFERS) {
}
");
is(TypeFunctionName("ndr_pull", "uint32"), "ndr_pull_uint32");
is(TypeFunctionName("ndr_pull", {TYPE => "ENUM", NAME => "bar"}), "ndr_pull_ENUM_bar");
is(TypeFunctionName("ndr_pull", {TYPE => "TYPEDEF", NAME => "bar", DATA => undef}), "ndr_pull_bar");
is(TypeFunctionName("ndr_push", {TYPE => "STRUCT", NAME => "bar"}), "ndr_push_STRUCT_bar");
# check noprint works
$generator = new Parse::Pidl::Samba4::NDR::Parser();
$generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt",
PROPERTIES => { noprint => 1},
LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt"} ]},
"ndr", "var", { "x" => "r->foobar" } );
is($generator->{res}, "");
$generator = new Parse::Pidl::Samba4::NDR::Parser();
$generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt",
PROPERTIES => {},
LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt" }]},
"ndr", "var", { "x" => "r->foobar" } );
is($generator->{res}, "ndr_print_rt(ndr, \"x\", &var);\n");
# make sure that a print function for an element with value() set works
$generator = new Parse::Pidl::Samba4::NDR::Parser();
$generator->ParseElementPrint({ NAME => "x", TYPE => "uint32", REPRESENTATION_TYPE => "uint32",
PROPERTIES => { value => "23" },
LEVELS => [ { TYPE => "DATA", DATA_TYPE => "uint32"} ]},
"ndr", "var", { "x" => "r->foobar" } );
is($generator->{res}, "ndr_print_uint32(ndr, \"x\", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?23:var);\n");
$generator = new Parse::Pidl::Samba4::NDR::Parser();
$generator->AuthServiceStruct("bridge", "\"rot13\",\"onetimepad\"");
is($generator->{res}, "static const char * const bridge_authservice_strings[] = {
\"rot13\",
\"onetimepad\",
};
static const struct ndr_interface_string_array bridge_authservices = {
.count = 2,
.names = bridge_authservice_strings
};
");

236
bin/pidl/tests/samba3-cli.pl Executable file
View file

@ -0,0 +1,236 @@
#!/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 => 8;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper);
use Parse::Pidl::Samba3::ClientNDR qw(ParseFunction);
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn, "r."));
is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionOutEnv($fn, "r."));
$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn, "r."));
is_deeply({ "foo" => "r.out.foo" }, GenerateFunctionOutEnv($fn, "r."));
$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
is_deeply({ }, GenerateFunctionInEnv($fn, "r."));
is_deeply({ "foo" => "r.out.foo" }, GenerateFunctionOutEnv($fn, "r."));
my $x = new Parse::Pidl::Samba3::ClientNDR();
$fn = { NAME => "bar", ELEMENTS => [ ] };
$x->ParseFunction("foo", $fn);
is($x->{res},
"struct rpccli_bar_state {
TALLOC_CTX *out_mem_ctx;
};
static void rpccli_bar_done(struct tevent_req *subreq);
struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct rpc_pipe_client *cli)
{
struct tevent_req *req;
struct rpccli_bar_state *state;
struct tevent_req *subreq;
req = tevent_req_create(mem_ctx, &state,
struct rpccli_bar_state);
if (req == NULL) {
return NULL;
}
state->out_mem_ctx = NULL;
subreq = dcerpc_bar_send(state,
ev,
cli->binding_handle);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, rpccli_bar_done, req);
return req;
}
static void rpccli_bar_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
struct rpccli_bar_state *state = tevent_req_data(
req, struct rpccli_bar_state);
NTSTATUS status;
TALLOC_CTX *mem_ctx;
if (state->out_mem_ctx) {
mem_ctx = state->out_mem_ctx;
} else {
mem_ctx = state;
}
status = dcerpc_bar_recv(subreq,
mem_ctx);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return;
}
tevent_req_done(req);
}
NTSTATUS rpccli_bar_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx)
{
struct rpccli_bar_state *state = tevent_req_data(
req, struct rpccli_bar_state);
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
tevent_req_received(req);
return status;
}
/* Steal possible out parameters to the callers context */
talloc_steal(mem_ctx, state->out_mem_ctx);
tevent_req_received(req);
return NT_STATUS_OK;
}
NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx)
{
NTSTATUS status;
status = dcerpc_bar(cli->binding_handle,
mem_ctx);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* Return result */
return NT_STATUS_OK;
}
");
$x = new Parse::Pidl::Samba3::ClientNDR();
$fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" };
$x->ParseFunction("foo", $fn);
is($x->{res},
"struct rpccli_bar_state {
TALLOC_CTX *out_mem_ctx;
WERROR result;
};
static void rpccli_bar_done(struct tevent_req *subreq);
struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct rpc_pipe_client *cli)
{
struct tevent_req *req;
struct rpccli_bar_state *state;
struct tevent_req *subreq;
req = tevent_req_create(mem_ctx, &state,
struct rpccli_bar_state);
if (req == NULL) {
return NULL;
}
state->out_mem_ctx = NULL;
subreq = dcerpc_bar_send(state,
ev,
cli->binding_handle);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, rpccli_bar_done, req);
return req;
}
static void rpccli_bar_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
struct rpccli_bar_state *state = tevent_req_data(
req, struct rpccli_bar_state);
NTSTATUS status;
TALLOC_CTX *mem_ctx;
if (state->out_mem_ctx) {
mem_ctx = state->out_mem_ctx;
} else {
mem_ctx = state;
}
status = dcerpc_bar_recv(subreq,
mem_ctx,
&state->result);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return;
}
tevent_req_done(req);
}
NTSTATUS rpccli_bar_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
WERROR *result)
{
struct rpccli_bar_state *state = tevent_req_data(
req, struct rpccli_bar_state);
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
tevent_req_received(req);
return status;
}
/* Steal possible out parameters to the callers context */
talloc_steal(mem_ctx, state->out_mem_ctx);
/* Return result */
*result = state->result;
tevent_req_received(req);
return NT_STATUS_OK;
}
NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
WERROR *werror)
{
WERROR result;
NTSTATUS status;
status = dcerpc_bar(cli->binding_handle,
mem_ctx,
&result);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* Return result */
if (werror) {
*werror = result;
}
return werror_to_ntstatus(result);
}
");

18
bin/pidl/tests/samba3-srv.pl Executable file
View file

@ -0,0 +1,18 @@
#!/usr/bin/perl
# (C) 2008 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict;
use warnings;
use Test::More tests => 1;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper has_property);
use Parse::Pidl::Samba3::ServerNDR qw(DeclLevel);
my $l = { TYPE => "DATA", DATA_TYPE => "uint32" };
my $e = { FILE => "foo", LINE => 0, PROPERTIES => { }, TYPE => "uint32",
LEVELS => [ $l ] };
is("uint32_t", DeclLevel($e, 0));

49
bin/pidl/tests/tdr.pl Executable file
View file

@ -0,0 +1,49 @@
#!/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 => 6;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Samba4::TDR qw(ParserType);
my $tdr = new Parse::Pidl::Samba4::TDR();
$tdr->ParserType({TYPE => "STRUCT", NAME => "foo", PROPERTIES => {public => 1}}, "pull");
is($tdr->{ret}, "NTSTATUS tdr_pull_foo (struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, struct foo *v)
{
return NT_STATUS_OK;
}
");
is($tdr->{ret_hdr}, "NTSTATUS tdr_pull_foo (struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, struct foo *v);\n");
$tdr = new Parse::Pidl::Samba4::TDR();
$tdr->ParserType({TYPE => "UNION", NAME => "bar", PROPERTIES => {public => 1}}, "pull");
is($tdr->{ret}, "NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v)
{
switch (level) {
}
return NT_STATUS_OK;
}
");
is($tdr->{ret_hdr}, "NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v);\n");
$tdr = new Parse::Pidl::Samba4::TDR();
$tdr->ParserType({TYPE => "UNION", NAME => "bar", PROPERTIES => {}}, "pull");
is($tdr->{ret}, "static NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v)
{
switch (level) {
}
return NT_STATUS_OK;
}
");
is($tdr->{ret_hdr}, "");

21
bin/pidl/tests/test_util.pl Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/perl
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict;
use Test::More tests => 6;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util qw(test_warnings test_errors);
use Parse::Pidl qw(warning error);
test_warnings("", sub {});
test_warnings("x:1: msg\n", sub { warning({FILE => "x", LINE => 1}, "msg"); });
test_warnings("", sub {});
test_errors("", sub {});
test_errors("x:1: msg\n", sub { error({FILE => "x", LINE => 1}, "msg"); });
test_errors("", sub {});

93
bin/pidl/tests/typelist.pl Executable file
View file

@ -0,0 +1,93 @@
#!/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 => 56;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Typelist qw(hasType typeHasBody getType mapTypeName expandAlias
mapScalarType addType typeIs is_scalar scalar_is_reference
enum_type_fn bitmap_type_fn mapType);
is("foo", expandAlias("foo"));
is("uint32", expandAlias("DWORD"));
is("int32", expandAlias("int"));
is("", expandAlias(""));
is("int32", expandAlias("int32"));
is("uint32_t", mapScalarType("uint32"));
is("void", mapScalarType("void"));
is("uint64_t", mapScalarType("hyper"));
is("double", mapScalarType("double"));
my $x = { TYPE => "ENUM", NAME => "foo", EXTRADATA => 1 };
addType($x);
is_deeply($x, getType("foo"));
is(undef, getType("bloebla"));
is_deeply(getType({ TYPE => "STRUCT" }), { TYPE => "STRUCT" });
is_deeply(getType({ TYPE => "ENUM", NAME => "foo" }), $x);
is_deeply(getType("uint16"), {
NAME => "uint16",
BASEFILE => "<builtin>",
TYPE => "TYPEDEF",
DATA => { NAME => "uint16", TYPE => "SCALAR" }});
is_deeply(getType("double"), {
NAME => "double",
BASEFILE => "<builtin>",
TYPE => "TYPEDEF",
DATA => { NAME => "double", TYPE => "SCALAR" }});
is(0, typeIs("someUnknownType", "ENUM"));
is(0, typeIs("foo", "ENUM"));
addType({NAME => "mytypedef", TYPE => "TYPEDEF", DATA => { TYPE => "ENUM" }});
is(1, typeIs("mytypedef", "ENUM"));
is(0, typeIs("mytypedef", "BITMAP"));
is(1, typeIs({ TYPE => "ENUM"}, "ENUM"));
is(0, typeIs({ TYPE => "BITMAP"}, "ENUM"));
is(1, typeIs("uint32", "SCALAR"));
is(0, typeIs("uint32", "ENUM"));
is(1, hasType("foo"));
is(0, hasType("nonexistant"));
is(0, hasType({TYPE => "ENUM", NAME => "someUnknownType"}));
is(1, hasType({TYPE => "ENUM", NAME => "foo"}));
is(1, hasType({TYPE => "ENUM"}));
is(1, hasType({TYPE => "STRUCT"}));
is(1, is_scalar("uint32"));
is(0, is_scalar("nonexistant"));
is(1, is_scalar({TYPE => "ENUM"}));
is(0, is_scalar({TYPE => "STRUCT"}));
is(1, is_scalar({TYPE => "TYPEDEF", DATA => {TYPE => "ENUM" }}));
is(1, is_scalar("mytypedef"));
is(1, scalar_is_reference("string"));
is(0, scalar_is_reference("uint32"));
is(0, scalar_is_reference({TYPE => "STRUCT", NAME => "echo_foobar"}));
is("uint8", enum_type_fn({TYPE => "ENUM", PARENT=>{PROPERTIES => {enum8bit => 1}}}));
is("uint32", enum_type_fn({TYPE => "ENUM", PARENT=>{PROPERTIES => {v1_enum => 1}}}));
is("uint1632", enum_type_fn({TYPE => "ENUM", PARENT=>{PROPERTIES => {}}}));
is("uint8", bitmap_type_fn({TYPE => "BITMAP", PROPERTIES => {bitmap8bit => 1}}));
is("uint16", bitmap_type_fn({TYPE => "BITMAP", PROPERTIES => {bitmap16bit => 1}}));
is("hyper", bitmap_type_fn({TYPE => "BITMAP", PROPERTIES => {bitmap64bit => 1}}));
is("uint32", bitmap_type_fn({TYPE => "BITMAP", PROPERTIES => {}}));
is("enum foo", mapType({TYPE => "ENUM"}, "foo"));
is("union foo", mapType({TYPE => "UNION"}, "foo"));
is("struct foo", mapType({TYPE => "STRUCT"}, "foo"));
is("uint8_t", mapType({TYPE => "BITMAP", PROPERTIES => {bitmap8bit => 1}}, "foo"));
is("uint8_t", mapType({TYPE => "SCALAR"}, "uint8"));
is("uint32_t", mapType({TYPE => "TYPEDEF", DATA => {TYPE => "SCALAR"}}, "uint32"));
is("void", mapTypeName(undef));
is("uint32_t", mapTypeName("uint32"));
is("int32_t", mapTypeName("int"));
ok(not typeHasBody({TYPE => "TYPEDEF", DATA => { TYPE => "STRUCT" }}));
ok(typeHasBody({TYPE => "TYPEDEF", DATA => { TYPE => "STRUCT", ELEMENTS => [] }}));

115
bin/pidl/tests/util.pl Executable file
View file

@ -0,0 +1,115 @@
#!/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 => 72;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl qw(error);
use Parse::Pidl::Util;
# has_property()
is(undef, has_property({}, "foo"));
is(undef, has_property({PROPERTIES => {}}, "foo"));
is("data", has_property({PROPERTIES => {foo => "data"}}, "foo"));
is(undef, has_property({PROPERTIES => {foo => undef}}, "foo"));
# is_constant()
ok(is_constant("2"));
ok(is_constant("256"));
ok(is_constant("0x400"));
ok(is_constant("0x4BC"));
ok(not is_constant("0x4BGC"));
ok(not is_constant("str"));
ok(not is_constant("2 * expr"));
# make_str()
is("\"bla\"", make_str("bla"));
is("\"bla\"", make_str("\"bla\""));
is("\"\"bla\"\"", make_str("\"\"bla\"\""));
is("\"bla\"\"", make_str("bla\""));
is("\"foo\"bar\"", make_str("foo\"bar"));
is("bla", unmake_str("\"bla\""));
is("\"bla\"", unmake_str("\"\"bla\"\""));
# print_uuid()
is(undef, print_uuid("invalid"));
is("{0x12345778,0x1234,0xabcd,{0xef,0x00},{0x01,0x23,0x45,0x67,0x89,0xac}}",
print_uuid("12345778-1234-abcd-ef00-0123456789ac"));
is("{0x12345778,0x1234,0xabcd,{0xef,0x00},{0x01,0x23,0x45,0x67,0x89,0xac}}",
print_uuid("\"12345778-1234-abcd-ef00-0123456789ac\""));
# property_matches()
# missing property
ok(not property_matches({PROPERTIES => {}}, "x", "data"));
# data not matching
ok(not property_matches({PROPERTIES => {x => "bar"}}, "x", "data"));
# data matching exactly
ok(property_matches({PROPERTIES => {x => "data"}}, "x", "data"));
# regex matching
ok(property_matches({PROPERTIES => {x => "data"}}, "x", "^([dat]+)\$"));
# ParseExpr()
is(undef, ParseExpr("", {}, undef));
is("a", ParseExpr("a", {"b" => "2"}, undef));
is("2", ParseExpr("a", {"a" => "2"}, undef));
is("2 * 2", ParseExpr("a*a", {"a" => "2"}, undef));
is("r->length + r->length",
ParseExpr("length+length", {"length" => "r->length"}, undef));
is("2 / 2 * (r->length)",
ParseExpr("constant/constant*(len)", {"constant" => "2",
"len" => "r->length"}, undef));
is("2 + 2 - r->length",
ParseExpr("constant+constant-len", {"constant" => "2",
"len" => "r->length"}, undef));
is("*r->length", ParseExpr("*len", { "len" => "r->length"}, undef));
is("**r->length", ParseExpr("**len", { "len" => "r->length"}, undef));
is("r->length & 2", ParseExpr("len&2", { "len" => "r->length"}, undef));
is("&r->length", ParseExpr("&len", { "len" => "r->length"}, undef));
is("calc()", ParseExpr("calc()", { "foo" => "2"}, undef));
is("calc(2 * 2)", ParseExpr("calc(foo * 2)", { "foo" => "2"}, undef));
is("strlen(\"data\")", ParseExpr("strlen(foo)", { "foo" => "\"data\""}, undef));
is("strlen(\"data\", 4)", ParseExpr("strlen(foo, 4)", { "foo" => "\"data\""}, undef));
is("foo / bar", ParseExpr("foo / bar", { "bla" => "\"data\""}, undef));
is("r->length % 2", ParseExpr("len%2", { "len" => "r->length"}, undef));
is("r->length == 2", ParseExpr("len==2", { "len" => "r->length"}, undef));
is("r->length != 2", ParseExpr("len!=2", { "len" => "r->length"}, undef));
is("pr->length", ParseExpr("pr->length", { "p" => "r"}, undef));
is("r->length", ParseExpr("p->length", { "p" => "r"}, undef));
is("_foo / bla32", ParseExpr("_foo / bla32", { "bla" => "\"data\""}, undef));
is("foo.bar.blah", ParseExpr("foo.blah", { "foo" => "foo.bar"}, undef));
is("\"bla\"", ParseExpr("\"bla\"", {}, undef));
is("1 << 2", ParseExpr("1 << 2", {}, undef));
is("1 >> 2", ParseExpr("1 >> 2", {}, undef));
is("0x200", ParseExpr("0x200", {}, undef));
is("2?3:0", ParseExpr("2?3:0", {}, undef));
is("~0", ParseExpr("~0", {}, undef));
is("b->a->a", ParseExpr("a->a->a", {"a" => "b"}, undef));
is("b.a.a", ParseExpr("a.a.a", {"a" => "b"}, undef));
test_errors("nofile:0: Parse error in `~' near `~'\n", sub {
is(undef, ParseExpr("~", {}, {FILE => "nofile", LINE => 0})); });
test_errors("nofile:0: Got pointer, expected integer\n", sub {
is(undef, ParseExprExt("foo", {}, {FILE => "nofile", LINE => 0},
undef, sub { my $x = shift;
error({FILE => "nofile", LINE => 0},
"Got pointer, expected integer");
return undef; }))});
is("b.a.a", ParseExpr("b.a.a", {"a" => "b"}, undef));
is("((rr_type) == NBT_QTYPE_NETBIOS)", ParseExpr("((rr_type)==NBT_QTYPE_NETBIOS)", {}, undef));
is("talloc_check_name", ParseExpr("talloc_check_name", {}, undef));
is("talloc_check_name()", ParseExpr("talloc_check_name()", {}, undef));
is("talloc_check_name(ndr)", ParseExpr("talloc_check_name(ndr)", {}, undef));
is("talloc_check_name(ndr, 1)", ParseExpr("talloc_check_name(ndr,1)", {}, undef));
is("talloc_check_name(ndr, \"struct ndr_push\")", ParseExpr("talloc_check_name(ndr,\"struct ndr_push\")", {}, undef));
is("((rr_type) == NBT_QTYPE_NETBIOS) && talloc_check_name(ndr, \"struct ndr_push\")", ParseExpr("((rr_type)==NBT_QTYPE_NETBIOS)&&talloc_check_name(ndr,\"struct ndr_push\")", {}, undef));
is("(rdata).data.length", ParseExpr("(rdata).data.length", {}, undef));
is("((rdata).data.length == 2)", ParseExpr("((rdata).data.length==2)", {}, undef));
is("((rdata).data.length == 2)?0:rr_type", ParseExpr("((rdata).data.length==2)?0:rr_type", {}, undef));
is("((((rr_type) == NBT_QTYPE_NETBIOS) && talloc_check_name(ndr, \"struct ndr_push\") && ((rdata).data.length == 2))?0:rr_type)", ParseExpr("((((rr_type)==NBT_QTYPE_NETBIOS)&&talloc_check_name(ndr,\"struct ndr_push\")&&((rdata).data.length==2))?0:rr_type)", {}, undef));

205
bin/pidl/tests/wireshark-conf.pl Executable file
View file

@ -0,0 +1,205 @@
#!/usr/bin/perl
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
# test parsing wireshark conformance files
use strict;
use warnings;
use Test::More tests => 49;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper);
use Parse::Pidl::Wireshark::Conformance qw(ReadConformanceFH valid_ft_type valid_base_type);
sub parse_conf($)
{
my $str = shift;
open(TMP, "+>", undef) or die("unable to open temp file");
print TMP $str;
seek(TMP, 0, 0);
my $data = {};
ReadConformanceFH(*TMP, $data, "nofile") or return undef;
close(TMP);
return $data;
}
ok(parse_conf("\n"), undef);
ok(parse_conf(" \n"), undef);
ok(parse_conf("CODE START\nCODE END\n"));
test_warnings("nofile:1: Expecting CODE END\n", sub { is(parse_conf("CODE START\n"), undef); });
ok(parse_conf("#foobar\n"), undef);
test_warnings("nofile:1: Unknown command `foobar'\n",
sub { ok(parse_conf("foobar\n"), undef); });
test_warnings("nofile:1: incomplete HF_RENAME command\n",
sub { parse_conf("HF_RENAME\n"); });
is_deeply(parse_conf("HF_RENAME foo bar\n")->{hf_renames}->{foo},
{ OLDNAME => "foo", NEWNAME => "bar", POS => {FILE => "nofile", LINE => 1}, USED => 0});
is_deeply(parse_conf("NOEMIT\n"), { "noemit_dissector" => 1 });
is_deeply(parse_conf("NOEMIT foo\n"), { "noemit" => { "foo" => 1 } });
test_warnings("nofile:1: incomplete MANUAL command\n",
sub { parse_conf("MANUAL\n"); } );
is_deeply(parse_conf("MANUAL foo\n"), { manual => {foo => 1}});
test_errors("nofile:1: incomplete INCLUDE command\n",
sub { parse_conf("INCLUDE\n"); } );
test_warnings("nofile:1: incomplete FIELD_DESCRIPTION command\n",
sub { parse_conf("FIELD_DESCRIPTION foo\n"); });
is_deeply(parse_conf("FIELD_DESCRIPTION foo \"my description\"\n"),
{ fielddescription => { foo => { DESCRIPTION => "\"my description\"", POS => { FILE => "nofile", LINE => 1}, USED => 0 }}});
is_deeply(parse_conf("FIELD_DESCRIPTION foo my description\n"),
{ fielddescription => { foo => { DESCRIPTION => "my", POS => { FILE => "nofile", LINE => 1}, USED => 0 }}});
is_deeply(parse_conf("CODE START\ndata\nCODE END\n"), { override => "data\n" });
is_deeply(parse_conf("CODE START\ndata\nmore data\nCODE END\n"), { override => "data\nmore data\n" });
test_warnings("nofile:1: Unknown command `CODE'\n",
sub { parse_conf("CODE END\n"); } );
is_deeply(parse_conf("TYPE winreg_String dissect_myminregstring(); FT_STRING BASE_DEC 0 0 2\n"), { types => { winreg_String => {
NAME => "winreg_String",
POS => { FILE => "nofile", LINE => 1 },
USED => 0,
DISSECTOR_NAME => "dissect_myminregstring();",
FT_TYPE => "FT_STRING",
BASE_TYPE => "BASE_DEC",
MASK => 0,
VALSSTRING => 0,
ALIGNMENT => 2}}});
ok(valid_ft_type("FT_UINT32"));
ok(not valid_ft_type("BLA"));
ok(not valid_ft_type("ft_uint32"));
ok(valid_ft_type("FT_BLA"));
ok(valid_base_type("BASE_DEC"));
ok(valid_base_type("BASE_HEX"));
ok(not valid_base_type("base_dec"));
ok(not valid_base_type("BLA"));
ok(not valid_base_type("BASEDEC"));
test_errors("nofile:1: incomplete TYPE command\n",
sub { parse_conf("TYPE mytype dissector\n"); });
test_warnings("nofile:1: dissector name does not contain `dissect'\n",
sub { parse_conf("TYPE winreg_String myminregstring; FT_STRING BASE_DEC 0 0 2\n"); });
test_warnings("nofile:1: invalid FT_TYPE `BLA'\n",
sub { parse_conf("TYPE winreg_String dissect_myminregstring; BLA BASE_DEC 0 0 2\n"); });
test_warnings("nofile:1: invalid BASE_TYPE `BLOE'\n",
sub { parse_conf("TYPE winreg_String dissect_myminregstring; FT_UINT32 BLOE 0 0 2\n"); });
is_deeply(parse_conf("TFS hf_bla \"True string\" \"False String\"\n"),
{ tfs => { hf_bla => {
TRUE_STRING => "\"True string\"",
FALSE_STRING => "\"False String\"" } } });
test_errors("nofile:1: incomplete TFS command\n",
sub { parse_conf("TFS hf_bla \"Trues\""); } );
test_errors("nofile:1: incomplete PARAM_VALUE command\n",
sub { parse_conf("PARAM_VALUE\n"); });
is_deeply(parse_conf("PARAM_VALUE Life 42\n"),
{ dissectorparams => {
Life => {
DISSECTOR => "Life",
POS => { FILE => "nofile", LINE => 1 },
PARAM => 42,
USED => 0
}
}
});
is_deeply(parse_conf("STRIP_PREFIX bla_\n"),
{ strip_prefixes => [ "bla_" ] });
is_deeply(parse_conf("STRIP_PREFIX bla_\nSTRIP_PREFIX bloe\n"),
{ strip_prefixes => [ "bla_", "bloe" ] });
is_deeply(parse_conf("PROTOCOL atsvc \"Scheduling jobs on remote machines\" \"at\" \"atsvc\"\n"),
{ protocols => {
atsvc => {
LONGNAME => "\"Scheduling jobs on remote machines\"",
SHORTNAME => "\"at\"",
FILTERNAME => "\"atsvc\""
}
}
}
);
is_deeply(parse_conf("IMPORT bla\n"), {
imports => {
bla => {
NAME => "bla",
DATA => "",
USED => 0,
POS => { FILE => "nofile", LINE => 1 }
}
}
}
);
is_deeply(parse_conf("IMPORT bla fn1 fn2 fn3\n"), {
imports => {
bla => {
NAME => "bla",
DATA => "fn1 fn2 fn3",
USED => 0,
POS => { FILE => "nofile", LINE => 1 }
}
}
}
);
test_errors("nofile:1: no dissectorname specified\n",
sub { parse_conf("IMPORT\n"); } );
test_errors("nofile:1: incomplete HF_FIELD command\n",
sub { parse_conf("HF_FIELD hf_idx\n"); });
test_errors("nofile:1: incomplete ETT_FIELD command\n",
sub { parse_conf("ETT_FIELD\n"); });
is_deeply(parse_conf("TYPE winreg_String dissect_myminregstring(); FT_STRING BASE_DEC 0 0 0 2\n"), {
types => {
winreg_String => {
NAME => "winreg_String",
POS => { FILE => "nofile", LINE => 1 },
USED => 0,
DISSECTOR_NAME => "dissect_myminregstring();",
FT_TYPE => "FT_STRING",
BASE_TYPE => "BASE_DEC",
MASK => 0,
VALSSTRING => 0,
ALIGNMENT => 0
}
}
}
);
is_deeply(parse_conf("TYPE winreg_String \"offset = dissect_myminregstring(\@HF\@);\" FT_STRING BASE_DEC 0 0 0 2\n"), {
types => {
winreg_String => {
NAME => "winreg_String",
POS => { FILE => "nofile", LINE => 1 },
USED => 0,
DISSECTOR_NAME => "offset = dissect_myminregstring(\@HF\@);",
FT_TYPE => "FT_STRING",
BASE_TYPE => "BASE_DEC",
MASK => 0,
VALSSTRING => 0,
ALIGNMENT => 0
}
}
}
);

274
bin/pidl/tests/wireshark-ndr.pl Executable file
View file

@ -0,0 +1,274 @@
#!/usr/bin/perl
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
# test parsing wireshark conformance files
use strict;
use warnings;
use Test::More tests => 40;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper);
use strict;
use Parse::Pidl::Wireshark::NDR qw(field2name %res PrintIdl StripPrefixes RegisterInterfaceHandoff register_hf_field ProcessImport ProcessInclude find_type DumpEttList DumpEttDeclaration DumpHfList DumpHfDeclaration DumpFunctionTable register_type register_ett);
is("Access Mask", field2name("access_mask"));
is("Accessmask", field2name("AccessMask"));
my $x = new Parse::Pidl::Wireshark::NDR();
$x->PrintIdl("foo\nbar\n");
is("/* IDL: foo */
/* IDL: bar */
", $x->{res}->{code});
is("bla_foo", StripPrefixes("bla_foo", []));
is("foo", StripPrefixes("bla_foo", ["bla"]));
is("foo_bla", StripPrefixes("foo_bla", ["bla"]));
$x = new Parse::Pidl::Wireshark::NDR();
$x->RegisterInterfaceHandoff({});
is($x->{res}->{code}, "");
ok(not defined($x->{hf_used}->{hf_bla_opnum}));
$x = new Parse::Pidl::Wireshark::NDR();
$x->{res}->{code} = "";
$x->RegisterInterfaceHandoff({UUID => "uuid", NAME => "bla"});
is($x->{res}->{code}, 'void proto_reg_handoff_dcerpc_bla(void)
{
dcerpc_init_uuid(proto_dcerpc_bla, ett_dcerpc_bla,
&uuid_dcerpc_bla, ver_dcerpc_bla,
bla_dissectors, hf_bla_opnum);
}
');
is($x->{hf_used}->{hf_bla_opnum}, 1);
$x->{conformance} = {};
is("hf_bla_idx",
$x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF, undef));
is_deeply($x->{conformance}, {
header_fields => {
"hf_bla_idx" => {
INDEX => "hf_bla_idx",
NAME => "bla",
FILTER => "my.filter",
BASE_TYPE => "BASE_HEX",
FT_TYPE => "FT_UINT32",
VALSSTRING => "NULL",
BLURB => undef,
MASK => 0xF
}
},
hf_renames => {},
fielddescription => {}
});
$x->{conformance} = { fielddescription => { hf_bla_idx => { DESCRIPTION => "Some Description" }}};
is("hf_bla_idx",
$x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF, undef));
is_deeply($x->{conformance}, {
fielddescription => {
hf_bla_idx => {
DESCRIPTION => "Some Description",
USED => 1
}
},
header_fields => {
"hf_bla_idx" => {
INDEX => "hf_bla_idx",
NAME => "bla",
FILTER => "my.filter",
BASE_TYPE => "BASE_HEX",
FT_TYPE => "FT_UINT32",
VALSSTRING => "NULL",
BLURB => "Some Description",
MASK => 0xF
}
},
hf_renames => {},
});
$x->{conformance} = { fielddescription => { hf_bla_idx => { DESCRIPTION => "Some Description" }}};
is("hf_bla_idx",
$x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF,
"Actual Description"));
is_deeply($x->{conformance}, {
fielddescription => {
hf_bla_idx => { DESCRIPTION => "Some Description" }
},
header_fields => {
"hf_bla_idx" => {
INDEX => "hf_bla_idx",
NAME => "bla",
FILTER => "my.filter",
BASE_TYPE => "BASE_HEX",
FT_TYPE => "FT_UINT32",
VALSSTRING => "NULL",
BLURB => "Actual Description",
MASK => 0xF
}
},
hf_renames => {},
});
$x->{conformance} = { hf_renames => { "hf_bla_idx" => { NEWNAME => "hf_bloe_idx" } } };
$x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF, undef);
is_deeply($x->{conformance}, {
hf_renames => { hf_bla_idx => { USED => 1, NEWNAME => "hf_bloe_idx" } } });
$x->{hf_used} = { hf_bla => 1 };
test_warnings("", sub {
$x->CheckUsed({ header_fields => { foo => { INDEX => "hf_bla" }}})});
$x->{hf_used} = { };
test_warnings("hf field `hf_bla' not used\n", sub {
$x->CheckUsed({ header_fields => { foo => { INDEX => "hf_bla" }}})});
test_warnings("hf field `hf_id' not used\n",
sub { $x->CheckUsed({
hf_renames => {
hf_id => {
OLDNAME => "hf_id",
NEWNAME => "hf_newid",
USED => 0
}
}
}); } );
test_warnings("dissector param never used\n",
sub { $x->CheckUsed({
dissectorparams => {
dissect_foo => {
PARAM => 42,
USED => 0
}
}
}); } );
test_warnings("description never used\n",
sub { $x->CheckUsed({
fielddescription => {
hf_bla => {
USED => 0
}
}
}); } );
test_warnings("import never used\n",
sub { $x->CheckUsed({
imports => {
bla => {
USED => 0
}
}
}); } );
test_warnings("nofile:1: type never used\n",
sub { $x->CheckUsed({
types => {
bla => {
USED => 0,
POS => { FILE => "nofile", LINE => 1 }
}
}
}); } );
test_warnings("True/False description never used\n",
sub { $x->CheckUsed({
tfs => {
hf_bloe => {
USED => 0
}
}
}); } );
$x = new Parse::Pidl::Wireshark::NDR();
$x->ProcessImport("security", "bla");
is($x->{res}->{hdr}, "#include \"packet-dcerpc-bla.h\"\n\n");
$x = new Parse::Pidl::Wireshark::NDR();
$x->ProcessImport("\"bla.idl\"", "\"foo.idl\"");
is($x->{res}->{hdr}, "#include \"packet-dcerpc-bla.h\"\n" .
"#include \"packet-dcerpc-foo.h\"\n\n");
$x = new Parse::Pidl::Wireshark::NDR();
$x->ProcessInclude("foo.h", "bla.h", "bar.h");
is($x->{res}->{hdr}, "#include \"foo.h\"\n" .
"#include \"bla.h\"\n" .
"#include \"bar.h\"\n\n");
$x->{conformance} = {types => { bla => "brainslug" } };
is("brainslug", $x->find_type("bla"));
is(DumpEttList(["ett_t1", "ett_bla"]),
"\tstatic gint *ett[] = {\n" .
"\t\t&ett_t1,\n" .
"\t\t&ett_bla,\n" .
"\t};\n");
is(DumpEttList(), "\tstatic gint *ett[] = {\n\t};\n");
is(DumpEttList(["bla"]), "\tstatic gint *ett[] = {\n\t\t&bla,\n\t};\n");
is(DumpEttDeclaration(["void", "zoid"]),
"\n/* Ett declarations */\n" .
"static gint void = -1;\n" .
"static gint zoid = -1;\n" .
"\n");
is(DumpEttDeclaration(), "\n/* Ett declarations */\n\n");
$x->{conformance} = {
header_fields => {
hf_bla => { INDEX => "hf_bla", NAME => "Bla", FILTER => "bla.field", FT_TYPE => "FT_UINT32", BASE_TYPE => "BASE_DEC", VALSSTRING => "NULL", MASK => 0xFF, BLURB => "NULL" }
}
};
is($x->DumpHfList(), "\tstatic hf_register_info hf[] = {
{ &hf_bla,
{ \"Bla\", \"bla.field\", FT_UINT32, BASE_DEC, NULL, 255, \"NULL\", HFILL }},
};
");
is($x->DumpHfDeclaration(), "
/* Header field declarations */
static gint hf_bla = -1;
");
is(DumpFunctionTable({
NAME => "someif",
FUNCTIONS => [ { NAME => "fn1", OPNUM => 3 }, { NAME => "someif_fn2", OPNUM => 2 } ] }),
'static dcerpc_sub_dissector someif_dissectors[] = {
{ 3, "fn1",
someif_dissect_fn1_request, someif_dissect_fn1_response},
{ 2, "fn2",
someif_dissect_fn2_request, someif_dissect_fn2_response},
{ 0, NULL, NULL, NULL }
};
');
$x->{conformance} = {};
$x->register_type("bla_type", "dissect_bla", "FT_UINT32", "BASE_HEX", 0xFF, "NULL", 4);
is_deeply($x->{conformance}, {
types => {
bla_type => {
NAME => "bla_type",
DISSECTOR_NAME => "dissect_bla",
FT_TYPE => "FT_UINT32",
BASE_TYPE => "BASE_HEX",
MASK => 255,
VALSSTRING => "NULL",
ALIGNMENT => 4
}
}
}
);
$x->{ett} = [];
$x->register_ett("name");
is_deeply($x->{ett}, ["name"]);
$x->register_ett("leela");
is_deeply($x->{ett}, ["name", "leela"]);