The proftpd source code is accompanied by a testsuite, for testing various features and functionality. At present, the testsuite is divided into two main parts: the API-level tests, and the integration tests. The API tests are written in C, and exercise the various APIs that proftpd provides to module developers. The integration tests are currently written in Perl, and seek to check a compiled proftpd's run-time behavior.
proftpd
In order to run the testsuite, you must configure your proftpd build so that the testsuite is prepared. You do this by using the --enable-tests configure option, along with your other build options, e.g.:
--enable-tests
$ ./configure --enable-tests ...
API Tests The API tests use the libcheck library; see:
libcheck
http://check.sourceforge.net/
checking for tcase_create in -lcheck... no configure: error: libcheck support, required for tests, not present -- aborting
--with-includes
--with-libraries
To run the testsuite, use the make check target:
make check
$ ./configure --enable-tests ... $ make ... $ make check ... $ ./api-tests Running suite(s): pool array str sets timers table var event env version feat netaddr netacl class regexp expr scoreboard modules 100%: Checks: 140, Failures: 0, Errors: 0
If one of the API tests fails, you will see an error message like:
99%: Checks: 140, Failures: 1, Errors: 0 api/env.c:53:F:base:env_get_test:0: Failed to handle null arguments ------------------------------------------------- FAILED 1 test Please send email to: proftp-devel@lists.sourceforge.net containing the `api-tests.log' file (in the tests/ directory) and the output from running `proftpd -V' -------------------------------------------------
Expected Failures Unfortunately, due to variations in system configurations, it's possible that some of the API tests will fail, without it necessarily being an indication of a regression or problem.
Most notably, some of the most brittle tests make assumptions about the host's /etc/hosts file, particularly the list of names associated with the address 127.0.0.1. If the /etc/hosts file has a name other than "localhost" or "localhost.localdomain" immediately after the 127.0.0.1 address, e.g.:
/etc/hosts
127.0.0.1
127.0.0.1 some.other.name localhost
98%: Checks: 152, Failures: 2, Errors: 0 api/netaddr.c:344:F:base:netaddr_get_dnsstr_test:0: Expected 'localhost or localhost.localdomain', got 'some.other.name' api/netacl.c:535:F:base:netacl_match_test:0: Failed to positively match ACL to addr: No such file or directory
Integration Tests The current integration tests are written in Perl, and rely on the Test-Unit Perl package. Specifically, you must use Test-Unit-0.14, not Test-Unit-0.25. Not sure which version of Test-Unit you have, if at all? Run the following command:
Test-Unit
Test-Unit-0.14
Test-Unit-0.25
$ perl -MTest::Unit -e 'print $Test::Unit::VERSION, "\n";' 0.14
To run the integration tests manually, use the tests.pl script:
tests.pl
$ cd tests/ $ perl tests.pl t/logins.....................ok t/commands/user..............ok t/commands/pass..............ok t/commands/pwd...............ok t/commands/cwd...............ok t/commands/cdup..............ok t/commands/syst..............ok t/commands/type..............ok t/commands/mkd...............ok t/commands/rmd...............ok t/commands/dele..............ok t/commands/mdtm..............ok t/commands/size..............ok t/commands/mode..............ok t/commands/stru..............ok t/commands/allo..............ok t/commands/noop..............ok t/commands/feat..............ok t/commands/help..............ok t/commands/quit..............ok t/commands/rnfr..............ok t/commands/rnto..............ok t/commands/rest..............ok t/commands/pasv..............ok t/commands/epsv..............ok t/commands/port..............ok t/commands/eprt..............ok t/commands/nlst..............ok t/commands/list..............ok t/commands/retr..............ok t/commands/stor..............ok t/commands/appe..............ok t/config/displayconnect......ok t/config/displaylogin........ok t/config/maxloginattempts....ok t/config/serverident.........ok All tests successful. Files=37, Tests=141, 160 wallclock secs ( 4.33 cusr + 4.74 csys = 9.07 CPU)
Some of the integration require root privileges in order to perform the test properly, e.g. for <Anonymous>/DefaultRoot logins, etc. If you do not run `make check' as root, those tests which require root privileges are automatically skipped. Thus for doing a full regression, run the integration tests as the root user.
<Anonymous>
DefaultRoot
Adding New Tests The following information is for those who are interested in adding new tests, updating existing tests, or otherwise helping with the testsuite development.
The API tests driver, api-tests, honors the PR_TEST_SUITE environment variable. This is useful for running just the test cases associated with a particular suite, such as env or pool. Only one suite can be specified using the PR_TEST_SUITE environment variable:
api-tests
PR_TEST_SUITE
$ make check $ cd tests/ $ PR_TEST_SUITE=pool ./api-tests Running suite(s): pool 100%: Checks: 5, Failures: 0, Errors: 0
Frequently Asked Questions Question: I have installed the check library, and I am using the --enable-tests configure option, but the configure command fails with: checking check.h usability... yes checking check.h presence... yes checking for check.h... yes checking for tcase_create in -lcheck... no configure: error: libcheck support, required for tests, not present -- aborting What am I missing? Answer: To properly answer this, we would need to look in the log file generated by the configure script, i.e. the config.log file. I suspect that looking in that config.log file, you would see something like this: configure:20568: checking for tcase_create in -lcheck configure:20603: gcc -o conftest -g2 -g -O2 -fdebug-prefix-map=/home/hille/devel/proftp/pftp_build/proftpd-dfsg=. -fstack-protector-strong -Wformat -Werror=format-security -Wall -fno-omit-frame-pointer -Werror=implicit-function-declaration -Wdate-time -D_FORTIFY_SOURCE=2 -I/usr/include/mysql -I/usr/include/postgresql -L$(top_srcdir)/lib -Wl,-z,relro -rdynamic conftest.c -lcheck -ldl >&5 /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check.o): In function `tcase_create': (.text+0x1ce): undefined reference to `floor' /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check.o): In function `tcase_set_timeout': (.text+0x513): undefined reference to `floor' /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check.o): In function `check_get_clockid': (.text+0xc1d): undefined reference to `timer_create' (.text+0xc48): undefined reference to `timer_delete' /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check_pack.o): In function `ppack': (.text+0x5b1): undefined reference to `__pthread_register_cancel' (.text+0x5fc): undefined reference to `__pthread_unregister_cancel' collect2: error: ld returned 1 exit status Newer versions of the check library have dependencies on other libraries, which need to be declared explicitly. Thus to address these dependency linker errors, you would need to re-run your configure command and provide those linker dependencies: $ make clean $ ./configure LIBS="-lm -lrt -pthread" ... Note that even after doing the above, you still may have the configure command fail to detect the check library. There are reports that using check 0.10.0 and later also require the subunit library, and thus you may need to use: $ make clean $ ./configure LIBS="-lsubunit -lm -lrt -pthread" ... © Copyright 2017-2018 The ProFTPD Project All Rights Reserved
Question: I have installed the check library, and I am using the --enable-tests configure option, but the configure command fails with:
check
checking check.h usability... yes checking check.h presence... yes checking for check.h... yes checking for tcase_create in -lcheck... no configure: error: libcheck support, required for tests, not present -- aborting
Answer: To properly answer this, we would need to look in the log file generated by the configure script, i.e. the config.log file. I suspect that looking in that config.log file, you would see something like this:
config.log
configure:20568: checking for tcase_create in -lcheck configure:20603: gcc -o conftest -g2 -g -O2 -fdebug-prefix-map=/home/hille/devel/proftp/pftp_build/proftpd-dfsg=. -fstack-protector-strong -Wformat -Werror=format-security -Wall -fno-omit-frame-pointer -Werror=implicit-function-declaration -Wdate-time -D_FORTIFY_SOURCE=2 -I/usr/include/mysql -I/usr/include/postgresql -L$(top_srcdir)/lib -Wl,-z,relro -rdynamic conftest.c -lcheck -ldl >&5 /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check.o): In function `tcase_create': (.text+0x1ce): undefined reference to `floor' /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check.o): In function `tcase_set_timeout': (.text+0x513): undefined reference to `floor' /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check.o): In function `check_get_clockid': (.text+0xc1d): undefined reference to `timer_create' (.text+0xc48): undefined reference to `timer_delete' /usr/lib/gcc/i686-linux-gnu/7/../../../i386-linux-gnu/libcheck.a(check_pack.o): In function `ppack': (.text+0x5b1): undefined reference to `__pthread_register_cancel' (.text+0x5fc): undefined reference to `__pthread_unregister_cancel' collect2: error: ld returned 1 exit status
$ make clean $ ./configure LIBS="-lm -lrt -pthread" ...
subunit
$ make clean $ ./configure LIBS="-lsubunit -lm -lrt -pthread" ...