git: 64c2a712d661 - main - tftp: Add tests.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 10 Mar 2023 13:29:24 UTC
The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=64c2a712d661db9be31f02fe97c3b59710290ae3 commit 64c2a712d661db9be31f02fe97c3b59710290ae3 Author: Dag-Erling Smørgrav <des@FreeBSD.org> AuthorDate: 2023-03-10 13:24:56 +0000 Commit: Dag-Erling Smørgrav <des@FreeBSD.org> CommitDate: 2023-03-10 13:25:16 +0000 tftp: Add tests. Sponsored by: Klara, Inc. Reviewed by: asomers Differential Revision: https://reviews.freebsd.org/D38969 --- etc/mtree/BSD.tests.dist | 2 + usr.bin/tftp/Makefile | 5 + usr.bin/tftp/tests/Makefile | 10 + usr.bin/tftp/tests/tftp_test.sh | 406 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 423 insertions(+) diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index f3420369ad80..c9a13cec193e 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -1110,6 +1110,8 @@ .. tar .. + tftp + .. tr .. truncate diff --git a/usr.bin/tftp/Makefile b/usr.bin/tftp/Makefile index b6ad018e03ac..91df4847c629 100644 --- a/usr.bin/tftp/Makefile +++ b/usr.bin/tftp/Makefile @@ -1,6 +1,8 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include <src.opts.mk> + .PATH: ${SRCTOP}/libexec/tftpd PROG= tftp @@ -10,4 +12,7 @@ CFLAGS+=-I${SRCTOP}/libexec/tftpd LIBADD= edit +HAS_TESTS= +SUBDIR.${MK_TESTS}= tests + .include <bsd.prog.mk> diff --git a/usr.bin/tftp/tests/Makefile b/usr.bin/tftp/tests/Makefile new file mode 100644 index 000000000000..ca5d89f92af3 --- /dev/null +++ b/usr.bin/tftp/tests/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +PACKAGE= tests + +ATF_TESTS_SH= tftp_test +BINDIR= ${TESTSDIR} + +TESTS_METADATA.tftp_test+= is_exclusive="true" + +.include <bsd.test.mk> diff --git a/usr.bin/tftp/tests/tftp_test.sh b/usr.bin/tftp/tests/tftp_test.sh new file mode 100644 index 000000000000..96e375f51aeb --- /dev/null +++ b/usr.bin/tftp/tests/tftp_test.sh @@ -0,0 +1,406 @@ +# +# Copyright (c) 2023 Klara, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause +# + +tftp_dir="${TMPDIR:-/tmp}/tftp.dir" +inetd_conf="${TMPDIR:-/tmp}/inetd.conf" +inetd_pid="${TMPDIR:-/tmp}/inetd.pid" + +start_tftpd() { + if ! [ -z "$(sockstat -PUDP -p69 -q)" ] ; then + atf_skip "the tftp port is in use" + fi + echo "starting inetd for $(atf_get ident)" >&2 + rm -rf "${tftp_dir}" + mkdir "${tftp_dir}" + cat >"${inetd_conf}" <<EOF +tftp dgram udp wait root /usr/libexec/tftpd tftpd -d15 -l ${tftp_dir} +tftp dgram udp6 wait root /usr/libexec/tftpd tftpd -d15 -l ${tftp_dir} +EOF + /usr/sbin/inetd -a localhost -p "${inetd_pid}" "${inetd_conf}" +} + +stop_tftpd() { + echo "stopping inetd for $(atf_get ident)" >&2 + # Send SIGTERM to inetd, then SIGKILL until it's gone + local sig=TERM + while pkill -$sig -LF "${inetd_pid}" inetd ; do + echo "waiting for inetd to stop" >&2 + sleep 1 + sig=KILL + done + rm -rf "${tftp_dir}" "${inetd_conf}" "${inetd_pid}" +} + +atf_test_case tftp_get_big cleanup +tftp_get_big_head() { + atf_set "descr" "get command with big file" + atf_set "require.user" "root" +} +tftp_get_big_body() { + start_tftpd + local remote_file="${tftp_dir}/remote.bin" + dd if=/dev/urandom of="${remote_file}" bs=1m count=16 status=none + local local_file="local.bin" + echo "get ${remote_file##*/} ${local_file}" >client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp localhost <client-script + atf_check cmp -s "${local_file}" "${remote_file}" +} +tftp_get_big_cleanup() { + stop_tftpd +} + +atf_test_case tftp_get_host cleanup +tftp_get_host_head() { + atf_set "descr" "get command with host name" + atf_set "require.user" "root" +} +tftp_get_host_body() { + start_tftpd + local remote_file="${tftp_dir}/hello.txt" + echo "Hello, $$!" >"${remote_file}" + local local_file="${remote_file##*/}" + echo "get localhost:${remote_file##*/}" >client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp <client-script + atf_check cmp -s "${local_file}" "${remote_file}" +} +tftp_get_host_cleanup() { + stop_tftpd +} + +atf_test_case tftp_get_ipv4 cleanup +tftp_get_ipv4_head() { + atf_set "descr" "get command with ipv4 address" + atf_set "require.user" "root" +} +tftp_get_ipv4_body() { + start_tftpd + local remote_file="${tftp_dir}/hello.txt" + echo "Hello, $$!" >"${remote_file}" + local local_file="${remote_file##*/}" + echo "get 127.0.0.1:${remote_file##*/}" >client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp <client-script + atf_check cmp -s "${local_file}" "${remote_file}" +} +tftp_get_ipv4_cleanup() { + stop_tftpd +} + +atf_test_case tftp_get_ipv6 cleanup +tftp_get_ipv6_head() { + atf_set "descr" "get command with ipv6 address" + atf_set "require.user" "root" +} +tftp_get_ipv6_body() { + sysctl -q kern.features.inet6 || atf_skip "This test requires IPv6 support" + start_tftpd + local remote_file="${tftp_dir}/hello.txt" + echo "Hello, $$!" >"${remote_file}" + local local_file="${remote_file##*/}" + echo "get [::1]:${remote_file##*/}" >client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp <client-script + atf_check cmp -s "${local_file}" "${remote_file}" +} +tftp_get_ipv6_cleanup() { + stop_tftpd +} + +atf_test_case tftp_get_one cleanup +tftp_get_one_head() { + atf_set "descr" "get command with one argument" + atf_set "require.user" "root" +} +tftp_get_one_body() { + start_tftpd + local remote_file="${tftp_dir}/hello.txt" + echo "Hello, $$!" >"${remote_file}" + local local_file="${remote_file##*/}" + echo "get ${remote_file##*/}" >client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp localhost <client-script + atf_check cmp -s "${local_file}" "${remote_file}" +} +tftp_get_one_cleanup() { + stop_tftpd +} + +atf_test_case tftp_get_two cleanup +tftp_get_two_head() { + atf_set "descr" "get command with two arguments" + atf_set "require.user" "root" +} +tftp_get_two_body() { + start_tftpd + local remote_file="${tftp_dir}/hello.txt" + echo "Hello, $$!" >"${remote_file}" + local local_file="world.txt" + echo "get ${remote_file##*/} ${local_file}" >client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp localhost <client-script + atf_check cmp -s "${local_file}" "${remote_file}" +} +tftp_get_two_cleanup() { + stop_tftpd +} + +atf_test_case tftp_get_more cleanup +tftp_get_more_head() { + atf_set "descr" "get command with three or more arguments" + atf_set "require.user" "root" +} +tftp_get_more_body() { + start_tftpd + for n in 3 4 5 6 7 ; do + echo -n "get" >client-script + for f in $(jot -c $n 97) ; do + echo "test file $$/$f/$n" >"${tftp_dir}/${f}.txt" + echo -n " ${f}.txt" >>client-script + rm -f "${f}.txt" + done + echo >>client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp localhost <client-script + for f in $(jot -c $n 97) ; do + atf_check cmp -s "${f}.txt" "${tftp_dir}/${f}.txt" + done + done +} +tftp_get_more_cleanup() { + stop_tftpd +} + +atf_test_case tftp_get_multi_host cleanup +tftp_get_multi_host_head() { + atf_set "descr" "get command with multiple files and host name" + atf_set "require.user" "root" +} +tftp_get_multi_host_body() { + start_tftpd + for f in a b c ; do + echo "test file $$/$f/$n" >"${tftp_dir}/${f}.txt" + rm -f "${f}.txt" + done + echo "get localhost:a.txt b.txt c.txt" >client-script + atf_check -o match:"Received [0-9]+ bytes" \ + tftp localhost <client-script + for f in a b c ; do + atf_check cmp -s "${f}.txt" "${tftp_dir}/${f}.txt" + done +} +tftp_get_multi_host_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_big cleanup +tftp_put_big_head() { + atf_set "descr" "put command with big file" + atf_set "require.user" "root" +} +tftp_put_big_body() { + start_tftpd + local local_file="local.bin" + dd if=/dev/urandom of="${local_file}" bs=1m count=16 status=none + local remote_file="${tftp_dir}/random.bin" + truncate -s 0 "${remote_file}" + chown nobody:nogroup "${remote_file}" + chmod 0666 "${remote_file}" + echo "put ${local_file} ${remote_file##*/}" >client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp localhost <client-script + atf_check cmp -s "${remote_file}" "${local_file}" +} +tftp_put_big_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_host cleanup +tftp_put_host_head() { + atf_set "descr" "put command with host name" + atf_set "require.user" "root" +} +tftp_put_host_body() { + start_tftpd + local local_file="local.txt" + echo "test file $$" >"${local_file}" + local remote_file="${tftp_dir}/remote.txt" + truncate -s 0 "${remote_file}" + chown nobody:nogroup "${remote_file}" + chmod 0666 "${remote_file}" + echo "put ${local_file} localhost:${remote_file##*/}" >client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp <client-script + atf_check cmp -s "${remote_file}" "${local_file}" +} +tftp_put_host_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_ipv4 cleanup +tftp_put_ipv4_head() { + atf_set "descr" "put command with ipv4 address" + atf_set "require.user" "root" +} +tftp_put_ipv4_body() { + start_tftpd + local local_file="local.txt" + echo "test file $$" >"${local_file}" + local remote_file="${tftp_dir}/remote.txt" + truncate -s 0 "${remote_file}" + chown nobody:nogroup "${remote_file}" + chmod 0666 "${remote_file}" + echo "put ${local_file} 127.0.0.1:${remote_file##*/}" >client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp <client-script + atf_check cmp -s "${remote_file}" "${local_file}" +} +tftp_put_ipv4_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_ipv6 cleanup +tftp_put_ipv6_head() { + atf_set "descr" "put command with ipv6 address" + atf_set "require.user" "root" +} +tftp_put_ipv6_body() { + sysctl -q kern.features.inet6 || atf_skip "This test requires IPv6 support" + start_tftpd + local local_file="local.txt" + echo "test file $$" >"${local_file}" + local remote_file="${tftp_dir}/remote.txt" + truncate -s 0 "${remote_file}" + chown nobody:nogroup "${remote_file}" + chmod 0666 "${remote_file}" + echo "put ${local_file} [::1]:${remote_file##*/}" >client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp <client-script + atf_check cmp -s "${remote_file}" "${local_file}" +} +tftp_put_ipv6_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_one cleanup +tftp_put_one_head() { + atf_set "descr" "put command with one argument" + atf_set "require.user" "root" +} +tftp_put_one_body() { + start_tftpd + local local_file="file.txt" + echo "test file $$" >"${local_file}" + local remote_file="${tftp_dir}/${local_file}" + truncate -s 0 "${remote_file}" + chown nobody:nogroup "${remote_file}" + chmod 0666 "${remote_file}" + echo "put ${local_file}" >client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp localhost <client-script + atf_check cmp -s "${remote_file}" "${local_file}" +} +tftp_put_one_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_two cleanup +tftp_put_two_head() { + atf_set "descr" "put command with two arguments" + atf_set "require.user" "root" +} +tftp_put_two_body() { + start_tftpd + local local_file="local.txt" + echo "test file $$" >"${local_file}" + local remote_file="${tftp_dir}/remote.txt" + truncate -s 0 "${remote_file}" + chown nobody:nogroup "${remote_file}" + chmod 0666 "${remote_file}" + echo "put ${local_file} ${remote_file##*/}" >client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp localhost <client-script + atf_check cmp -s "${remote_file}" "${local_file}" +} +tftp_put_two_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_more cleanup +tftp_put_more_head() { + atf_set "descr" "put command with three or more arguments" + atf_set "require.user" "root" +} +tftp_put_more_body() { + start_tftpd + mkdir "${tftp_dir}/subdir" + for n in 2 3 4 5 6 ; do + echo -n "put" >client-script + for f in $(jot -c $n 97) ; do + echo "test file $$/$f/$n" >"${f}.txt" + truncate -s 0 "${tftp_dir}/subdir/${f}.txt" + chown nobody:nogroup "${tftp_dir}/subdir/${f}.txt" + chmod 0666 "${tftp_dir}/subdir/${f}.txt" + echo -n " ${f}.txt" >>client-script + done + echo " subdir" >>client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp localhost <client-script + for f in $(jot -c $n 97) ; do + atf_check cmp -s "${tftp_dir}/subdir/${f}.txt" "${f}.txt" + done + done +} +tftp_put_more_cleanup() { + stop_tftpd +} + +atf_test_case tftp_put_multi_host cleanup +tftp_put_multi_host_head() { + atf_set "descr" "put command with multiple files and host name" + atf_set "require.user" "root" +} +tftp_put_multi_host_body() { + start_tftpd + mkdir "${tftp_dir}/subdir" + echo -n "put" >client-script + for f in a b c ; do + echo "test file $$/$f" >"${f}.txt" + truncate -s 0 "${tftp_dir}/subdir/${f}.txt" + chown nobody:nogroup "${tftp_dir}/subdir/${f}.txt" + chmod 0666 "${tftp_dir}/subdir/${f}.txt" + echo -n " ${f}.txt" >>client-script + done + echo " localhost:subdir" >>client-script + atf_check -o match:"Sent [0-9]+ bytes" \ + tftp <client-script + for f in a b c ; do + atf_check cmp -s "${tftp_dir}/subdir/${f}.txt" "${f}.txt" + done +} +tftp_put_multi_host_cleanup() { + stop_tftpd +} + +atf_init_test_cases() { + atf_add_test_case tftp_get_big + atf_add_test_case tftp_get_host + atf_add_test_case tftp_get_ipv4 + atf_add_test_case tftp_get_ipv6 + atf_add_test_case tftp_get_one + atf_add_test_case tftp_get_two + atf_add_test_case tftp_get_more + atf_add_test_case tftp_get_multi_host + atf_add_test_case tftp_put_big + atf_add_test_case tftp_put_host + atf_add_test_case tftp_put_ipv4 + atf_add_test_case tftp_put_ipv6 + atf_add_test_case tftp_put_one + atf_add_test_case tftp_put_two + atf_add_test_case tftp_put_more + atf_add_test_case tftp_put_multi_host +}