##// END OF EJS Templates
test: add a push race case where each client replaces a different head...
marmoute -
r32631:63afbc74 default
parent child Browse files
Show More
@@ -1,191 +1,280 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
193 Pushing on two different heads
194 ------------------------------
195
196 Both try to replace a different head
197
198 # a b
199 # | |
200 # * *
201 # |/
202 # *
203
204 (resync-all)
205
206 $ hg -R ./server pull ./client-racy
207 pulling from ./client-racy
208 searching for changes
209 adding changesets
210 adding manifests
211 adding file changes
212 added 1 changesets with 1 changes to 1 files (+1 heads)
213 (run 'hg heads' to see heads, 'hg merge' to merge)
214 $ hg -R ./client-other pull
215 pulling from ssh://user@dummy/server
216 searching for changes
217 adding changesets
218 adding manifests
219 adding file changes
220 added 1 changesets with 1 changes to 1 files (+1 heads)
221 (run 'hg heads' to see heads, 'hg merge' to merge)
222 $ hg -R ./client-racy pull
223 pulling from ssh://user@dummy/server
224 searching for changes
225 adding changesets
226 adding manifests
227 adding file changes
228 added 1 changesets with 1 changes to 1 files (+1 heads)
229 (run 'hg heads' to see heads, 'hg merge' to merge)
230
231 $ hg -R server graph
232 o a9149a1428e2 C-B (default)
233 |
234 | o 98217d5a1659 C-A (default)
235 |/
236 @ 842e2fac6304 C-ROOT (default)
237
238
239 Creating changesets
240
241 $ echo aa >> client-other/a
242 $ hg -R client-other/ commit -m "C-C"
243 $ echo bb >> client-racy/b
244 $ hg -R client-racy/ commit -m "C-D"
245
246 Pushing
247
248 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
249
250 $ waiton $TESTTMP/readyfile
251
252 $ hg -R client-other push -r 'tip'
253 pushing to ssh://user@dummy/server
254 searching for changes
255 remote: adding changesets
256 remote: adding manifests
257 remote: adding file changes
258 remote: added 1 changesets with 1 changes to 1 files
259
260 $ release $TESTTMP/watchfile
261
262 Check the result of the push
263
264 $ cat ./push-log
265 pushing to ssh://user@dummy/server
266 searching for changes
267 wrote ready: $TESTTMP/readyfile
268 waiting on: $TESTTMP/watchfile
269 abort: push failed:
270 'repository changed while pushing - please try again'
271
272 $ hg -R server graph
273 o 51c544a58128 C-C (default)
274 |
275 o 98217d5a1659 C-A (default)
276 |
277 | o a9149a1428e2 C-B (default)
278 |/
279 @ 842e2fac6304 C-ROOT (default)
280
General Comments 0
You need to be logged in to leave comments. Login now