--- a/tests/test-lfs-serve-access.t Sat Apr 14 10:43:19 2018 -0400
+++ b/tests/test-lfs-serve-access.t Sat Apr 07 12:48:21 2018 -0400
@@ -4,7 +4,6 @@
> [extensions]
> lfs=
> [lfs]
- > url=http://localhost:$HGPORT/.git/info/lfs
> track=all()
> [web]
> push_ssl = False
@@ -149,3 +148,187 @@
$LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
$LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
$LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
+
+ $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
+ > import errno
+ > from hgext.lfs import blobstore
+ >
+ > _numverifies = 0
+ > _readerr = True
+ >
+ > def reposetup(ui, repo):
+ > # Nothing to do with a remote repo
+ > if not repo.local():
+ > return
+ >
+ > store = repo.svfs.lfslocalblobstore
+ > class badstore(store.__class__):
+ > def download(self, oid, src):
+ > '''Called in the server to handle reading from the client in a
+ > PUT request.'''
+ > origread = src.read
+ > def _badread(nbytes):
+ > # Simulate bad data/checksum failure from the client
+ > return b'0' * len(origread(nbytes))
+ > src.read = _badread
+ > super(badstore, self).download(oid, src)
+ >
+ > def _read(self, vfs, oid, verify):
+ > '''Called in the server to read data for a GET request, and then
+ > calls self._verify() on it before returning.'''
+ > global _readerr
+ > # One time simulation of a read error
+ > if _readerr:
+ > _readerr = False
+ > raise IOError(errno.EIO, '%s: I/O error' % oid)
+ > # Simulate corrupt content on client download
+ > blobstore._verify(oid, 'dummy content')
+ >
+ > def verify(self, oid):
+ > '''Called in the server to populate the Batch API response,
+ > letting the client re-upload if the file is corrupt.'''
+ > # Fail verify in Batch API for one clone command and one push
+ > # command with an IOError. Then let it through to access other
+ > # functions. Checksum failure is tested elsewhere.
+ > global _numverifies
+ > _numverifies += 1
+ > if _numverifies <= 2:
+ > raise IOError(errno.EIO, '%s: I/O error' % oid)
+ > return super(badstore, self).verify(oid)
+ >
+ > store.__class__ = badstore
+ > EOF
+
+ $ rm -rf `hg config lfs.usercache`
+ $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
+ $ hg --config "lfs.usercache=$TESTTMP/servercache" \
+ > --config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
+ > -R server serve -d \
+ > -p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
+ $ cat hg.pid >> $DAEMON_PIDS
+
+Test an I/O error in localstore.verify() (Batch API) with GET
+
+ $ hg clone http://localhost:$HGPORT1 httpclone2
+ requesting all changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files
+ new changesets 525251863cad
+ updating to branch default
+ abort: LFS server error for "lfs.bin": Internal server error!
+ [255]
+
+Test an I/O error in localstore.verify() (Batch API) with PUT
+
+ $ echo foo > client/lfs.bin
+ $ hg -R client ci -m 'mod lfs'
+ $ hg -R client push http://localhost:$HGPORT1
+ pushing to http://localhost:$HGPORT1/
+ searching for changes
+ abort: LFS server error for "unknown": Internal server error!
+ [255]
+TODO: figure out how to associate the file name in the error above
+
+Test a bad checksum sent by the client in the transfer API
+
+ $ hg -R client push http://localhost:$HGPORT1
+ pushing to http://localhost:$HGPORT1/
+ searching for changes
+ abort: HTTP error: HTTP Error 500: Internal Server Error (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)!
+ [255]
+
+ $ echo 'test lfs file' > server/lfs3.bin
+ $ hg --config experimental.lfs.disableusercache=True \
+ > -R server ci -Aqm 'another lfs file'
+ $ hg -R client pull -q http://localhost:$HGPORT1
+
+Test an I/O error during the processing of the GET request
+
+ $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
+ > -R client update -r tip
+ abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
+ [255]
+
+Test a checksum failure during the processing of the GET request
+
+ $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
+ > -R client update -r tip
+ abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
+ [255]
+
+ $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+
+ $ cat $TESTTMP/access.log
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c HTTP/1.1" 500 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=525251863cad618e55d483555f3d00a2ca99597e&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
+ $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
+ $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+ $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
+
+ $ grep -v ' File "' $TESTTMP/errors.log
+ $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c': (glob)
+ Traceback (most recent call last):
+ self.do_write()
+ self.do_hgweb()
+ for chunk in self.server.application(env, self._start_response):
+ for r in self._runwsgi(req, res, repo):
+ rctx, req, res, self.check_perm)
+ return func(*(args + a), **kw)
+ lambda perm:
+ localstore.download(oid, req.bodyfh)
+ super(badstore, self).download(oid, src)
+ raise error.Abort(_('corrupt remote lfs object: %s') % oid)
+ Abort: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
+
+ $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
+ Traceback (most recent call last):
+ self.do_write()
+ self.do_hgweb()
+ for chunk in self.server.application(env, self._start_response):
+ for r in self._runwsgi(req, res, repo):
+ rctx, req, res, self.check_perm)
+ return func(*(args + a), **kw)
+ lambda perm:
+ res.setbodybytes(localstore.read(oid))
+ blob = self._read(self.vfs, oid, verify)
+ raise IOError(errno.EIO, '%s: I/O error' % oid)
+ IOError: [Errno 5] 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d: I/O error
+
+ $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
+ Traceback (most recent call last):
+ self.do_write()
+ self.do_hgweb()
+ for chunk in self.server.application(env, self._start_response):
+ for r in self._runwsgi(req, res, repo):
+ rctx, req, res, self.check_perm)
+ return func(*(args + a), **kw)
+ lambda perm:
+ res.setbodybytes(localstore.read(oid))
+ blob = self._read(self.vfs, oid, verify)
+ blobstore._verify(oid, 'dummy content')
+ hint=_('run hg verify'))
+ Abort: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d
+