2006-03-17 19:27:22 +03:00
/*
Unix SMB / CIFS implementation .
SMB torture tester
Copyright ( C ) Andrew Tridgell 1997 - 2003
Copyright ( C ) Jelmer Vernooij 2006
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "lib/cmdline/popt_common.h"
# include "system/time.h"
# include "system/wait.h"
# include "system/filesys.h"
2006-10-30 04:19:31 +03:00
# include "system/readline.h"
# include "lib/smbreadline/smbreadline.h"
2006-03-17 19:27:22 +03:00
# include "libcli/libcli.h"
# include "lib/ldb/include/ldb.h"
# include "lib/events/events.h"
2006-10-17 00:05:19 +04:00
# include "dynconfig.h"
2006-03-17 19:27:22 +03:00
# include "torture/torture.h"
# include "build.h"
2006-08-30 15:29:34 +04:00
# include "lib/util/dlinklist.h"
2006-03-18 18:42:57 +03:00
# include "librpc/rpc/dcerpc.h"
2006-03-17 19:27:22 +03:00
2006-10-16 17:06:41 +04:00
static bool run_matching ( struct torture_context * torture ,
const char * prefix ,
const char * expr ,
struct torture_suite * suite ,
bool * matched )
{
bool ret = true ;
if ( suite = = NULL ) {
2006-10-17 03:09:15 +04:00
struct torture_suite * o ;
2006-10-16 17:06:41 +04:00
2006-10-17 03:09:15 +04:00
for ( o = torture_root - > children ; o ; o = o - > next ) {
if ( gen_fnmatch ( expr , o - > name ) = = 0 ) {
2006-10-16 17:06:41 +04:00
* matched = true ;
init_iconv ( ) ;
2006-10-17 03:09:15 +04:00
ret & = torture_run_suite ( torture , o ) ;
2006-10-16 17:06:41 +04:00
continue ;
}
2006-10-18 02:06:43 +04:00
ret & = run_matching ( torture , o - > name , expr , o , matched ) ;
2006-10-16 17:06:41 +04:00
}
} else {
char * name ;
struct torture_suite * c ;
struct torture_tcase * t ;
for ( c = suite - > children ; c ; c = c - > next ) {
asprintf ( & name , " %s-%s " , prefix , c - > name ) ;
if ( gen_fnmatch ( expr , name ) = = 0 ) {
* matched = true ;
init_iconv ( ) ;
ret & = torture_run_suite ( torture , c ) ;
free ( name ) ;
continue ;
}
ret & = run_matching ( torture , name , expr , c , matched ) ;
free ( name ) ;
}
for ( t = suite - > testcases ; t ; t = t - > next ) {
asprintf ( & name , " %s-%s " , prefix , t - > name ) ;
if ( gen_fnmatch ( expr , name ) = = 0 ) {
* matched = true ;
init_iconv ( ) ;
ret & = torture_run_tcase ( torture , t ) ;
}
free ( name ) ;
}
}
return ret ;
}
2006-03-17 19:27:22 +03:00
# define MAX_COLS 80 /* FIXME: Determine this at run-time */
/****************************************************************************
run a specified test or " ALL "
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-10-16 17:06:41 +04:00
static bool run_test ( struct torture_context * torture , const char * name )
2006-03-17 19:27:22 +03:00
{
2006-10-16 17:06:41 +04:00
bool ret = true ;
bool matched = false ;
2006-10-17 03:09:15 +04:00
struct torture_suite * o ;
2006-03-17 19:27:22 +03:00
2006-10-16 17:06:41 +04:00
if ( strequal ( name , " ALL " ) ) {
2006-10-17 03:09:15 +04:00
for ( o = torture_root - > children ; o ; o = o - > next ) {
ret & = torture_run_suite ( torture , o ) ;
2006-03-17 19:27:22 +03:00
}
return ret ;
}
2006-10-16 17:06:41 +04:00
ret = run_matching ( torture , NULL , name , NULL , & matched ) ;
2006-03-17 19:27:22 +03:00
if ( ! matched ) {
printf ( " Unknown torture operation '%s' \n " , name ) ;
2006-10-16 17:06:41 +04:00
return false ;
2006-03-17 19:27:22 +03:00
}
return ret ;
}
static void parse_dns ( const char * dns )
{
char * userdn , * basedn , * secret ;
char * p , * d ;
/* retrievieng the userdn */
p = strchr_m ( dns , ' # ' ) ;
if ( ! p ) {
lp_set_cmdline ( " torture:ldap_userdn " , " " ) ;
lp_set_cmdline ( " torture:ldap_basedn " , " " ) ;
lp_set_cmdline ( " torture:ldap_secret " , " " ) ;
return ;
}
userdn = strndup ( dns , p - dns ) ;
lp_set_cmdline ( " torture:ldap_userdn " , userdn ) ;
/* retrieve the basedn */
d = p + 1 ;
p = strchr_m ( d , ' # ' ) ;
if ( ! p ) {
lp_set_cmdline ( " torture:ldap_basedn " , " " ) ;
lp_set_cmdline ( " torture:ldap_secret " , " " ) ;
return ;
}
basedn = strndup ( d , p - d ) ;
lp_set_cmdline ( " torture:ldap_basedn " , basedn ) ;
/* retrieve the secret */
p = p + 1 ;
if ( ! p ) {
lp_set_cmdline ( " torture:ldap_secret " , " " ) ;
return ;
}
secret = strdup ( p ) ;
lp_set_cmdline ( " torture:ldap_secret " , secret ) ;
printf ( " %s - %s - %s \n " , userdn , basedn , secret ) ;
}
static void usage ( poptContext pc )
{
2006-10-17 03:09:15 +04:00
struct torture_suite * o ;
2006-10-16 17:06:41 +04:00
struct torture_suite * s ;
struct torture_tcase * t ;
2006-03-17 19:27:22 +03:00
int i ;
poptPrintUsage ( pc , stdout , 0 ) ;
printf ( " \n " ) ;
printf ( " The binding format is: \n \n " ) ;
printf ( " TRANSPORT:host[flags] \n \n " ) ;
2006-05-27 16:16:48 +04:00
printf ( " where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP \n " ) ;
printf ( " or ncalrpc for local connections. \n \n " ) ;
2006-03-17 19:27:22 +03:00
printf ( " 'host' is an IP or hostname or netbios name. If the binding string \n " ) ;
printf ( " identifies the server side of an endpoint, 'host' may be an empty \n " ) ;
printf ( " string. \n \n " ) ;
printf ( " 'flags' can include a SMB pipe name if using the ncacn_np transport or \n " ) ;
printf ( " a TCP port number if using the ncacn_ip_tcp transport, otherwise they \n " ) ;
printf ( " will be auto-determined. \n \n " ) ;
printf ( " other recognised flags are: \n \n " ) ;
printf ( " sign : enable ntlmssp signing \n " ) ;
printf ( " seal : enable ntlmssp sealing \n " ) ;
printf ( " connect : enable rpc connect level auth (auth, but no sign or seal) \n " ) ;
printf ( " validate: enable the NDR validator \n " ) ;
printf ( " print: enable debugging of the packets \n " ) ;
printf ( " bigendian: use bigendian RPC \n " ) ;
printf ( " padcheck: check reply data for non-zero pad bytes \n \n " ) ;
printf ( " For example, these all connect to the samr pipe: \n \n " ) ;
printf ( " ncacn_np:myserver \n " ) ;
printf ( " ncacn_np:myserver[samr] \n " ) ;
printf ( " ncacn_np:myserver[ \\ pipe \\ samr] \n " ) ;
printf ( " ncacn_np:myserver[/pipe/samr] \n " ) ;
printf ( " ncacn_np:myserver[samr,sign,print] \n " ) ;
printf ( " ncacn_np:myserver[ \\ pipe \\ samr,sign,seal,bigendian] \n " ) ;
printf ( " ncacn_np:myserver[/pipe/samr,seal,validate] \n " ) ;
printf ( " ncacn_np: \n " ) ;
printf ( " ncacn_np:[/pipe/samr] \n \n " ) ;
printf ( " ncacn_ip_tcp:myserver \n " ) ;
printf ( " ncacn_ip_tcp:myserver[1024] \n " ) ;
printf ( " ncacn_ip_tcp:myserver[1024,sign,seal] \n \n " ) ;
2006-05-27 16:16:48 +04:00
printf ( " ncalrpc: \n \n " ) ;
2006-04-19 07:06:50 +04:00
printf ( " The UNC format is: \n \n " ) ;
2006-03-17 19:27:22 +03:00
2006-04-19 07:06:50 +04:00
printf ( " //server/share \n \n " ) ;
2006-03-17 19:27:22 +03:00
2006-04-19 07:06:50 +04:00
printf ( " Tests are: " ) ;
2006-03-17 19:27:22 +03:00
2006-10-17 03:09:15 +04:00
for ( o = torture_root - > children ; o ; o = o - > next ) {
printf ( " \n %s (%s): \n " , o - > description , o - > name ) ;
2006-10-16 17:06:41 +04:00
i = 0 ;
2006-10-17 03:09:15 +04:00
for ( s = o - > children ; s ; s = s - > next ) {
if ( i + strlen ( o - > name ) + strlen ( s - > name ) > = ( MAX_COLS - 3 ) ) {
2006-10-16 17:06:41 +04:00
printf ( " \n " ) ;
2006-04-19 07:06:50 +04:00
i = 0 ;
}
2006-10-17 03:09:15 +04:00
i + = printf ( " %s-%s " , o - > name , s - > name ) ;
2006-04-19 07:06:50 +04:00
}
2006-10-17 03:09:15 +04:00
for ( t = o - > testcases ; t ; t = t - > next ) {
if ( i + strlen ( o - > name ) + strlen ( t - > name ) > = ( MAX_COLS - 3 ) ) {
2006-10-16 17:06:41 +04:00
printf ( " \n " ) ;
i = 0 ;
}
2006-10-17 03:09:15 +04:00
i + = printf ( " %s-%s " , o - > name , t - > name ) ;
2006-03-17 19:27:22 +03:00
}
2006-10-16 17:06:41 +04:00
if ( i ) printf ( " \n " ) ;
2006-03-17 19:27:22 +03:00
}
2006-10-16 17:06:41 +04:00
printf ( " \n The default test is ALL. \n " ) ;
2006-03-17 19:27:22 +03:00
exit ( 1 ) ;
}
2006-10-16 17:06:41 +04:00
static bool is_binding_string ( const char * binding_string )
2006-03-17 19:27:22 +03:00
{
2006-08-31 13:26:43 +04:00
TALLOC_CTX * mem_ctx = talloc_named_const ( NULL , 0 , " is_binding_string " ) ;
2006-03-17 19:27:22 +03:00
struct dcerpc_binding * binding_struct ;
NTSTATUS status ;
status = dcerpc_parse_binding ( mem_ctx , binding_string , & binding_struct ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_IS_OK ( status ) ;
}
static void max_runtime_handler ( int sig )
{
DEBUG ( 0 , ( " maximum runtime exceeded for smbtorture - terminating \n " ) ) ;
exit ( 1 ) ;
}
2006-06-17 04:17:50 +04:00
struct timeval last_suite_started ;
static void simple_suite_start ( struct torture_context * ctx ,
struct torture_suite * suite )
2006-03-25 22:12:08 +03:00
{
2006-06-17 04:17:50 +04:00
last_suite_started = timeval_current ( ) ;
printf ( " Running %s \n " , suite - > name ) ;
2006-03-25 22:12:08 +03:00
}
2006-06-17 04:17:50 +04:00
static void simple_suite_finish ( struct torture_context * ctx ,
struct torture_suite * suite )
2006-06-17 02:06:09 +04:00
{
2006-06-17 04:17:50 +04:00
printf ( " %s took %g secs \n \n " , suite - > name ,
timeval_elapsed ( & last_suite_started ) ) ;
2006-06-17 02:06:09 +04:00
}
static void simple_test_result ( struct torture_context * context ,
enum torture_result res , const char * reason )
2006-03-25 22:12:08 +03:00
{
2006-06-13 03:03:02 +04:00
switch ( res ) {
case TORTURE_OK :
if ( reason )
printf ( " OK: %s \n " , reason ) ;
break ;
case TORTURE_FAIL :
2006-06-17 04:17:50 +04:00
printf ( " TEST %s FAILED! - %s \n " , context - > active_test - > name , reason ) ;
2006-06-13 03:03:02 +04:00
break ;
2006-10-17 23:36:55 +04:00
case TORTURE_ERROR :
printf ( " ERROR IN TEST %s! - %s \n " , context - > active_test - > name , reason ) ;
break ;
2006-06-13 03:03:02 +04:00
case TORTURE_SKIP :
2006-06-17 02:06:09 +04:00
printf ( " SKIP: %s - %s \n " , context - > active_test - > name , reason ) ;
2006-06-13 03:03:02 +04:00
break ;
}
2006-03-25 22:12:08 +03:00
}
2006-10-16 17:06:41 +04:00
static void simple_comment ( struct torture_context * test ,
const char * comment )
2006-03-25 22:12:08 +03:00
{
2006-10-16 17:06:41 +04:00
printf ( " %s " , comment ) ;
2006-03-25 22:12:08 +03:00
}
const static struct torture_ui_ops std_ui_ops = {
. comment = simple_comment ,
2006-06-17 04:17:50 +04:00
. suite_start = simple_suite_start ,
. suite_finish = simple_suite_finish ,
2006-03-25 22:12:08 +03:00
. test_result = simple_test_result
} ;
2006-06-12 16:24:33 +04:00
2006-06-17 02:06:09 +04:00
static void subunit_test_start ( struct torture_context * ctx ,
struct torture_tcase * tcase ,
struct torture_test * test )
2006-06-12 16:24:33 +04:00
{
printf ( " test: %s \n " , test - > name ) ;
}
2006-06-17 02:06:09 +04:00
static void subunit_test_result ( struct torture_context * context ,
enum torture_result res , const char * reason )
2006-06-12 16:24:33 +04:00
{
switch ( res ) {
case TORTURE_OK :
2006-10-17 00:05:19 +04:00
printf ( " success: %s " , context - > active_test - > name ) ;
2006-06-12 16:24:33 +04:00
break ;
case TORTURE_FAIL :
2006-10-17 00:05:19 +04:00
printf ( " failure: %s " , context - > active_test - > name ) ;
2006-06-12 16:24:33 +04:00
break ;
2006-10-17 23:36:55 +04:00
case TORTURE_ERROR :
printf ( " error: %s " , context - > active_test - > name ) ;
break ;
2006-06-12 16:24:33 +04:00
case TORTURE_SKIP :
2006-10-17 00:05:19 +04:00
printf ( " skip: %s " , context - > active_test - > name ) ;
2006-06-12 16:24:33 +04:00
break ;
}
2006-10-17 00:05:19 +04:00
if ( reason )
printf ( " [ %s ] " , reason ) ;
printf ( " \n " ) ;
2006-06-12 16:24:33 +04:00
}
2006-10-16 17:06:41 +04:00
static void subunit_comment ( struct torture_context * test ,
const char * comment )
2006-06-12 16:24:33 +04:00
{
2006-10-17 00:05:19 +04:00
fprintf ( stderr , " %s " , comment ) ;
2006-06-12 16:24:33 +04:00
}
const static struct torture_ui_ops subunit_ui_ops = {
. comment = subunit_comment ,
. test_start = subunit_test_start ,
. test_result = subunit_test_result
} ;
2006-06-17 02:06:09 +04:00
static void harness_test_start ( struct torture_context * ctx ,
struct torture_tcase * tcase ,
struct torture_test * test )
2006-06-12 23:11:24 +04:00
{
}
2006-06-17 02:06:09 +04:00
static void harness_test_result ( struct torture_context * context ,
enum torture_result res , const char * reason )
2006-06-12 23:11:24 +04:00
{
switch ( res ) {
case TORTURE_OK :
2006-06-17 02:06:09 +04:00
printf ( " ok %s - %s \n " , context - > active_test - > name , reason ) ;
2006-06-12 23:11:24 +04:00
break ;
case TORTURE_FAIL :
2006-10-17 23:36:55 +04:00
case TORTURE_ERROR :
2006-06-17 02:06:09 +04:00
printf ( " not ok %s - %s \n " , context - > active_test - > name , reason ) ;
2006-06-12 23:11:24 +04:00
break ;
case TORTURE_SKIP :
2006-06-17 02:06:09 +04:00
printf ( " skip %s - %s \n " , context - > active_test - > name , reason ) ;
2006-06-12 23:11:24 +04:00
break ;
}
}
2006-10-16 17:06:41 +04:00
static void harness_comment ( struct torture_context * test ,
const char * comment )
2006-06-12 23:11:24 +04:00
{
printf ( " # %s \n " , comment ) ;
}
const static struct torture_ui_ops harness_ui_ops = {
. comment = harness_comment ,
. test_start = harness_test_start ,
. test_result = harness_test_result
} ;
2006-06-17 04:17:50 +04:00
static void quiet_suite_start ( struct torture_context * ctx ,
struct torture_suite * suite )
2006-06-17 03:10:15 +04:00
{
2006-10-16 17:06:41 +04:00
int i ;
ctx - > quiet = true ;
for ( i = 1 ; i < ctx - > level ; i + + ) putchar ( ' \t ' ) ;
2006-06-17 04:17:50 +04:00
printf ( " %s: " , suite - > name ) ;
2006-10-16 17:06:41 +04:00
fflush ( stdout ) ;
2006-06-17 04:17:50 +04:00
}
static void quiet_suite_finish ( struct torture_context * ctx ,
struct torture_suite * suite )
{
putchar ( ' \n ' ) ;
}
static void quiet_test_result ( struct torture_context * context ,
2006-10-16 17:06:41 +04:00
enum torture_result res , const char * reason )
2006-06-17 04:17:50 +04:00
{
2006-10-16 17:06:41 +04:00
fflush ( stdout ) ;
2006-06-17 04:17:50 +04:00
switch ( res ) {
case TORTURE_OK : putchar ( ' . ' ) ; break ;
2006-10-17 23:06:50 +04:00
case TORTURE_FAIL : putchar ( ' F ' ) ; break ;
2006-10-17 23:36:55 +04:00
case TORTURE_ERROR : putchar ( ' E ' ) ; break ;
2006-10-17 23:06:50 +04:00
case TORTURE_SKIP : putchar ( ' I ' ) ; break ;
2006-06-17 04:17:50 +04:00
}
2006-06-17 03:10:15 +04:00
}
const static struct torture_ui_ops quiet_ui_ops = {
2006-06-17 04:17:50 +04:00
. suite_start = quiet_suite_start ,
. suite_finish = quiet_suite_finish ,
. test_result = quiet_test_result
2006-06-17 03:10:15 +04:00
} ;
2006-10-30 14:34:59 +03:00
void run_recipe ( struct torture_context * tctx , const char * recipe )
{
int numlines , i , ret ;
char * * lines ;
lines = file_lines_load ( recipe , & numlines , NULL ) ;
if ( lines = = NULL ) {
fprintf ( stderr , " Unable to load file %s \n " , recipe ) ;
return ;
}
for ( i = 0 ; i < numlines ; i + + ) {
int argc ;
char * * argv ;
ret = poptParseArgvString ( lines [ i ] , & argc , & argv ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Error parsing line \n " ) ;
continue ;
}
run_test ( tctx , argv [ 0 ] ) ;
}
talloc_free ( lines ) ;
}
2006-10-30 04:19:31 +03:00
void run_shell ( struct torture_context * tctx )
{
char * cline ;
int argc ;
char * * argv ;
int ret ;
while ( 1 ) {
cline = smb_readline ( " torture> " , NULL , NULL ) ;
if ( cline = = NULL )
return ;
ret = poptParseArgvString ( cline , & argc , & argv ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Error parsing line \n " ) ;
continue ;
}
if ( ! strcmp ( argv [ 0 ] , " quit " ) ) {
return ;
} else if ( ! strcmp ( argv [ 0 ] , " set " ) ) {
if ( argc < 3 ) {
fprintf ( stderr , " Usage: set <variable> <value> \n " ) ;
} else {
char * name = talloc_asprintf ( NULL , " torture:%s " , argv [ 1 ] ) ;
lp_set_cmdline ( name , argv [ 2 ] ) ;
talloc_free ( name ) ;
}
} else if ( ! strcmp ( argv [ 0 ] , " help " ) ) {
fprintf ( stderr , " Available commands: \n "
" help - This help command \n "
" run - Run test \n "
" set - Change variables \n "
" \n " ) ;
} else if ( ! strcmp ( argv [ 0 ] , " run " ) ) {
if ( argc < 2 ) {
fprintf ( stderr , " Usage: run TEST-NAME [OPTIONS...] \n " ) ;
} else {
run_test ( tctx , argv [ 1 ] ) ;
}
}
}
}
2006-06-17 03:10:15 +04:00
2006-03-17 19:27:22 +03:00
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-10-30 04:19:31 +03:00
int main ( int argc , char * argv [ ] )
2006-03-17 19:27:22 +03:00
{
int opt , i ;
2006-10-16 17:06:41 +04:00
bool correct = true ;
2006-03-17 19:27:22 +03:00
int max_runtime = 0 ;
int argc_new ;
2006-03-25 22:12:08 +03:00
struct torture_context * torture ;
2006-10-18 02:06:43 +04:00
const struct torture_ui_ops * ui_ops ;
2006-03-17 19:27:22 +03:00
char * * argv_new ;
poptContext pc ;
2006-06-27 00:09:35 +04:00
static const char * target = " other " ;
2006-10-17 00:05:19 +04:00
const char * * subunit_dir ;
2006-10-30 04:19:31 +03:00
int shell = False ;
2006-06-17 02:06:09 +04:00
static const char * ui_ops_name = " simple " ;
2006-03-17 19:27:22 +03:00
enum { OPT_LOADFILE = 1000 , OPT_UNCLIST , OPT_TIMELIMIT , OPT_DNS ,
2006-05-05 13:52:12 +04:00
OPT_DANGEROUS , OPT_SMB_PORTS , OPT_ASYNC } ;
2006-03-17 19:27:22 +03:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2006-06-12 23:11:24 +04:00
{ " format " , 0 , POPT_ARG_STRING , & ui_ops_name , 0 , " Output format (one of: simple, subunit, harness) " , NULL } ,
2006-03-17 19:27:22 +03:00
{ " smb-ports " , ' p ' , POPT_ARG_STRING , NULL , OPT_SMB_PORTS , " SMB ports " , NULL } ,
{ " seed " , 0 , POPT_ARG_INT , & torture_seed , 0 , " seed " , NULL } ,
{ " num-ops " , 0 , POPT_ARG_INT , & torture_numops , 0 , " num ops " , NULL } ,
{ " entries " , 0 , POPT_ARG_INT , & torture_entries , 0 , " entries " , NULL } ,
{ " show-all " , 0 , POPT_ARG_NONE , & torture_showall , 0 , " show all " , NULL } ,
{ " loadfile " , 0 , POPT_ARG_STRING , NULL , OPT_LOADFILE , " loadfile " , NULL } ,
{ " unclist " , 0 , POPT_ARG_STRING , NULL , OPT_UNCLIST , " unclist " , NULL } ,
{ " timelimit " , ' t ' , POPT_ARG_STRING , NULL , OPT_TIMELIMIT , " timelimit " , NULL } ,
{ " failures " , ' f ' , POPT_ARG_INT , & torture_failures , 0 , " failures " , NULL } ,
{ " parse-dns " , ' D ' , POPT_ARG_STRING , NULL , OPT_DNS , " parse-dns " , NULL } ,
2006-05-05 13:52:12 +04:00
{ " dangerous " , ' X ' , POPT_ARG_NONE , NULL , OPT_DANGEROUS ,
" run dangerous tests (eg. wiping out password database) " , NULL } ,
2006-10-30 04:19:31 +03:00
{ " shell " , ' s ' , POPT_ARG_NONE , & shell , True , " Run shell " , NULL } ,
2006-09-12 11:35:04 +04:00
{ " target " , ' T ' , POPT_ARG_STRING , & target , 0 , " samba3|samba4|other " , NULL } ,
2006-05-05 13:52:12 +04:00
{ " async " , ' a ' , POPT_ARG_NONE , NULL , OPT_ASYNC ,
" run async tests " , NULL } ,
{ " num-async " , 0 , POPT_ARG_INT , & torture_numasync , 0 ,
" number of simultaneous async requests " , NULL } ,
2006-03-17 19:27:22 +03:00
{ " maximum-runtime " , 0 , POPT_ARG_INT , & max_runtime , 0 ,
" set maximum time for smbtorture to live " , " seconds " } ,
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
POPT_COMMON_VERSION
2006-09-06 16:28:01 +04:00
{ NULL }
2006-03-17 19:27:22 +03:00
} ;
2006-09-10 18:19:38 +04:00
setlinebuf ( stdout ) ;
2006-03-17 19:27:22 +03:00
/* we are never interested in SIGPIPE */
2006-10-30 14:34:59 +03:00
BlockSignals ( true , SIGPIPE ) ;
2006-03-17 19:27:22 +03:00
pc = poptGetContext ( " smbtorture " , argc , ( const char * * ) argv , long_options ,
POPT_CONTEXT_KEEP_FIRST ) ;
poptSetOtherOptionHelp ( pc , " <binding>|<unc> TEST1 TEST2 ... " ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case OPT_LOADFILE :
lp_set_cmdline ( " torture:loadfile " , poptGetOptArg ( pc ) ) ;
break ;
case OPT_UNCLIST :
lp_set_cmdline ( " torture:unclist " , poptGetOptArg ( pc ) ) ;
break ;
case OPT_TIMELIMIT :
lp_set_cmdline ( " torture:timelimit " , poptGetOptArg ( pc ) ) ;
break ;
case OPT_DNS :
parse_dns ( poptGetOptArg ( pc ) ) ;
break ;
case OPT_DANGEROUS :
lp_set_cmdline ( " torture:dangerous " , " Yes " ) ;
break ;
2006-05-05 13:52:12 +04:00
case OPT_ASYNC :
lp_set_cmdline ( " torture:async " , " Yes " ) ;
break ;
2006-03-17 19:27:22 +03:00
case OPT_SMB_PORTS :
lp_set_cmdline ( " smb ports " , poptGetOptArg ( pc ) ) ;
break ;
}
}
2006-10-17 16:06:20 +04:00
if ( strcmp ( target , " samba3 " ) = = 0 ) {
2006-10-18 18:23:19 +04:00
lp_set_cmdline ( " torture:samba3 " , " true " ) ;
2006-10-18 14:03:30 +04:00
lp_set_cmdline ( " torture:knownfail " , " samba3-knownfail " ) ;
2006-10-17 16:06:20 +04:00
} else if ( strcmp ( target , " samba4 " ) = = 0 ) {
2006-10-18 18:23:19 +04:00
lp_set_cmdline ( " torture:samba4 " , " true " ) ;
2006-10-18 14:03:30 +04:00
lp_set_cmdline ( " torture:knownfail " , " samba4-knownfail " ) ;
2006-10-17 16:06:20 +04:00
}
2006-03-17 19:27:22 +03:00
if ( max_runtime ) {
/* this will only work if nobody else uses alarm(),
which means it won ' t work for some tests , but we
can ' t use the event context method we use for smbd
as so many tests create their own event
context . This will at least catch most cases . */
signal ( SIGALRM , max_runtime_handler ) ;
alarm ( max_runtime ) ;
}
2006-04-07 22:02:51 +04:00
torture_init ( ) ;
2006-10-17 16:06:20 +04:00
ldb_global_init ( ) ;
2006-10-17 00:05:19 +04:00
subunit_dir = lp_parm_string_list ( - 1 , " torture " , " subunitdir " , " : " ) ;
if ( subunit_dir = = NULL )
2006-10-17 03:09:15 +04:00
torture_subunit_load_testsuites ( dyn_TORTUREDIR , true , NULL ) ;
2006-10-17 00:05:19 +04:00
else {
for ( i = 0 ; subunit_dir [ i ] ; i + + )
2006-10-17 03:09:15 +04:00
torture_subunit_load_testsuites ( subunit_dir [ i ] , true , NULL ) ;
2006-10-17 00:05:19 +04:00
}
2006-03-17 19:27:22 +03:00
if ( torture_seed = = 0 ) {
torture_seed = time ( NULL ) ;
}
printf ( " Using seed %d \n " , torture_seed ) ;
srandom ( torture_seed ) ;
argv_new = discard_const_p ( char * , poptGetArgs ( pc ) ) ;
argc_new = argc ;
for ( i = 0 ; i < argc ; i + + ) {
if ( argv_new [ i ] = = NULL ) {
argc_new = i ;
break ;
}
}
2006-10-30 04:19:31 +03:00
if ( ! ( argc_new > = 3 | | ( shell & & argc_new > = 2 ) ) ) {
2006-03-17 19:27:22 +03:00
usage ( pc ) ;
exit ( 1 ) ;
}
/* see if its a RPC transport specifier */
if ( is_binding_string ( argv_new [ 1 ] ) ) {
lp_set_cmdline ( " torture:binding " , argv_new [ 1 ] ) ;
} else {
char * binding = NULL ;
char * host = NULL , * share = NULL ;
if ( ! smbcli_parse_unc ( argv_new [ 1 ] , NULL , & host , & share ) ) {
d_printf ( " Invalid option: %s is not a valid torture target (share or binding string) \n \n " , argv_new [ 1 ] ) ;
usage ( pc ) ;
}
lp_set_cmdline ( " torture:host " , host ) ;
lp_set_cmdline ( " torture:share " , share ) ;
asprintf ( & binding , " ncacn_np:%s " , host ) ;
lp_set_cmdline ( " torture:binding " , binding ) ;
}
2006-06-12 16:24:33 +04:00
if ( ! strcmp ( ui_ops_name , " simple " ) ) {
2006-10-18 02:06:43 +04:00
ui_ops = & std_ui_ops ;
2006-06-12 16:24:33 +04:00
} else if ( ! strcmp ( ui_ops_name , " subunit " ) ) {
2006-10-18 02:06:43 +04:00
ui_ops = & subunit_ui_ops ;
2006-06-12 23:11:24 +04:00
} else if ( ! strcmp ( ui_ops_name , " harness " ) ) {
2006-10-18 02:06:43 +04:00
ui_ops = & harness_ui_ops ;
2006-06-17 03:10:15 +04:00
} else if ( ! strcmp ( ui_ops_name , " quiet " ) ) {
2006-10-18 02:06:43 +04:00
ui_ops = & quiet_ui_ops ;
2006-06-12 16:24:33 +04:00
} else {
printf ( " Unknown output format '%s' \n " , ui_ops_name ) ;
exit ( 1 ) ;
}
2006-03-25 22:12:08 +03:00
2006-10-18 14:03:30 +04:00
torture = torture_context_init ( talloc_autofree_context ( ) ,
lp_parm_string ( - 1 , " torture " , " knownfail " ) , ui_ops ) ;
2006-10-18 02:06:43 +04:00
2006-03-17 19:27:22 +03:00
if ( argc_new = = 0 ) {
printf ( " You must specify a test to run, or 'ALL' \n " ) ;
2006-10-30 04:19:31 +03:00
} else if ( shell ) {
run_shell ( torture ) ;
2006-03-17 19:27:22 +03:00
} else {
2006-06-17 04:56:17 +04:00
int total ;
double rate ;
2006-10-18 02:06:43 +04:00
int unexpected_failures ;
2006-03-17 19:27:22 +03:00
for ( i = 2 ; i < argc_new ; i + + ) {
2006-10-30 14:34:59 +03:00
if ( argv_new [ i ] [ 0 ] = = ' @ ' ) {
run_recipe ( torture , argv_new [ i ] + 1 ) ;
} else if ( ! run_test ( torture , argv_new [ i ] ) ) {
2006-10-16 17:06:41 +04:00
correct = false ;
2006-03-17 19:27:22 +03:00
}
}
2006-06-17 04:56:17 +04:00
2006-10-18 02:06:43 +04:00
unexpected_failures = str_list_length ( torture - > results . unexpected_failures ) ;
total = torture - > results . skipped + torture - > results . success + torture - > results . failed + torture - > results . errors ;
2006-10-16 17:06:41 +04:00
if ( total = = 0 ) {
printf ( " No tests run. \n " ) ;
} else {
2006-10-18 02:06:43 +04:00
rate = ( ( total - unexpected_failures - torture - > results . errors ) * ( 100.0 / total ) ) ;
printf ( " Tests: %d, Failures: %d " , total , torture - > results . failed ) ;
if ( torture - > results . failed - unexpected_failures ) {
printf ( " (%d expected) " , torture - > results . failed - unexpected_failures ) ;
}
printf ( " , Errors: %d, Skipped: %d. Success rate: %.2f%% \n " ,
torture - > results . errors , torture - > results . skipped , rate ) ;
}
if ( unexpected_failures ) {
printf ( " The following tests failed: \n " ) ;
for ( i = 0 ; torture - > results . unexpected_failures [ i ] ; i + + ) {
printf ( " %s \n " , torture - > results . unexpected_failures [ i ] ) ;
}
printf ( " \n " ) ;
}
if ( str_list_length ( torture - > results . unexpected_errors ) ) {
printf ( " Errors occurred while running the following tests: \n " ) ;
for ( i = 0 ; torture - > results . unexpected_errors [ i ] ; i + + ) {
printf ( " %s \n " , torture - > results . unexpected_errors [ i ] ) ;
}
printf ( " \n " ) ;
}
if ( str_list_length ( torture - > results . unexpected_successes ) ) {
printf ( " The following tests were expected to fail but succeeded: \n " ) ;
for ( i = 0 ; torture - > results . unexpected_successes [ i ] ; i + + ) {
printf ( " %s \n " , torture - > results . unexpected_successes [ i ] ) ;
}
printf ( " \n " ) ;
2006-10-16 17:06:41 +04:00
}
2006-03-17 19:27:22 +03:00
}
2006-10-18 14:03:30 +04:00
if ( torture - > results . returncode ) {
2006-03-17 19:27:22 +03:00
return ( 0 ) ;
} else {
return ( 1 ) ;
}
}