1#!/usr/bin/env perl 2 3use strict; 4 5use Cwd qw(abs_path); 6use File::Spec; 7use Getopt::Long; 8use Test::Harness qw(&runtests $verbose); 9 10my $opts = {}; 11GetOptions($opts, 'h|help', 'C|class=s@', 'K|keep-tmpfiles', 'F|file-pattern=s', 12 'V|verbose'); 13 14if ($opts->{h}) { 15 usage(); 16} 17 18if ($opts->{K}) { 19 $ENV{KEEP_TMPFILES} = 1; 20} 21 22if ($opts->{V}) { 23 $ENV{TEST_VERBOSE} = 1; 24 $verbose = 1; 25} 26 27# We use this, rather than use(), since use() is equivalent to a BEGIN 28# block, and we want the module to be loaded at run-time. 29 30my $test_dir = (File::Spec->splitpath(abs_path(__FILE__)))[1]; 31push(@INC, "$test_dir/t/lib"); 32 33require ProFTPD::TestSuite::Utils; 34import ProFTPD::TestSuite::Utils qw(:testsuite); 35 36# This is to handle the case where this tests.pl script might be 37# being used to run test files other than those that ship with proftpd, 38# e.g. to run the tests that come with third-party modules. 39unless (defined($ENV{PROFTPD_TEST_BIN})) { 40 $ENV{PROFTPD_TEST_BIN} = File::Spec->catfile($test_dir, '..', 'proftpd'); 41} 42 43# Set this environment variable, for other test cases which may want to 44# know the directory, and not necessarily just the location of the uninstalled 45# `proftpd' binary. This is useful, for example, for using the utilities. 46$ENV{PROFTPD_TEST_PATH} = $test_dir; 47 48$| = 1; 49 50my $test_files; 51 52if (scalar(@ARGV) > 0) { 53 $test_files = [@ARGV]; 54 55} else { 56 $test_files = [qw( 57 t/http.t 58 t/smtp.t 59 t/ssh2.t 60 t/logins.t 61 t/commands/user.t 62 t/commands/pass.t 63 t/commands/pwd.t 64 t/commands/cwd.t 65 t/commands/cdup.t 66 t/commands/syst.t 67 t/commands/type.t 68 t/commands/mkd.t 69 t/commands/rmd.t 70 t/commands/dele.t 71 t/commands/mdtm.t 72 t/commands/size.t 73 t/commands/mode.t 74 t/commands/stru.t 75 t/commands/allo.t 76 t/commands/noop.t 77 t/commands/feat.t 78 t/commands/help.t 79 t/commands/quit.t 80 t/commands/rang.t 81 t/commands/rnfr.t 82 t/commands/rnto.t 83 t/commands/rest.t 84 t/commands/pasv.t 85 t/commands/epsv.t 86 t/commands/port.t 87 t/commands/eprt.t 88 t/commands/nlst.t 89 t/commands/list.t 90 t/commands/retr.t 91 t/commands/stor.t 92 t/commands/stou.t 93 t/commands/appe.t 94 t/commands/stat.t 95 t/commands/abor.t 96 t/commands/mlsd.t 97 t/commands/mlst.t 98 t/commands/mff.t 99 t/commands/mfmt.t 100 t/commands/opts.t 101 t/commands/host.t 102 t/commands/clnt.t 103 t/commands/site/chgrp.t 104 t/commands/site/chmod.t 105 t/config/accessdenymsg.t 106 t/config/accessgrantmsg.t 107 t/config/allowfilter.t 108 t/config/allowforeignaddress.t 109 t/config/allowoverwrite.t 110 t/config/anonrejectpasswords.t 111 t/config/anonrequirepassword.t 112 t/config/authaliasonly.t 113 t/config/authgroupfile.t 114 t/config/authorder.t 115 t/config/authuserfile.t 116 t/config/authusingalias.t 117 t/config/classes.t 118 t/config/commandbuffersize.t 119 t/config/createhome.t 120 t/config/defaultchdir.t 121 t/config/defaultroot.t 122 t/config/deferwelcome.t 123 t/config/deleteabortedstores.t 124 t/config/denyfilter.t 125 t/config/dirfakegroup.t 126 t/config/dirfakemode.t 127 t/config/dirfakeuser.t 128 t/config/displaychdir.t 129 t/config/displayconnect.t 130 t/config/displayfiletransfer.t 131 t/config/displaylogin.t 132 t/config/displayquit.t 133 t/config/envvars.t 134 t/config/factsoptions.t 135 t/config/groupowner.t 136 t/config/hiddenstores.t 137 t/config/hidefiles.t 138 t/config/hidegroup.t 139 t/config/hidenoaccess.t 140 t/config/hideuser.t 141 t/config/ifdefine.t 142 t/config/include.t 143 t/config/listoptions.t 144 t/config/logoptions.t 145 t/config/masqueradeaddress.t 146 t/config/maxclients.t 147 t/config/maxclientsperclass.t 148 t/config/maxclientsperhost.t 149 t/config/maxclientsperuser.t 150 t/config/maxcommandrate.t 151 t/config/maxconnectionsperhost.t 152 t/config/maxinstances.t 153 t/config/maxloginattempts.t 154 t/config/maxpasswordsize.t 155 t/config/maxretrievefilesize.t 156 t/config/maxstorefilesize.t 157 t/config/maxtransfersperhost.t 158 t/config/maxtransfersperuser.t 159 t/config/multilinerfc2228.t 160 t/config/order.t 161 t/config/passiveports.t 162 t/config/pathallowfilter.t 163 t/config/pathdenyfilter.t 164 t/config/pidfile.t 165 t/config/protocols.t 166 t/config/requirevalidshell.t 167 t/config/rewritehome.t 168 t/config/rlimitchroot.t 169 t/config/rlimitcpu.t 170 t/config/rlimitmemory.t 171 t/config/rlimitopenfiles.t 172 t/config/rootrevoke.t 173 t/config/serveradmin.t 174 t/config/serverident.t 175 t/config/setenv.t 176 t/config/showsymlinks.t 177 t/config/socketoptions.t 178 t/config/storeuniqueprefix.t 179 t/config/sysloglevel.t 180 t/config/timeoutidle.t 181 t/config/timeoutlogin.t 182 t/config/timeoutnotransfer.t 183 t/config/timeoutsession.t 184 t/config/timeoutstalled.t 185 t/config/trace.t 186 t/config/traceoptions.t 187 t/config/transferrate.t 188 t/config/umask.t 189 t/config/useftpusers.t 190 t/config/useglobbing.t 191 t/config/useralias.t 192 t/config/userowner.t 193 t/config/userpassword.t 194 t/config/usesendfile.t 195 t/config/virtualhost.t 196 t/config/directory/limits.t 197 t/config/directory/umask.t 198 t/config/ftpaccess/dele.t 199 t/config/ftpaccess/empty.t 200 t/config/ftpaccess/merging.t 201 t/config/ftpaccess/retr.t 202 t/config/limit/anonymous.t 203 t/config/limit/login.t 204 t/config/limit/mfmt.t 205 t/config/limit/opts.t 206 t/config/limit/rmd.t 207 t/config/limit/xmkd.t 208 t/config/limit/filters.t 209 t/config/limit/subdirs.t 210 t/logging/extendedlog.t 211 t/logging/serverlog.t 212 t/logging/systemlog.t 213 t/logging/transferlog.t 214 t/signals/term.t 215 t/signals/hup.t 216 t/signals/segv.t 217 t/signals/abrt.t 218 t/telnet.t 219 t/utils/ftpcount.t 220 t/utils/ftpwho.t 221 )]; 222 223 # Now interrogate the build to see which module/feature-specific test files 224 # should be added to the list. 225 my $order = 0; 226 227 my $FEATURE_TESTS = { 228 't/modules/mod_auth_file.t' => { 229 order => ++$order, 230 test_class => [qw(mod_auth_file)], 231 }, 232 233 't/modules/mod_auth_otp.t' => { 234 order => ++$order, 235 test_class => [qw(mod_auth_otp mod_sql mod_sql_sqlite)], 236 }, 237 238 't/modules/mod_auth_otp/sftp.t' => { 239 order => ++$order, 240 test_class => [qw(mod_auth_otp mod_sftp mod_sql mod_sql_sqlite)], 241 }, 242 243 't/modules/mod_ban.t' => { 244 order => ++$order, 245 test_class => [qw(mod_ban)], 246 }, 247 248 't/modules/mod_ban/memcache.t' => { 249 order => ++$order, 250 test_class => [qw(mod_ban mod_memcache)], 251 }, 252 253 't/modules/mod_cap.t' => { 254 order => ++$order, 255 test_class => [qw(mod_cap)], 256 }, 257 258 't/modules/mod_copy.t' => { 259 order => ++$order, 260 test_class => [qw(mod_copy)], 261 }, 262 263 't/modules/mod_ctrls.t' => { 264 order => ++$order, 265 test_class => [qw(mod_ctrls)], 266 }, 267 268 't/modules/mod_deflate.t' => { 269 order => ++$order, 270 test_class => [qw(mod_deflate)], 271 }, 272 273 't/modules/mod_delay.t' => { 274 order => ++$order, 275 test_class => [qw(mod_delay)], 276 }, 277 278 't/modules/mod_digest.t' => { 279 order => ++$order, 280 test_class => [qw(mod_digest)], 281 }, 282 283 't/modules/mod_dynmasq.t' => { 284 order => ++$order, 285 test_class => [qw(mod_dynmasq)], 286 }, 287 288 't/modules/mod_exec.t' => { 289 order => ++$order, 290 test_class => [qw(mod_exec)], 291 }, 292 293 't/modules/mod_facl.t' => { 294 order => ++$order, 295 test_class => [qw(mod_facl)], 296 }, 297 298 't/modules/mod_facts.t' => { 299 order => ++$order, 300 test_class => [qw(mod_facts)], 301 }, 302 303 't/modules/mod_geoip.t' => { 304 order => ++$order, 305 test_class => [qw(mod_geoip)], 306 }, 307 308 't/modules/mod_geoip/sql.t' => { 309 order => ++$order, 310 test_class => [qw(mod_geoip mod_sql mod_sql_sqlite)], 311 }, 312 313 't/modules/mod_ifversion.t' => { 314 order => ++$order, 315 test_class => [qw(mod_ifversion)], 316 }, 317 318 't/modules/mod_lang.t' => { 319 order => ++$order, 320 test_class => [qw(mod_lang)], 321 }, 322 323 't/modules/mod_log_forensic.t' => { 324 order => ++$order, 325 test_class => [qw(mod_log_forensic)], 326 }, 327 328 't/modules/mod_quotatab_file.t' => { 329 order => ++$order, 330 test_class => [qw(mod_quotatab mod_quotatab_file)], 331 }, 332 333 't/modules/mod_quotatab_sql.t' => { 334 order => ++$order, 335 test_class => [qw(mod_quotatab mod_quotatab_sql mod_sql_sqlite)], 336 }, 337 338 't/modules/mod_quotatab/copy.t' => { 339 order => ++$order, 340 test_class => [qw(mod_copy mod_quotatab mod_quotatab_sql mod_sql_sqlite)], 341 }, 342 343 't/modules/mod_quotatab/site_misc.t' => { 344 order => ++$order, 345 test_class => [qw( 346 mod_copy 347 mod_quotatab 348 mod_quotatab_sql 349 mod_sql_sqlite 350 mod_site_misc 351 )], 352 }, 353 354 't/modules/mod_ratio.t' => { 355 order => ++$order, 356 test_class => [qw(mod_ratio)], 357 }, 358 359 't/modules/mod_readme.t' => { 360 order => ++$order, 361 test_class => [qw(mod_readme)], 362 }, 363 364 't/modules/mod_redis.t' => { 365 order => ++$order, 366 test_class => [qw(mod_redis)], 367 }, 368 369 't/modules/mod_rewrite.t' => { 370 order => ++$order, 371 test_class => [qw(mod_rewrite)], 372 }, 373 374 't/modules/mod_rlimit.t' => { 375 order => ++$order, 376 test_class => [qw(mod_rlimit)], 377 }, 378 379 't/modules/mod_sftp.t' => { 380 order => ++$order, 381 test_class => [qw(mod_sftp)], 382 }, 383 384 't/modules/mod_sftp/ban.t' => { 385 order => ++$order, 386 test_class => [qw(mod_ban mod_sftp)], 387 }, 388 389 't/modules/mod_sftp/exec.t' => { 390 order => ++$order, 391 test_class => [qw(mod_exec mod_sftp)], 392 }, 393 394 't/modules/mod_sftp/fips.t' => { 395 order => ++$order, 396 test_class => [qw(feat_openssl_fips mod_sftp)], 397 }, 398 399 't/modules/mod_sftp/rewrite.t' => { 400 order => ++$order, 401 test_class => [qw(mod_rewrite mod_sftp)], 402 }, 403 404 't/modules/mod_sftp/sql.t' => { 405 order => ++$order, 406 test_class => [qw(mod_sftp mod_sql_sqlite)], 407 }, 408 409 't/modules/mod_sftp/wrap2.t' => { 410 order => ++$order, 411 test_class => [qw(mod_sftp mod_wrap2)], 412 }, 413 414 't/modules/mod_sftp_pam.t' => { 415 order => ++$order, 416 test_class => [qw(mod_sftp mod_sftp_pam)], 417 }, 418 419 't/modules/mod_sftp_sql.t' => { 420 order => ++$order, 421 test_class => [qw(mod_sftp mod_sftp_sql mod_sql_sqlite)], 422 }, 423 424 't/modules/mod_shaper.t' => { 425 order => ++$order, 426 test_class => [qw(mod_shaper)], 427 }, 428 429 't/modules/mod_site.t' => { 430 order => ++$order, 431 test_class => [qw(mod_site)], 432 }, 433 434 't/modules/mod_site_misc.t' => { 435 order => ++$order, 436 test_class => [qw(mod_site_misc)], 437 }, 438 439 't/modules/mod_snmp.t' => { 440 order => ++$order, 441 test_class => [qw(mod_snmp)], 442 }, 443 444 't/modules/mod_sql.t' => { 445 order => ++$order, 446 test_class => [qw(mod_sql)], 447 }, 448 449 't/modules/mod_sql_passwd.t' => { 450 order => ++$order, 451 test_class => [qw(mod_sql_passwd mod_sql_sqlite)], 452 }, 453 454 't/modules/mod_sql_passwd/fips.t' => { 455 order => ++$order, 456 test_class => [qw(feat_openssl_fips mod_sql_passwd mod_sql_sqlite mod_sftp)], 457 }, 458 459 't/modules/mod_sql_odbc.t' => { 460 order => ++$order, 461 test_class => [qw(mod_sql_odbc)], 462 }, 463 464 't/modules/mod_sql_sqlite.t' => { 465 order => ++$order, 466 test_class => [qw(mod_sql_sqlite)], 467 }, 468 469 't/modules/mod_statcache.t' => { 470 order => ++$order, 471 test_class => [qw(mod_statcache)], 472 }, 473 474 't/modules/mod_statcache/sftp.t' => { 475 order => ++$order, 476 test_class => [qw(mod_sftp mod_statcache)], 477 }, 478 479 't/modules/mod_tls.t' => { 480 order => ++$order, 481 test_class => [qw(mod_tls)], 482 }, 483 484 't/modules/mod_tls/sni.t' => { 485 order => ++$order, 486 test_class => [qw(mod_tls)], 487 }, 488 489 't/modules/mod_tls_fscache.t' => { 490 order => ++$order, 491 test_class => [qw(mod_tls_fscache)], 492 }, 493 494 't/modules/mod_tls_memcache.t' => { 495 order => ++$order, 496 test_class => [qw(mod_tls_memcache)], 497 }, 498 499 't/modules/mod_tls_shmcache.t' => { 500 order => ++$order, 501 test_class => [qw(mod_tls_shmcache)], 502 }, 503 504 't/modules/mod_unique_id.t' => { 505 order => ++$order, 506 test_class => [qw(mod_unique_id)], 507 }, 508 509 't/modules/mod_wrap.t' => { 510 order => ++$order, 511 test_class => [qw(mod_wrap)], 512 }, 513 514 't/modules/mod_wrap2_file.t' => { 515 order => ++$order, 516 test_class => [qw(mod_wrap2_file)], 517 }, 518 519 't/modules/mod_wrap2_redis.t' => { 520 order => ++$order, 521 test_class => [qw(mod_redis mod_wrap2_redis)], 522 }, 523 524 't/modules/mod_wrap2_sql.t' => { 525 order => ++$order, 526 test_class => [qw(mod_sql_sqlite mod_wrap2_sql)], 527 }, 528 }; 529 530 my @feature_tests = testsuite_get_runnable_tests($FEATURE_TESTS); 531 my $feature_ntests = scalar(@feature_tests); 532 if ($feature_ntests > 1 || 533 ($feature_ntests == 1 && $feature_tests[0] ne 'testsuite_empty_test')) { 534 push(@$test_files, @feature_tests); 535 } 536} 537 538$ENV{PROFTPD_TEST} = 1; 539 540if (defined($opts->{C})) { 541 $ENV{PROFTPD_TEST_ENABLE_CLASS} = join(':', @{ $opts->{C} }); 542 543} else { 544 # Disable all 'inprogress' and 'slow' tests by default 545 $ENV{PROFTPD_TEST_DISABLE_CLASS} = 'inprogress:slow'; 546} 547 548if (defined($opts->{F})) { 549 # Using the provided string as a regex, and run only the tests whose 550 # files match the pattern 551 552 my $file_pattern = $opts->{F}; 553 554 my $filtered_files = []; 555 foreach my $test_file (@$test_files) { 556 if ($test_file =~ /$file_pattern/) { 557 push(@$filtered_files, $test_file); 558 } 559 } 560 561 $test_files = $filtered_files; 562} 563 564runtests(@$test_files) if scalar(@$test_files) > 0; 565 566exit 0; 567 568sub usage { 569 print STDOUT <<EOH; 570 571$0: [--help] [--class=\$name] [--verbose] 572 573Examples: 574 575 perl $0 576 perl $0 --class foo 577 perl $0 --class bar --class baz 578 579EOH 580 exit 0; 581} 582