Files
wehub-resource-sync 5357c39144
Fuzzer / Run Fuzzer (push) Has been cancelled
Race tests / Go race tests (ubuntu-22.04) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:01:40 +08:00

159 lines
5.1 KiB
Bash

#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
load $BATS_TEST_DIRNAME/helper/query-server-common.bash
load $BATS_TEST_DIRNAME/helper/git-ssh-common.bash
# Regression tests for https://github.com/dolthub/dolt/issues/10897
# Verifies that `dolt sql-server` does not leak ssh child processes
# when CALL dolt_fetch / dolt_pull / dolt_push runs against an ssh://
# remote. Each remote db must be closed at the end of the procedure,
# tearing down the spawned ssh subprocess.
setup() {
skiponwindows "ssh transport tests are not supported on Windows"
if ! command -v sshd >/dev/null 2>&1 && [[ ! -x /usr/sbin/sshd ]]; then
skip "sshd not available on this host"
fi
cd "$BATS_TEST_TMPDIR"
setup_git_sshd
gen_ssh_key "$BATS_TEST_TMPDIR/ssh_key" ""
export DOLT_SSH_COMMAND="ssh -i $BATS_TEST_TMPDIR/ssh_key -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
export DOLT_SSH_EXEC_PATH="$(command -v dolt)"
mkdir "$BATS_TEST_TMPDIR/remote"
(
cd "$BATS_TEST_TMPDIR/remote"
dolt init
)
REMOTE_URL="ssh://$(whoami)@127.0.0.1:${SSHD_PORT}${BATS_TEST_TMPDIR}/remote"
export REMOTE_URL
}
teardown() {
stop_sql_server
teardown_git_ssh
unset DOLT_SSH_COMMAND DOLT_SSH_EXEC_PATH REMOTE_URL
}
count_ssh_kids() {
local parent="$1"
ps -eo pid,ppid,comm --no-headers 2>/dev/null \
| awk -v p="$parent" '$2==p && $3=="ssh"' \
| wc -l
}
# wait_for_no_ssh_kids polls count_ssh_kids until it reports 0 or a short
# deadline elapses, returning the final count. Close() is synchronous from
# the SQL caller's perspective but the kernel may take a brief moment to
# fully reap the exited child.
wait_for_no_ssh_kids() {
local parent="$1"
local i
for (( i = 0; i < 50; i++ )); do
local n
n="$(count_ssh_kids "$parent")"
if [ "$n" -eq 0 ]; then
echo 0
return
fi
sleep 0.1
done
count_ssh_kids "$parent"
}
@test "ssh-pid-leak: single fetch leaves no orphan ssh process" {
dolt clone "$REMOTE_URL" repo_local
cd repo_local
start_sql_server
server_pid="$SERVER_PID"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_fetch('origin')"
remaining="$(wait_for_no_ssh_kids "$server_pid")"
[ "$remaining" -eq 0 ] || {
echo "expected 0 ssh subprocesses after fetch, got $remaining" >&2
ps -eo pid,ppid,stat,comm --no-headers | awk -v p="$server_pid" '$2==p' >&2
false
}
}
@test "ssh-pid-leak: 10 sequential fetches do not accumulate" {
dolt clone "$REMOTE_URL" repo_local
cd repo_local
start_sql_server
server_pid="$SERVER_PID"
for i in 1 2 3 4 5 6 7 8 9 10; do
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_fetch('origin')"
done
remaining="$(wait_for_no_ssh_kids "$server_pid")"
[ "$remaining" -eq 0 ] || {
echo "expected 0 ssh subprocesses after 10 fetches, got $remaining" >&2
false
}
}
@test "ssh-pid-leak: push leaves no orphan ssh process" {
dolt clone "$REMOTE_URL" repo_local
cd repo_local
dolt sql -q "create table t (id int primary key)"
dolt sql -q "call dolt_commit('-Am', 'add table')"
start_sql_server
server_pid="$SERVER_PID"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_push('origin', 'main')"
remaining="$(wait_for_no_ssh_kids "$server_pid")"
[ "$remaining" -eq 0 ]
}
@test "ssh-pid-leak: pull leaves no orphan ssh process" {
dolt clone "$REMOTE_URL" repo_local
cd repo_local
start_sql_server
server_pid="$SERVER_PID"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_pull('origin', 'main')"
remaining="$(wait_for_no_ssh_kids "$server_pid")"
[ "$remaining" -eq 0 ]
}
@test "ssh-pid-leak: mixed fetch+pull+push do not accumulate" {
dolt clone "$REMOTE_URL" repo_local
cd repo_local
start_sql_server
server_pid="$SERVER_PID"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_fetch('origin')"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_pull('origin', 'main')"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; create table t (id int primary key); call dolt_commit('-Am', 'add table');"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_push('origin', 'main')"
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_fetch('origin')"
remaining="$(wait_for_no_ssh_kids "$server_pid")"
[ "$remaining" -eq 0 ]
}
@test "ssh-pid-leak: concurrent fetches all clean up" {
dolt clone "$REMOTE_URL" repo_local
cd repo_local
start_sql_server
server_pid="$SERVER_PID"
pids=()
for i in 1 2 3 4 5; do
dolt --host=127.0.0.1 --port=$PORT --no-tls sql -q "use repo_local; call dolt_fetch('origin')" &
pids+=($!)
done
for p in "${pids[@]}"; do wait $p; done
remaining="$(wait_for_no_ssh_kids "$server_pid")"
[ "$remaining" -eq 0 ]
}