robustcheckout: add test for server failure during clone (
bug 1291926); r?glob
We're seeing a lot of "stream ended unexpectedly" failures when
cloning/pulling in automation. As far as I can tell, this is due
to dropped connections. Unreliable networks are unreliable.
This commit adds a test to reproduce the failure by implementing an
extension that wraps the server response serving function and has it
return early after a configured number of bytes have been sent.
This test will allow us to verify that automatric retry logic
(to be introduced in the next commit) works as advertised.
MozReview-Commit-ID: 96p8L7jDHeE
new file mode 100644
--- /dev/null
+++ b/hgext/robustcheckout/tests/badserver.py
@@ -0,0 +1,41 @@
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from mercurial.hgweb import (
+ hgweb_mod,
+)
+
+def extsetup(ui):
+ class droppinghgweb(hgweb_mod.hgweb):
+ def _runwsgi(self, req, repo):
+ bytelimit = repo.ui.configint('badserver', 'bytelimit')
+
+ untilgoodcount = repo.vfs.tryread('badserveruntilgood')
+ if untilgoodcount:
+ untilgoodcount = int(untilgoodcount)
+
+ # This check is different than the one above because it is
+ # comparing an int type instead of a string. The first check could
+ # be true for "0" but this check would be false for int(0).
+ if untilgoodcount:
+ repo.vfs.write('badserveruntilgood', str(untilgoodcount - 1))
+
+ bytecount = 0
+ for r in super(droppinghgweb, self)._runwsgi(req, repo):
+ # We serviced the requested number of requests. Do everything
+ # like normal.
+ if untilgoodcount == 0:
+ yield r
+ continue
+
+ if bytelimit:
+ if bytecount + len(r) >= bytelimit:
+ yield r[0:bytelimit - bytecount]
+ return
+
+ bytecount += len(r)
+ yield r
+
+ bytecount += len(r)
+
+ hgweb_mod.hgweb = droppinghgweb
--- a/hgext/robustcheckout/tests/helpers.sh
+++ b/hgext/robustcheckout/tests/helpers.sh
@@ -4,16 +4,17 @@ pool = $TESTTMP/share
[extensions]
robustcheckout = $TESTDIR/hgext/robustcheckout
EOF
mkdir server
hg init server/repo0
hg init server/repo1
+hg init server/bad-server
cd server/repo0
touch foo
hg -q commit -A -m initial0
echo 1 > foo
hg commit -m 1
hg -q up -r 0
@@ -21,21 +22,35 @@ hg -q branch branch1
echo branch1 > foo
hg commit -m branch1
cd ../repo1
touch foo
hg -q commit -A -m initial1
echo 1 > foo
hg commit -m 1
+cd ../bad-server
+
+cat >> .hg/hgrc << EOF
+[extensions]
+badserver = $TESTDIR/hgext/robustcheckout/tests/badserver.py
+EOF
+
+touch foo
+hg -q commit -A -m initial
+echo 1 > foo
+hg commit -m 'commit 1'
+
cd ..
hg -q clone -r 0 --pull -U repo0 repo0-upstream
cat >> hgweb.conf << EOF
[paths]
/ = $TESTTMP/server/*
+[web]
+refreshinterval = -1
EOF
hg serve -d -p $HGPORT --pid-file hg.pid --web-conf hgweb.conf
cat hg.pid >> $DAEMON_PIDS
-cd $TESTTMP
\ No newline at end of file
+cd $TESTTMP
new file mode 100644
--- /dev/null
+++ b/hgext/robustcheckout/tests/test-server-failure.t
@@ -0,0 +1,34 @@
+ $ . $TESTDIR/hgext/robustcheckout/tests/helpers.sh
+
+Extension works with default config
+
+ $ hg robustcheckout http://localhost:$HGPORT/bad-server good-clone --revision 94086d65796f
+ ensuring http://localhost:$HGPORT/bad-server@94086d65796f is available at good-clone
+ (sharing from new pooled repository 96ee1d7354c4ad7372047672c36a1f561e3a6a4c)
+ requesting all changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 1 files
+ searching for changes
+ no changes found
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ updated to 94086d65796fd7fc8f957a2c5548db17a13f1f1f
+
+Server abort part way through response is handled
+TODO not yet implemented properly
+
+ $ cp -a server/bad-server server/bad-server-bytelimit
+
+ $ cat >> server/bad-server-bytelimit/.hg/hgrc << EOF
+ > [badserver]
+ > bytelimit = 11
+ > EOF
+
+ $ hg robustcheckout http://localhost:$HGPORT/bad-server-bytelimit byte-limit --revision 94086d65796f
+ ensuring http://localhost:$HGPORT/bad-server-bytelimit@94086d65796f is available at byte-limit
+ (sharing from existing pooled repository 96ee1d7354c4ad7372047672c36a1f561e3a6a4c)
+ searching for changes
+ no changes found
+ abort: stream ended unexpectedly (got 3 bytes, expected 4)
+ [255]