Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109447351
D38969.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D38969.diff
View Options
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
--- 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
--- 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 @@
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
--- /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
--- /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
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Feb 6, 4:43 AM (12 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16487154
Default Alt Text
D38969.diff (12 KB)
Attached To
Mode
D38969: tftp: Add tests.
Attached
Detach File
Event Timeline
Log In to Comment