97 lines
2.8 KiB
Bash
Executable File
97 lines
2.8 KiB
Bash
Executable File
#!/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
|