svn verify: add a test for corrupt repositories.

This case contains a couple of unlikely (but not impossible) failure
cases that the code previously did not handle. The verifier is updated
to address these, and the output made a bit more consistent.
This commit is contained in:
Dan Villiom Podlaski Christiansen 2011-12-14 00:07:58 +01:00
parent 30ef9363dc
commit 19bb35256e
7 changed files with 259 additions and 18 deletions

View File

@ -66,24 +66,21 @@ def verify(ui, repo, args=None, **opts):
except error.LookupError:
result = 1
continue
dmatch = fctx.data() == data
mmatch = fctx.flags() == mode
if not (dmatch and mmatch):
ui.write('difference in file %s\n' % fn)
if not fctx.data() == data:
ui.write('difference in: %s\n' % fn)
result = 1
if not fctx.flags() == mode:
ui.write('wrong flags for: %s\n' % fn)
result = 1
hgfiles = set(ctx) - util.ignoredfiles
if hgfiles != svnfiles:
unexpected = hgfiles - svnfiles
if unexpected:
ui.write('unexpected files:\n')
for f in sorted(unexpected):
ui.write(' %s\n' % f)
for f in sorted(unexpected):
ui.write('unexpected file: %s\n' % f)
missing = svnfiles - hgfiles
if missing:
ui.write('missing files:\n')
for f in sorted(missing):
ui.write(' %s\n' % f)
for f in sorted(missing):
ui.write('missing file: %s\n' % f)
result = 1
util.progress(ui, 'verify', None)

View File

@ -45,6 +45,8 @@ def buildmethod(case, name, layout):
attrs = {'_do_case': _do_case,
}
for case in (f for f in os.listdir(test_util.FIXTURES) if f.endswith('.svndump')):
if case == 'corrupt.svndump':
continue
name = 'test_' + case[:-len('.svndump')]
# Automatic layout branchtag collision exposes a minor defect
# here, but since it isn't a regression we suppress the test case.

View File

