upload-pack: test negotiation with changing repository
Add tests to check the behavior of fetching from a repository which changes between rounds of negotiation (for example, when different servers in a load-balancing agreement participate in the same stateless RPC negotiation). This forms a baseline of comparison to the ref-in-want functionality (which will be introduced to the client in subsequent commits), and ensures that subsequent commits do not change existing behavior. As part of this effort, a mechanism to substitute strings in a single HTTP response is added. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Brandon Williams committed
Jun 27, 2018 at 15:30 UTC
3374292e55564fa6107b31a63a5e5432cd8c2265
4 files changed
+99
t/lib-httpd.sh
+1
@@ -132,6 +132,7 @@ prepare_httpd() {
132
cp "$TEST_PATH"/passwd "$HTTPD_ROOT_PATH"
133
install_script broken-smart-http.sh
134
install_script error.sh
135
+ install_script apply-one-time-sed.sh
136
137
ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
138
t/lib-httpd/apache.conf
+8
@@ -111,9 +111,14 @@ Alias /auth/dumb/ www/auth/dumb/
111
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
112
SetEnv GIT_HTTP_EXPORT_ALL
113
</LocationMatch>
114
+<LocationMatch /one_time_sed/>
115
+ SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
116
+ SetEnv GIT_HTTP_EXPORT_ALL
117
+</LocationMatch>
118
ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
119
ScriptAlias /broken_smart/ broken-smart-http.sh/
120
ScriptAlias /error/ error.sh/
121
+ScriptAliasMatch /one_time_sed/(.*) apply-one-time-sed.sh/$1
122
<Directory ${GIT_EXEC_PATH}>
123
Options FollowSymlinks
124
</Directory>
@@ -123,6 +128,9 @@ ScriptAlias /error/ error.sh/
128
<Files error.sh>
129
Options ExecCGI
130
</Files>
131
+<Files apply-one-time-sed.sh>
132
+ Options ExecCGI
133
+</Files>
134
<Files ${GIT_EXEC_PATH}/git-http-backend>
135
Options ExecCGI
136
</Files>
t/lib-httpd/apply-one-time-sed.sh
new
+22
@@ -0,0 +1,22 @@
1
+#!/bin/sh
2
+
3
+# If "one-time-sed" exists in $HTTPD_ROOT_PATH, run sed on the HTTP response,
4
+# using the contents of "one-time-sed" as the sed command to be run. If the
5
+# response was modified as a result, delete "one-time-sed" so that subsequent
6
+# HTTP responses are no longer modified.
7
+#
8
+# This can be used to simulate the effects of the repository changing in
9
+# between HTTP request-response pairs.
10
+if [ -e one-time-sed ]; then
11
+ "$GIT_EXEC_PATH/git-http-backend" >out
12
+ sed "$(cat one-time-sed)" <out >out_modified
13
+
14
+ if diff out out_modified >/dev/null; then
15
+ cat out
16
+ else
17
+ cat out_modified
18
+ rm one-time-sed
19
+ fi
20
+else
21
+ "$GIT_EXEC_PATH/git-http-backend"
22
+fi
t/t5703-upload-pack-ref-in-want.sh
+68
@@ -157,4 +157,72 @@ test_expect_success 'want-ref with ref we already have commit for' '
157
check_output
158
'
159
160
+. "$TEST_DIRECTORY"/lib-httpd.sh
161
+start_httpd
162
+
163
+REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo"
164
+LOCAL_PRISTINE="$(pwd)/local_pristine"
165
+
166
+test_expect_success 'setup repos for change-while-negotiating test' '
167
+ (
168
+ git init "$REPO" &&
169
+ cd "$REPO" &&
170
+ >.git/git-daemon-export-ok &&
171
+ test_commit m1 &&
172
+ git tag -d m1 &&
173
+
174
+ # Local repo with many commits (so that negotiation will take
175
+ # more than 1 request/response pair)
176
+ git clone "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" "$LOCAL_PRISTINE" &&
177
+ cd "$LOCAL_PRISTINE" &&
178
+ git checkout -b side &&
179
+ for i in $(seq 1 33); do test_commit s$i; done &&
180
+
181
+ # Add novel commits to upstream
182
+ git checkout master &&
183
+ cd "$REPO" &&
184
+ test_commit m2 &&
185
+ test_commit m3 &&
186
+ git tag -d m2 m3
187
+ ) &&
188
+ git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_sed/repo" &&
189
+ git -C "$LOCAL_PRISTINE" config protocol.version 2
190
+'
191
+
192
+inconsistency () {
193
+ # Simulate that the server initially reports $2 as the ref
194
+ # corresponding to $1, and after that, $1 as the ref corresponding to
195
+ # $1. This corresponds to the real-life situation where the server's
196
+ # repository appears to change during negotiation, for example, when
197
+ # different servers in a load-balancing arrangement serve (stateless)
198
+ # RPCs during a single negotiation.
199
+ printf "s/%s/%s/" \
200
+ $(git -C "$REPO" rev-parse $1 | tr -d "\n") \
201
+ $(git -C "$REPO" rev-parse $2 | tr -d "\n") \
202
+ >"$HTTPD_ROOT_PATH/one-time-sed"
203
+}
204
+
205
+test_expect_success 'server is initially ahead - no ref in want' '
206
+ git -C "$REPO" config uploadpack.allowRefInWant false &&
207
+ rm -rf local &&
208
+ cp -r "$LOCAL_PRISTINE" local &&
209
+ inconsistency master 1234567890123456789012345678901234567890 &&
210
+ test_must_fail git -C local fetch 2>err &&
211
+ grep "ERR upload-pack: not our ref" err
212
+'
213
+
214
+test_expect_success 'server is initially behind - no ref in want' '
215
+ git -C "$REPO" config uploadpack.allowRefInWant false &&
216
+ rm -rf local &&
217
+ cp -r "$LOCAL_PRISTINE" local &&
218
+ inconsistency master "master^" &&
219
+ git -C local fetch &&
220
+
221
+ git -C "$REPO" rev-parse --verify "master^" >expected &&
222
+ git -C local rev-parse --verify refs/remotes/origin/master >actual &&
223
+ test_cmp expected actual
224
+'
225
+
226
+stop_httpd
227
+
228
test_done