##// END OF EJS Templates
test: add a push race case where the racing client create a new head...
marmoute -
r32632:090a6fe6 default
parent child Browse files
Show More
@@ -1,280 +1,386 b''
1 ============================================================================================
1 ============================================================================================
2 Test cases where there are race condition between two clients pushing to the same repository
2 Test cases where there are race condition between two clients pushing to the same repository
3 ============================================================================================
3 ============================================================================================
4
4
5 This file tests cases where two clients push to a server at the same time. The
5 This file tests cases where two clients push to a server at the same time. The
6 "raced" client is done preparing it push bundle when the "racing" client
6 "raced" client is done preparing it push bundle when the "racing" client
7 perform its push. The "raced" client starts its actual push after the "racing"
7 perform its push. The "raced" client starts its actual push after the "racing"
8 client push is fully complete.
8 client push is fully complete.
9
9
10 A set of extension and shell functions ensures this scheduling.
10 A set of extension and shell functions ensures this scheduling.
11
11
12 $ cat >> delaypush.py << EOF
12 $ cat >> delaypush.py << EOF
13 > """small extension orchestrate push race
13 > """small extension orchestrate push race
14 >
14 >
15 > Client with the extensions will create a file when ready and get stuck until
15 > Client with the extensions will create a file when ready and get stuck until
16 > a file is created."""
16 > a file is created."""
17 >
17 >
18 > import atexit
18 > import atexit
19 > import errno
19 > import errno
20 > import os
20 > import os
21 > import time
21 > import time
22 >
22 >
23 > from mercurial import (
23 > from mercurial import (
24 > exchange,
24 > exchange,
25 > extensions,
25 > extensions,
26 > )
26 > )
27 >
27 >
28 > def delaypush(orig, pushop):
28 > def delaypush(orig, pushop):
29 > # notify we are done preparing
29 > # notify we are done preparing
30 > readypath = pushop.repo.ui.config('delaypush', 'ready-path', None)
30 > readypath = pushop.repo.ui.config('delaypush', 'ready-path', None)
31 > if readypath is not None:
31 > if readypath is not None:
32 > with open(readypath, 'w') as r:
32 > with open(readypath, 'w') as r:
33 > r.write('foo')
33 > r.write('foo')
34 > pushop.repo.ui.status('wrote ready: %s\n' % readypath)
34 > pushop.repo.ui.status('wrote ready: %s\n' % readypath)
35 > # now wait for the other process to be done
35 > # now wait for the other process to be done
36 > watchpath = pushop.repo.ui.config('delaypush', 'release-path', None)
36 > watchpath = pushop.repo.ui.config('delaypush', 'release-path', None)
37 > if watchpath is not None:
37 > if watchpath is not None:
38 > pushop.repo.ui.status('waiting on: %s\n' % watchpath)
38 > pushop.repo.ui.status('waiting on: %s\n' % watchpath)
39 > limit = 100
39 > limit = 100
40 > while 0 < limit and not os.path.exists(watchpath):
40 > while 0 < limit and not os.path.exists(watchpath):
41 > limit -= 1
41 > limit -= 1
42 > time.sleep(0.1)
42 > time.sleep(0.1)
43 > if limit <= 0:
43 > if limit <= 0:
44 > repo.ui.warn('exiting without watchfile: %s' % watchpath)
44 > repo.ui.warn('exiting without watchfile: %s' % watchpath)
45 > else:
45 > else:
46 > # delete the file at the end of the push
46 > # delete the file at the end of the push
47 > def delete():
47 > def delete():
48 > try:
48 > try:
49 > os.unlink(watchpath)
49 > os.unlink(watchpath)
50 > except OSError as exc:
50 > except OSError as exc:
51 > if exc.errno != errno.ENOENT:
51 > if exc.errno != errno.ENOENT:
52 > raise
52 > raise
53 > atexit.register(delete)
53 > atexit.register(delete)
54 > return orig(pushop)
54 > return orig(pushop)
55 >
55 >
56 > def uisetup(ui):
56 > def uisetup(ui):
57 > extensions.wrapfunction(exchange, '_pushbundle2', delaypush)
57 > extensions.wrapfunction(exchange, '_pushbundle2', delaypush)
58 > EOF
58 > EOF
59
59
60 $ waiton () {
60 $ waiton () {
61 > # wait for a file to be created (then delete it)
61 > # wait for a file to be created (then delete it)
62 > count=100
62 > count=100
63 > while [ ! -f $1 ] ;
63 > while [ ! -f $1 ] ;
64 > do
64 > do
65 > sleep 0.1;
65 > sleep 0.1;
66 > count=`expr $count - 1`;
66 > count=`expr $count - 1`;
67 > if [ $count -lt 0 ];
67 > if [ $count -lt 0 ];
68 > then
68 > then
69 > break
69 > break
70 > fi;
70 > fi;
71 > done
71 > done
72 > [ -f $1 ] || echo "ready file still missing: $1"
72 > [ -f $1 ] || echo "ready file still missing: $1"
73 > rm -f $1
73 > rm -f $1
74 > }
74 > }
75
75
76 $ release () {
76 $ release () {
77 > # create a file and wait for it be deleted
77 > # create a file and wait for it be deleted
78 > count=100
78 > count=100
79 > touch $1
79 > touch $1
80 > while [ -f $1 ] ;
80 > while [ -f $1 ] ;
81 > do
81 > do
82 > sleep 0.1;
82 > sleep 0.1;
83 > count=`expr $count - 1`;
83 > count=`expr $count - 1`;
84 > if [ $count -lt 0 ];
84 > if [ $count -lt 0 ];
85 > then
85 > then
86 > break
86 > break
87 > fi;
87 > fi;
88 > done
88 > done
89 > [ ! -f $1 ] || echo "delay file still exist: $1"
89 > [ ! -f $1 ] || echo "delay file still exist: $1"
90 > }
90 > }
91
91
92 $ cat >> $HGRCPATH << EOF
92 $ cat >> $HGRCPATH << EOF
93 > [ui]
93 > [ui]
94 > ssh = python "$TESTDIR/dummyssh"
94 > ssh = python "$TESTDIR/dummyssh"
95 > # simplify output
95 > # simplify output
96 > logtemplate = {node|short} {desc} ({branch})
96 > logtemplate = {node|short} {desc} ({branch})
97 > [alias]
97 > [alias]
98 > graph = log -G --rev 'sort(all(), "topo")'
98 > graph = log -G --rev 'sort(all(), "topo")'
99 > EOF
99 > EOF
100
100
101 Setup
101 Setup
102 -----
102 -----
103
103
104 create a repo with one root
104 create a repo with one root
105
105
106 $ hg init server
106 $ hg init server
107 $ cd server
107 $ cd server
108 $ echo root > root
108 $ echo root > root
109 $ hg ci -Am "C-ROOT"
109 $ hg ci -Am "C-ROOT"
110 adding root
110 adding root
111 $ cd ..
111 $ cd ..
112
112
113 clone it in two clients
113 clone it in two clients
114
114
115 $ hg clone ssh://user@dummy/server client-racy
115 $ hg clone ssh://user@dummy/server client-racy
116 requesting all changes
116 requesting all changes
117 adding changesets
117 adding changesets
118 adding manifests
118 adding manifests
119 adding file changes
119 adding file changes
120 added 1 changesets with 1 changes to 1 files
120 added 1 changesets with 1 changes to 1 files
121 updating to branch default
121 updating to branch default
122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 $ hg clone ssh://user@dummy/server client-other
123 $ hg clone ssh://user@dummy/server client-other
124 requesting all changes
124 requesting all changes
125 adding changesets
125 adding changesets
126 adding manifests
126 adding manifests
127 adding file changes
127 adding file changes
128 added 1 changesets with 1 changes to 1 files
128 added 1 changesets with 1 changes to 1 files
129 updating to branch default
129 updating to branch default
130 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
130 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
131
131
132 setup one to allow race on push
132 setup one to allow race on push
133
133
134 $ cat >> client-racy/.hg/hgrc << EOF
134 $ cat >> client-racy/.hg/hgrc << EOF
135 > [extensions]
135 > [extensions]
136 > delaypush = $TESTTMP/delaypush.py
136 > delaypush = $TESTTMP/delaypush.py
137 > [delaypush]
137 > [delaypush]
138 > ready-path = $TESTTMP/readyfile
138 > ready-path = $TESTTMP/readyfile
139 > release-path = $TESTTMP/watchfile
139 > release-path = $TESTTMP/watchfile
140 > EOF
140 > EOF
141
141
142 Simple race, both try to push to the server at the same time
142 Simple race, both try to push to the server at the same time
143 ------------------------------------------------------------
143 ------------------------------------------------------------
144
144
145 Both try to replace the same head
145 Both try to replace the same head
146
146
147 # a
147 # a
148 # | b
148 # | b
149 # |/
149 # |/
150 # *
150 # *
151
151
152 Creating changesets
152 Creating changesets
153
153
154 $ echo b > client-other/a
154 $ echo b > client-other/a
155 $ hg -R client-other/ add client-other/a
155 $ hg -R client-other/ add client-other/a
156 $ hg -R client-other/ commit -m "C-A"
156 $ hg -R client-other/ commit -m "C-A"
157 $ echo b > client-racy/b
157 $ echo b > client-racy/b
158 $ hg -R client-racy/ add client-racy/b
158 $ hg -R client-racy/ add client-racy/b
159 $ hg -R client-racy/ commit -m "C-B"
159 $ hg -R client-racy/ commit -m "C-B"
160
160
161 Pushing
161 Pushing
162
162
163 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
163 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
164
164
165 $ waiton $TESTTMP/readyfile
165 $ waiton $TESTTMP/readyfile
166
166
167 $ hg -R client-other push -r 'tip'
167 $ hg -R client-other push -r 'tip'
168 pushing to ssh://user@dummy/server
168 pushing to ssh://user@dummy/server
169 searching for changes
169 searching for changes
170 remote: adding changesets
170 remote: adding changesets
171 remote: adding manifests
171 remote: adding manifests
172 remote: adding file changes
172 remote: adding file changes
173 remote: added 1 changesets with 1 changes to 1 files
173 remote: added 1 changesets with 1 changes to 1 files
174
174
175 $ release $TESTTMP/watchfile
175 $ release $TESTTMP/watchfile
176
176
177 Check the result of the push
177 Check the result of the push
178
178
179 $ cat ./push-log
179 $ cat ./push-log
180 pushing to ssh://user@dummy/server
180 pushing to ssh://user@dummy/server
181 searching for changes
181 searching for changes
182 wrote ready: $TESTTMP/readyfile
182 wrote ready: $TESTTMP/readyfile
183 waiting on: $TESTTMP/watchfile
183 waiting on: $TESTTMP/watchfile
184 abort: push failed:
184 abort: push failed:
185 'repository changed while pushing - please try again'
185 'repository changed while pushing - please try again'
186
186
187 $ hg -R server graph
187 $ hg -R server graph
188 o 98217d5a1659 C-A (default)
188 o 98217d5a1659 C-A (default)
189 |
189 |
190 @ 842e2fac6304 C-ROOT (default)
190 @ 842e2fac6304 C-ROOT (default)
191
191
192
192
193 Pushing on two different heads
193 Pushing on two different heads
194 ------------------------------
194 ------------------------------
195
195
196 Both try to replace a different head
196 Both try to replace a different head
197
197
198 # a b
198 # a b
199 # | |
199 # | |
200 # * *
200 # * *
201 # |/
201 # |/
202 # *
202 # *
203
203
204 (resync-all)
204 (resync-all)
205
205
206 $ hg -R ./server pull ./client-racy
206 $ hg -R ./server pull ./client-racy
207 pulling from ./client-racy
207 pulling from ./client-racy
208 searching for changes
208 searching for changes
209 adding changesets
209 adding changesets
210 adding manifests
210 adding manifests
211 adding file changes
211 adding file changes
212 added 1 changesets with 1 changes to 1 files (+1 heads)
212 added 1 changesets with 1 changes to 1 files (+1 heads)
213 (run 'hg heads' to see heads, 'hg merge' to merge)
213 (run 'hg heads' to see heads, 'hg merge' to merge)
214 $ hg -R ./client-other pull
214 $ hg -R ./client-other pull
215 pulling from ssh://user@dummy/server
215 pulling from ssh://user@dummy/server
216 searching for changes
216 searching for changes
217 adding changesets
217 adding changesets
218 adding manifests
218 adding manifests
219 adding file changes
219 adding file changes
220 added 1 changesets with 1 changes to 1 files (+1 heads)
220 added 1 changesets with 1 changes to 1 files (+1 heads)
221 (run 'hg heads' to see heads, 'hg merge' to merge)
221 (run 'hg heads' to see heads, 'hg merge' to merge)
222 $ hg -R ./client-racy pull
222 $ hg -R ./client-racy pull
223 pulling from ssh://user@dummy/server
223 pulling from ssh://user@dummy/server
224 searching for changes
224 searching for changes
225 adding changesets
225 adding changesets
226 adding manifests
226 adding manifests
227 adding file changes
227 adding file changes
228 added 1 changesets with 1 changes to 1 files (+1 heads)
228 added 1 changesets with 1 changes to 1 files (+1 heads)
229 (run 'hg heads' to see heads, 'hg merge' to merge)
229 (run 'hg heads' to see heads, 'hg merge' to merge)
230
230
231 $ hg -R server graph
231 $ hg -R server graph
232 o a9149a1428e2 C-B (default)
232 o a9149a1428e2 C-B (default)
233 |
233 |
234 | o 98217d5a1659 C-A (default)
234 | o 98217d5a1659 C-A (default)
235 |/
235 |/
236 @ 842e2fac6304 C-ROOT (default)
236 @ 842e2fac6304 C-ROOT (default)
237
237
238
238
239 Creating changesets
239 Creating changesets
240
240
241 $ echo aa >> client-other/a
241 $ echo aa >> client-other/a
242 $ hg -R client-other/ commit -m "C-C"
242 $ hg -R client-other/ commit -m "C-C"
243 $ echo bb >> client-racy/b
243 $ echo bb >> client-racy/b
244 $ hg -R client-racy/ commit -m "C-D"
244 $ hg -R client-racy/ commit -m "C-D"
245
245
246 Pushing
246 Pushing
247
247
248 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
248 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
249
249
250 $ waiton $TESTTMP/readyfile
250 $ waiton $TESTTMP/readyfile
251
251
252 $ hg -R client-other push -r 'tip'
252 $ hg -R client-other push -r 'tip'
253 pushing to ssh://user@dummy/server
253 pushing to ssh://user@dummy/server
254 searching for changes
254 searching for changes
255 remote: adding changesets
255 remote: adding changesets
256 remote: adding manifests
256 remote: adding manifests
257 remote: adding file changes
257 remote: adding file changes
258 remote: added 1 changesets with 1 changes to 1 files
258 remote: added 1 changesets with 1 changes to 1 files
259
259
260 $ release $TESTTMP/watchfile
260 $ release $TESTTMP/watchfile
261
261
262 Check the result of the push
262 Check the result of the push
263
263
264 $ cat ./push-log
264 $ cat ./push-log
265 pushing to ssh://user@dummy/server
265 pushing to ssh://user@dummy/server
266 searching for changes
266 searching for changes
267 wrote ready: $TESTTMP/readyfile
267 wrote ready: $TESTTMP/readyfile
268 waiting on: $TESTTMP/watchfile
268 waiting on: $TESTTMP/watchfile
269 abort: push failed:
269 abort: push failed:
270 'repository changed while pushing - please try again'
270 'repository changed while pushing - please try again'
271
271
272 $ hg -R server graph
272 $ hg -R server graph
273 o 51c544a58128 C-C (default)
273 o 51c544a58128 C-C (default)
274 |
274 |
275 o 98217d5a1659 C-A (default)
275 o 98217d5a1659 C-A (default)
276 |
276 |
277 | o a9149a1428e2 C-B (default)
277 | o a9149a1428e2 C-B (default)
278 |/
278 |/
279 @ 842e2fac6304 C-ROOT (default)
279 @ 842e2fac6304 C-ROOT (default)
280
280
281 Pushing while someone creates a new head
282 -----------------------------------------
283
284 Pushing a new changeset while someone creates a new branch.
285
286 # a (raced)
287 # |
288 # * b
289 # |/
290 # *
291
292 (resync-all)
293
294 $ hg -R ./server pull ./client-racy
295 pulling from ./client-racy
296 searching for changes
297 adding changesets
298 adding manifests
299 adding file changes
300 added 1 changesets with 1 changes to 1 files
301 (run 'hg update' to get a working copy)
302 $ hg -R ./client-other pull
303 pulling from ssh://user@dummy/server
304 searching for changes
305 adding changesets
306 adding manifests
307 adding file changes
308 added 1 changesets with 1 changes to 1 files
309 (run 'hg update' to get a working copy)
310 $ hg -R ./client-racy pull
311 pulling from ssh://user@dummy/server
312 searching for changes
313 adding changesets
314 adding manifests
315 adding file changes
316 added 1 changesets with 1 changes to 1 files
317 (run 'hg update' to get a working copy)
318
319 $ hg -R server graph
320 o 59e76faf78bd C-D (default)
321 |
322 o a9149a1428e2 C-B (default)
323 |
324 | o 51c544a58128 C-C (default)
325 | |
326 | o 98217d5a1659 C-A (default)
327 |/
328 @ 842e2fac6304 C-ROOT (default)
329
330
331 Creating changesets
332
333 (new head)
334
335 $ hg -R client-other/ up 'desc("C-A")'
336 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 $ echo aaa >> client-other/a
338 $ hg -R client-other/ commit -m "C-E"
339 created new head
340
341 (children of existing head)
342
343 $ hg -R client-racy/ up 'desc("C-C")'
344 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
345 $ echo bbb >> client-racy/a
346 $ hg -R client-racy/ commit -m "C-F"
347
348 Pushing
349
350 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
351
352 $ waiton $TESTTMP/readyfile
353
354 $ hg -R client-other push -fr 'tip'
355 pushing to ssh://user@dummy/server
356 searching for changes
357 remote: adding changesets
358 remote: adding manifests
359 remote: adding file changes
360 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
361
362 $ release $TESTTMP/watchfile
363
364 Check the result of the push
365
366 $ cat ./push-log
367 pushing to ssh://user@dummy/server
368 searching for changes
369 wrote ready: $TESTTMP/readyfile
370 waiting on: $TESTTMP/watchfile
371 abort: push failed:
372 'repository changed while pushing - please try again'
373
374 $ hg -R server graph
375 o d603e2c0cdd7 C-E (default)
376 |
377 | o 51c544a58128 C-C (default)
378 |/
379 o 98217d5a1659 C-A (default)
380 |
381 | o 59e76faf78bd C-D (default)
382 | |
383 | o a9149a1428e2 C-B (default)
384 |/
385 @ 842e2fac6304 C-ROOT (default)
386
General Comments 0
You need to be logged in to leave comments. Login now