2007-01-10 02:41:25 +03:00
#!/usr/bin/perl
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU General Public License
use strict ;
use warnings ;
2008-04-06 02:57:14 +04:00
use Test::More tests = > 31 ;
2007-01-10 02:41:25 +03:00
use FindBin qw( $RealBin ) ;
use lib "$RealBin" ;
use Util ;
use Parse::Pidl::Util qw( MyDumper ) ;
2007-02-18 15:54:03 +03:00
use Parse::Pidl::Samba4::NDR::Parser qw( check_null_pointer
2008-01-13 20:15:12 +03:00
NeededFunction NeededElement NeededType
2007-03-02 17:05:52 +03:00
NeededInterface TypeFunctionName ParseElementPrint ) ;
2007-01-10 02:41:25 +03:00
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" }
] ,
} ,
]
}
2007-01-10 03:37:30 +03:00
} , { bla = > "r->in.bla" } , \ & print_fn , "return;" ) ;
2007-01-10 02:41:25 +03:00
test_warnings ( "" , sub { $ fn - > ( "r->in.bla" ) ; } ) ;
2007-01-10 03:37:30 +03:00
is ( $ output , "if (r->in.bla == NULL) return;" ) ;
2007-01-10 02:41:25 +03:00
# 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" }
] ,
} ,
]
}
2007-01-10 03:37:30 +03:00
} , { bla = > "r->in.bla" } , \ & print_fn , undef ) ;
2007-01-10 02:41:25 +03:00
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" }
] ,
} ,
]
}
2007-01-10 03:37:30 +03:00
} , { bla = > "r->in.bla" } , \ & print_fn , undef ) ;
2007-01-10 02:41:25 +03:00
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" }
] ,
} ,
]
}
2007-01-10 03:37:30 +03:00
} , { bla = > "r->in.bla" } , \ & print_fn , "return;" ) ;
2007-01-10 02:41:25 +03:00
test_warnings ( "" ,
sub { $ fn - > ( "*r->in.bla" ) ; } ) ;
2007-01-10 03:37:30 +03:00
is ( $ output , "if (*r->in.bla == NULL) return;" ) ;
2007-01-10 02:41:25 +03:00
# Test case 5: Unknown variable
$ output = "" ;
$ fn = check_null_pointer ( {
FILE = > "nofile" ,
LINE = > 2 ,
PARENT = > {
ELEMENTS = > [
{
NAME = > "bla" ,
LEVELS = > [
{ TYPE = > "DATA" }
] ,
} ,
]
}
2007-01-10 03:37:30 +03:00
} , { } , \ & print_fn , "return;" ) ;
2007-01-10 02:41:25 +03:00
test_warnings ( "nofile:2: unknown dereferenced expression `r->in.bla'\n" ,
sub { $ fn - > ( "r->in.bla" ) ; } ) ;
2007-01-10 03:37:30 +03:00
is ( $ output , "if (r->in.bla == NULL) return;" ) ;
2007-02-09 02:54:31 +03:00
2007-02-18 15:54:03 +03:00
my $ needed = { } ;
2007-02-18 16:44:01 +03:00
NeededElement ( { TYPE = > "foo" , REPRESENTATION_TYPE = > "foo" } , "pull" , $ needed ) ;
2007-02-28 04:51:37 +03:00
is_deeply ( $ needed , { ndr_pull_foo = > 1 } ) ;
2007-02-18 15:54:03 +03:00
# old settings should be kept
2007-02-28 04:51:37 +03:00
$ needed = { ndr_pull_foo = > 0 } ;
2007-02-18 16:44:01 +03:00
NeededElement ( { TYPE = > "foo" , REPRESENTATION_TYPE = > "foo" } , "pull" , $ needed ) ;
2007-02-28 04:51:37 +03:00
is_deeply ( $ needed , { ndr_pull_foo = > 0 } ) ;
2007-02-18 15:54:03 +03:00
# print/pull/push are independent of each other
2007-02-28 04:51:37 +03:00
$ needed = { ndr_pull_foo = > 0 } ;
2007-02-18 16:44:01 +03:00
NeededElement ( { TYPE = > "foo" , REPRESENTATION_TYPE = > "foo" } , "print" , $ needed ) ;
2007-02-28 04:51:37 +03:00
is_deeply ( $ needed , { ndr_pull_foo = > 0 , ndr_print_foo = > 1 } ) ;
2007-02-18 15:54:03 +03:00
$ needed = { } ;
2007-02-18 16:44:01 +03:00
NeededFunction ( { NAME = > "foo" , ELEMENTS = > [ { TYPE = > "bar" , REPRESENTATION_TYPE = > "bar" } ] } , $ needed ) ;
2007-02-28 04:51:37 +03:00
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 } ) ;
2007-02-18 15:54:03 +03:00
# push/pull/print are always set for functions
2007-02-28 04:51:37 +03:00
$ needed = { ndr_pull_foo = > 0 } ;
2007-02-18 16:44:01 +03:00
NeededFunction ( { NAME = > "foo" , ELEMENTS = > [ { TYPE = > "bar" , REPRESENTATION_TYPE = > "bar" } ] } , $ needed ) ;
2007-02-28 04:51:37 +03:00
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 } ) ;
2007-02-18 15:54:03 +03:00
# public structs are always needed
$ needed = { } ;
2007-02-21 13:31:14 +03:00
NeededType ( { NAME = > "bla" , TYPE = > "TYPEDEF" ,
DATA = > { TYPE = > "STRUCT" , ELEMENTS = > [] } } ,
$ needed , "pull" ) ;
2007-02-18 15:54:03 +03:00
is_deeply ( $ needed , { } ) ;
$ needed = { } ;
2007-02-21 13:31:14 +03:00
NeededInterface ( { TYPES = > [ { PROPERTIES = > { public = > 1 } , NAME = > "bla" ,
TYPE = > "TYPEDEF" ,
DATA = > { TYPE = > "STRUCT" , ELEMENTS = > [] } } ] } ,
2007-02-18 15:54:03 +03:00
$ needed ) ;
2007-02-28 04:51:37 +03:00
is_deeply ( $ needed , { ndr_pull_bla = > 1 , ndr_push_bla = > 1 , ndr_print_bla = > 1 } ) ;
2007-02-18 15:54:03 +03:00
# make sure types for elements are set too
$ needed = { } ;
2007-02-21 13:31:14 +03:00
NeededInterface ( { TYPES = > [ { PROPERTIES = > { public = > 1 } , NAME = > "bla" ,
TYPE = > "TYPEDEF" ,
2007-02-18 15:54:03 +03:00
DATA = > { TYPE = > "STRUCT" ,
2007-02-21 13:31:14 +03:00
ELEMENTS = > [ { TYPE = > "bar" , REPRESENTATION_TYPE = > "bar" } ] } } ] } ,
2007-02-18 15:54:03 +03:00
$ needed ) ;
2007-02-28 04:51:37 +03:00
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 } ) ;
2007-02-18 15:54:03 +03:00
$ needed = { } ;
2007-02-21 13:31:14 +03:00
NeededInterface ( { TYPES = > [ { PROPERTIES = > { gensize = > 1 } , NAME = > "bla" ,
TYPE = > "TYPEDEF" ,
2007-02-18 15:54:03 +03:00
DATA = > { TYPE = > "STRUCT" ,
2007-02-21 13:31:14 +03:00
ELEMENTS = > [ { TYPE = > "bar" , REPRESENTATION_TYPE = > "bar" } ] } } ] } ,
2007-02-18 15:54:03 +03:00
$ needed ) ;
is_deeply ( $ needed , { ndr_size_bla = > 1 } ) ;
2007-02-18 16:44:01 +03:00
# make sure types for elements are set too
2007-02-28 04:51:37 +03:00
$ needed = { ndr_pull_bla = > 1 } ;
2007-02-18 19:21:28 +03:00
NeededType ( { NAME = > "bla" ,
2007-02-21 13:31:14 +03:00
TYPE = > "TYPEDEF" ,
2007-02-18 16:44:01 +03:00
DATA = > { TYPE = > "STRUCT" ,
ELEMENTS = > [ { TYPE = > "bar" , REPRESENTATION_TYPE = > "bar" } ] } } ,
2007-02-21 13:31:14 +03:00
$ needed , "pull" ) ;
2007-02-28 04:51:37 +03:00
is_deeply ( $ needed , { ndr_pull_bla = > 1 , ndr_pull_bar = > 1 } ) ;
2007-02-18 16:44:01 +03:00
$ needed = { } ;
2007-02-21 13:31:14 +03:00
NeededInterface ( { TYPES = > [ { PROPERTIES = > { public = > 1 } ,
2007-02-18 16:44:01 +03:00
NAME = > "bla" ,
2007-02-21 13:31:14 +03:00
TYPE = > "TYPEDEF" ,
2007-02-18 16:44:01 +03:00
DATA = > { TYPE = > "STRUCT" ,
2007-02-21 13:31:14 +03:00
ELEMENTS = > [ { TYPE = > "bar" , REPRESENTATION_TYPE = > "rep" } ] } } ] } , $ needed ) ;
2007-02-28 04:51:37 +03:00
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 ,
2007-02-18 16:44:01 +03:00
ndr_bar_to_rep = > 1 , ndr_rep_to_bar = > 1 } ) ;
2007-04-22 19:59:34 +04:00
my $ generator = new Parse::Pidl::Samba4::NDR:: Parser ( ) ;
$ generator - > ParseStructPush ( {
2007-02-19 22:42:51 +03:00
NAME = > "mystruct" ,
TYPE = > "STRUCT" ,
PROPERTIES = > { } ,
ALIGN = > 4 ,
2008-08-19 15:24:05 +04:00
ELEMENTS = > [ ] } , "ndr" , "x" ) ;
2011-09-07 11:12:37 +04:00
is ( $ generator - > { res } , " NDR_PUSH_CHECK_FLAGS ( ndr , ndr_flags ) ;
if ( ndr_flags & NDR_SCALARS ) {
2007-02-19 22:42:51 +03:00
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
2009-10-02 11:14:15 +04:00
NDR_CHECK ( ndr_push_trailer_align ( ndr , 4 ) ) ;
2007-02-19 22:42:51 +03:00
}
if ( ndr_flags & NDR_BUFFERS ) {
}
" ) ;
2007-04-22 19:59:34 +04:00
$ generator = new Parse::Pidl::Samba4::NDR:: Parser ( ) ;
2007-02-19 22:42:51 +03:00
my $ e = {
NAME = > "el1" ,
TYPE = > "mytype" ,
REPRESENTATION_TYPE = > "mytype" ,
PROPERTIES = > { } ,
LEVELS = > [
{ LEVEL_INDEX = > 0 , TYPE = > "DATA" , DATA_TYPE = > "mytype" }
] } ;
2007-04-22 19:59:34 +04:00
$ generator - > ParseStructPush ( {
2007-02-19 22:42:51 +03:00
NAME = > "mystruct" ,
TYPE = > "STRUCT" ,
PROPERTIES = > { } ,
ALIGN = > 4 ,
SURROUNDING_ELEMENT = > $ e ,
2008-08-19 15:24:05 +04:00
ELEMENTS = > [ $ e ] } , "ndr" , "x" ) ;
2011-09-07 11:12:37 +04:00
is ( $ generator - > { res } , " NDR_PUSH_CHECK_FLAGS ( ndr , ndr_flags ) ;
if ( ndr_flags & NDR_SCALARS ) {
2009-09-19 22:06:46 +04:00
NDR_CHECK ( ndr_push_uint3264 ( ndr , NDR_SCALARS , ndr_string_array_size ( ndr , x - > el1 ) ) ) ;
2007-02-19 22:42:51 +03:00
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_push_mytype ( ndr , NDR_SCALARS , & x - > el1 ) ) ;
2009-10-02 11:14:15 +04:00
NDR_CHECK ( ndr_push_trailer_align ( ndr , 4 ) ) ;
2007-02-19 22:42:51 +03:00
}
if ( ndr_flags & NDR_BUFFERS ) {
}
" ) ;
2007-02-28 04:51:37 +03:00
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" ) ;
2007-03-02 17:05:52 +03:00
# check noprint works
2007-04-22 19:59:34 +04:00
$ generator = new Parse::Pidl::Samba4::NDR:: Parser ( ) ;
$ generator - > ParseElementPrint ( { NAME = > "x" , TYPE = > "rt" , REPRESENTATION_TYPE = > "rt" ,
2007-03-02 17:05:52 +03:00
PROPERTIES = > { noprint = > 1 } ,
2008-08-19 22:12:03 +04:00
LEVELS = > [ { TYPE = > "DATA" , DATA_TYPE = > "rt" } ] } ,
"ndr" , "var" , { "x" = > "r->foobar" } ) ;
2007-04-22 19:59:34 +04:00
is ( $ generator - > { res } , "" ) ;
2007-03-02 17:05:52 +03:00
2007-04-22 19:59:34 +04:00
$ generator = new Parse::Pidl::Samba4::NDR:: Parser ( ) ;
$ generator - > ParseElementPrint ( { NAME = > "x" , TYPE = > "rt" , REPRESENTATION_TYPE = > "rt" ,
2007-03-02 17:05:52 +03:00
PROPERTIES = > { } ,
2008-08-19 22:12:03 +04:00
LEVELS = > [ { TYPE = > "DATA" , DATA_TYPE = > "rt" } ] } ,
"ndr" , "var" , { "x" = > "r->foobar" } ) ;
2007-04-22 19:59:34 +04:00
is ( $ generator - > { res } , "ndr_print_rt(ndr, \"x\", &var);\n" ) ;
2007-03-02 17:05:52 +03:00
# make sure that a print function for an element with value() set works
2007-04-22 19:59:34 +04:00
$ generator = new Parse::Pidl::Samba4::NDR:: Parser ( ) ;
$ generator - > ParseElementPrint ( { NAME = > "x" , TYPE = > "uint32" , REPRESENTATION_TYPE = > "uint32" ,
2007-03-02 17:05:52 +03:00
PROPERTIES = > { value = > "23" } ,
2008-08-19 22:12:03 +04:00
LEVELS = > [ { TYPE = > "DATA" , DATA_TYPE = > "uint32" } ] } ,
"ndr" , "var" , { "x" = > "r->foobar" } ) ;
2007-04-22 19:59:34 +04:00
is ( $ generator - > { res } , "ndr_print_uint32(ndr, \"x\", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?23:var);\n" ) ;
2008-04-06 02:57:14 +04:00
$ 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
} ;
" ) ;