diff --git a/tests/test-lfs-serve-access.t b/tests/test-lfs-serve-access.t --- a/tests/test-lfs-serve-access.t +++ b/tests/test-lfs-serve-access.t @@ -4,7 +4,6 @@ > [extensions] > lfs= > [lfs] - > url=http://localhost:$HGPORT/.git/info/lfs > track=all() > [web] > push_ssl = False @@ -149,3 +148,187 @@ Blob URIs are correct when --prefix is u $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 < 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 +