@ -21,6 +21,8 @@ _skipshallow = set([
'binaryfiles.svndump',
'binaryfiles-broken.svndump',
'emptyrepo.svndump',
'correct.svndump',
'corrupt.svndump',
])
_skipall = set([
@ -29,6 +31,8 @@ _skipall = set([
_skipstandard = set([
'subdir_is_file_prefix.svndump',
'correct.svndump',
'corrupt.svndump',
])
def _do_case(self, name, stupid, layout):

103
tests/fixtures/correct.svndump vendored Normal file
View File

@ -0,0 +1,103 @@
SVN-fs-dump-format-version: 2
UUID: 00000000-0000-0000-0000-000000000000
Revision-number: 0
Prop-content-length: 56
Content-length: 56
K 8
svn:date
V 27
2010-11-30T15:10:25.898546Z
PROPS-END
Revision-number: 1
Prop-content-length: 100
Content-length: 100
K 7
svn:log
V 0
K 10
svn:author
V 6
danchr
K 8
svn:date
V 27
2010-11-30T15:16:01.077550Z
PROPS-END
Node-path: empty-file
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 0
Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
Content-length: 10
PROPS-END
Node-path: executable-file
Node-kind: file
Node-action: add
Prop-content-length: 36
Text-content-length: 11
Text-content-md5: 01839ba8c81c3b2c7486607e0c683e62
Text-content-sha1: 5e70f8a25fe8ad4ad971bfd3388c258b019268d4
Content-length: 47
K 14
svn:executable
V 1
*
PROPS-END
Executable
Node-path: regular-file
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 10
Text-content-md5: 2e01b7f4ab0c18c05a3059eb2e2420d9
Text-content-sha1: 6e530e985be313a43dc9734251656be8f0c94ab8
Content-length: 20
PROPS-END
Contents.
Node-path: another-regular-file
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 10
Text-content-md5: 2e01b7f4ab0c18c05a3059eb2e2420d9
Text-content-sha1: 6e530e985be313a43dc9734251656be8f0c94ab8
Content-length: 20
PROPS-END
Contents.
Node-path: symlink
Node-kind: file
Node-action: add
Prop-content-length: 33
Text-content-length: 6
Text-content-md5: 654580f41818cd6f51408c7cbd313728
Text-content-sha1: 130b8faaf3e1acc1b95f77ac835e9c8b6eee5c96
Content-length: 39
K 11
svn:special
V 1
*
PROPS-END
link A

97
tests/fixtures/corrupt.svndump vendored Normal file
View File

@ -0,0 +1,97 @@
SVN-fs-dump-format-version: 2
UUID: 00000000-0000-0000-0000-000000000000
Revision-number: 0
Prop-content-length: 56
Content-length: 56
K 8
svn:date
V 27
2010-11-30T15:10:25.898546Z
PROPS-END
Revision-number: 1
Prop-content-length: 100
Content-length: 100
K 10
svn:author
V 6
danchr
K 8
svn:date
V 27
2010-11-30T15:16:01.077550Z
K 7
svn:log
V 0
PROPS-END
Node-path: another-regular-file
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 0
Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
Content-length: 10
PROPS-END
Node-path: executable-file
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 11
Text-content-md5: 01839ba8c81c3b2c7486607e0c683e62
Text-content-sha1: 5e70f8a25fe8ad4ad971bfd3388c258b019268d4
Content-length: 21
PROPS-END
Executable
Node-path: missing-file
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 0
Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
Content-length: 10
PROPS-END
Node-path: regular-file
Node-kind: file
Node-action: add
Prop-content-length: 33
Text-content-length: 18
Text-content-md5: adf66a0cec83e25644c63f3c3007ae7c
Text-content-sha1: 047e6e482d0c9cb812f89d18a9f07a43caab76bb
Content-length: 51
K 11
svn:special
V 1
*
PROPS-END
link Bad contents.
Node-path: symlink
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 1
Text-content-md5: 7fc56270e7a70fa81a5935b72eacbe29
Text-content-sha1: 6dcd4ce23d88e2ee9568ba546c007c63d9131c1b
Content-length: 11
PROPS-END
A

View File

@ -101,11 +101,16 @@ def buildmethod(case, name, stupid, single):
return m
skip = set([
'project_root_not_repo_root.svndump',
'corrupt.svndump',
])
attrs = {'_do_case': _do_case,
}
for case in [f for f in os.listdir(test_util.FIXTURES) if f.endswith('.svndump')]:
# this fixture results in an empty repository, don't use it
if case == 'project_root_not_repo_root.svndump':
if case in skip:
continue
bname = 'test_' + case[:-len('.svndump')]
attrs[bname] = buildmethod(case, bname, False, False)

View File

@ -260,13 +260,46 @@ class UtilityTests(test_util.TestBase):
output = re.sub(r'file://\S+', 'file://', output)
self.assertMultiLineEqual("""\
verifying d51f46a715a1 against file://
difference in file binary2
unexpected files:
binary1
missing files:
binary3
difference in: binary2
unexpected file: binary1
missing file: binary3
""", output)
def test_svnverify_corruption(self):
SUCCESS = 0
FAILURE = 1
repo, repo_path = self.load_and_fetch('correct.svndump', layout='single',
subdir='')
ui = self.ui()
self.assertEqual(SUCCESS, svncommands.verify(ui, self.repo, rev='tip'))
corrupt_source = test_util.fileurl(self.load_svndump('corrupt.svndump'))
repo.ui.setconfig('paths', 'default', corrupt_source)
ui.pushbuffer()
code = svncommands.verify(ui, repo, rev='tip')
actual = ui.popbuffer()
actual = actual.replace(corrupt_source, '$REPO')
actual = set(actual.splitlines())
expected = set([
'verifying 78e965230a13 against $REPO@1',
'missing file: missing-file',
'wrong flags for: executable-file',
'wrong flags for: symlink',
'wrong flags for: regular-file',
'difference in: another-regular-file',
'difference in: regular-file',
'unexpected file: empty-file',
])
self.assertEqual((FAILURE, expected), (code, actual))
def suite():
all_tests = [unittest.TestLoader().loadTestsFromTestCase(UtilityTests),
]