From 46795b1ef2eb24761b3b4eb83aed0a5e989a04fb Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 11 Sep 2026 14:38:06 -0700 Subject: [PATCH] tests: cover the app-driven sftp and shell paths The -A cases in scp.test reach the exec callback and the scp handoff. These drive the rest: the subsystem callback with the sftp accept, the shell callback in echo mode, and both accepts on a blocking server. - sftp.test connects to an -A server blocking and non-blocking - sshclient.test runs a terminal session and a command session against an -A server - scp.test copies from a blocking -A server, where wolfSSH_SCP_accept() completes in one call rather than through the retry loop --- scripts/scp.test | 20 ++++++++++++++++++++ scripts/sftp.test | 35 +++++++++++++++++++++++++++++++++++ scripts/sshclient.test | 22 +++++++++++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/scripts/scp.test b/scripts/scp.test index 16064333..cfa69739 100755 --- a/scripts/scp.test +++ b/scripts/scp.test @@ -178,6 +178,26 @@ else exit 1 fi +# The same handoff on a blocking server, where wolfSSH_SCP_accept() runs to +# completion in one call rather than through the retry loop above. +echo "Test basic copy from server to local, blocking app-driven server" +./examples/echoserver/echoserver -A -1 -R $ready_file & +server_pid=$! +create_port +$run_client ./examples/scpclient/wolfscp -u jill -P upthehill -p $port -S $PWD/scripts/scp.test:$PWD/scp.test +RESULT=$? +remove_ready_file +stop_server +check_timeout $RESULT "basic copy from server to local, blocking app-driven server" + +if test -e $PWD/scp.test; then + rm $PWD/scp.test +else + echo -e "\n\nfailed to get file from blocking app-driven server" + do_cleanup + exit 1 +fi + echo "Test of getting empty file" touch $PWD/scripts/empty ./examples/echoserver/echoserver -1 -R $ready_file & diff --git a/scripts/sftp.test b/scripts/sftp.test index 3d5304cf..9e551df1 100755 --- a/scripts/sftp.test +++ b/scripts/sftp.test @@ -112,6 +112,41 @@ if [ $RESULT -ne 0 ]; then exit 1 fi +# With -A the echoserver answers the subsystem request in its own callback +# and serves the session through wolfSSH_SFTP_accept(); the cases above take +# the accept() re-entry instead. +if [ "$nonblockingOnly" = 0 ]; then + echo "Test connection to an app-driven server" + ./examples/echoserver/echoserver -A -1 -R "$ready_file" & + server_pid=$! + create_port + echo "exit" | ./examples/sftpclient/wolfsftp -u jill -P upthehill -p "$port" + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo + echo "failed to connect to app-driven server" + do_cleanup + exit 1 + fi +fi + +# The same handoff on a non-blocking server, which reaches the accept call's +# want-read and want-write retries. +echo "Test non blocking connection to an app-driven server" +./examples/echoserver/echoserver -A -N -1 -R "$ready_file" & +server_pid=$! +create_port +echo "exit" | ./examples/sftpclient/wolfsftp -N -u jill -P upthehill -p "$port" +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo + echo "failed to connect to non blocking app-driven server" + do_cleanup + exit 1 +fi + # Test want write return from highwater callback if [ "$nonblockingOnly" = 0 ]; then echo "Test want write return from highwater callback" diff --git a/scripts/sshclient.test b/scripts/sshclient.test index af145f96..762f457f 100755 --- a/scripts/sshclient.test +++ b/scripts/sshclient.test @@ -83,6 +83,7 @@ trap do_trap INT TERM # -f keeps the server in echo mode. Without it a build with shell support # tries to fork a login shell for the user, which fails since jill isn't a # real account, and the session ends before anything crosses the channel. +# Any arguments are passed on to the echoserver. start_server() { # The -1 server exits after its connection, but a client run that failed # before connecting leaves one listening. Reap it, server_pid is about @@ -95,7 +96,7 @@ start_server() { fi rm -f "$ready_file" - ./examples/echoserver/echoserver -1 -f -R "$ready_file" \ + ./examples/echoserver/echoserver -1 -f "$@" -R "$ready_file" \ > "$work_dir/server.log" 2>&1 & server_pid=$! @@ -282,6 +283,25 @@ if [ -s "$work_dir/terminal.log" ]; then && fail "the client sent a command it wasn't given" fi +# -A hands the session requests to the echoserver's own callbacks: the shell +# callback claims the channel the worker echoes on, and an exec request that +# is not a transfer runs as a session through the same callback. +echo "Test terminal session, app-driven server" +start_server -A +run_client "" -E "$work_dir/appterm.log" -p $port jill@127.0.0.1 +[ $? -ne 0 ] && fail "failed to open the terminal session on an app-driven server" + +grep -q "hello" "$client_out" \ + || fail "the app-driven echoserver's reply didn't make it back" + +echo "Test a session given a command, app-driven server" +start_server -A +run_client "" -E "$work_dir/appcommand.log" -p $port jill@127.0.0.1 "echo three" +[ $? -ne 0 ] && fail "failed to open the session on an app-driven server" + +grep -q "hello" "$client_out" \ + || fail "the app-driven echoserver's reply didn't make it back" + echo "Test the usage message" ./apps/wolfssh/wolfssh -Z 2>&1 | grep -q "usage:" \ || fail "no usage message for a bad option"