blob: a8429ef3c3d09235a4cf5a51c7cfe66557b13b6f [file] [edit]
#!/bin/sh
test_description='apply-one-time-script CGI helper is safe under concurrent requests'
. ./test-lib.sh
HELPER="$TEST_DIRECTORY/lib-httpd/apply-one-time-script.sh"
test_expect_success PIPE 'helper only serves one rewritten response for concurrent requests' '
mkdir workdir fakebin &&
ENTERED="$PWD/entered" &&
GATE="$PWD/gate" &&
export ENTERED GATE &&
mkfifo "$ENTERED" "$GATE" &&
# A stub git-http-backend that returns a response based on
# $ROLE. For $ROLE = modify, return the response string
# "packfile", which ends up being modified by the example
# one-time-script below.
#
# Otherwise, run the branch returning a response that
# should be passed through, and block until released
# by "read -r $GATE".
write_script fakebin/git-http-backend <<-\EOF &&
printf "Status: 200 OK\r\n"
printf "Content-Type: application/x-git-result\r\n"
printf "\r\n"
if test "$ROLE" = modify
then
printf "packfile\n"
else
echo entered >"$ENTERED"
read -r released <"$GATE"
printf "refs\n"
fi
EOF
# An example one-time-script for apply-one-time-script
# to execute. Checks for "packfile" in the response
# that will be returned, and replaces it with a
# modified response. Passes through responses without
# "packfile" in them.
write_script workdir/one-time-script <<-\EOF &&
if grep packfile "$1" >/dev/null
then
sed "/packfile/q" "$1" &&
printf "REPLACED\n"
else
cat "$1"
fi
EOF
GIT_EXEC_PATH="$PWD/fakebin" &&
export GIT_EXEC_PATH &&
# Ensure $GATE has a reader so the test does not block indefinitely if
# the helper is buggy and "echo released >&9" below does not unblock
# the unmodified response gate.
exec 9<>"$GATE" &&
# Launch the passthrough request in the background. Record its pid
# so it can be killed when the test finishes if, for some reason, the
# request stays blocked and would stall a test runner.
{ (
cd workdir &&
ROLE=passthrough sh "$HELPER" >../passthrough.out 2>../passthrough.err
) & } &&
passthrough_pid=$! &&
test_when_finished "kill $passthrough_pid 2>/dev/null || :" &&
# Wait until the passthrough request is "in-flight" and paused
# mid-response.
read -r entered <"$ENTERED" &&
# Launch the request for a modified response while the passthrough
# request is concurrently "in-flight" and paused.
(
cd workdir &&
ROLE=modify sh "$HELPER" >../modify.out 2>../modify.err
) &&
# Unblock the passthrough request, allowing git-http-backend to
# complete its response.
echo released >&9 &&
{ wait "$passthrough_pid" || :; } &&
test_must_be_empty passthrough.err &&
test_must_be_empty modify.err &&
test_grep "Status: 200 OK" passthrough.out &&
test_grep "Status: 200 OK" modify.out &&
test_grep REPLACED modify.out &&
test_grep ! REPLACED passthrough.out &&
test_grep refs passthrough.out
'
test_done