Commit 7bb97358 authored by Tim Peters's avatar Tim Peters

Collector #1307: fsrecover.py broken on HEAD.

fsrecover.py:  the call to restore() was still using .serial, which no
longer exists.  Changed to use .tid.

testRecover.py:  the tests here passed despite that fsrecover wasn't
working at all.  Changed RecoverTest.recover() to eliminate its unused
arguments, and to return all the output fsrecover.recover() produces (the
output was being thrown away, unlooked at).  Added new testNoDamage(),
which feeds recovery a healthy .fs, and then looks at the output of
recovery, to verify that no errors were reported and no bytes were
removed by recovery.  Changed all the other tests to stop passing unused
arguments to RecoverTest.recover(), and to verify that error output was
produced by recovery.

XXX I'm not sure that every call to RecoverTest.recover() will actually
XXX produce an error in fsrecover.recover(), so we may get some spurious
XXX test failures here.  I'll keep my open for those.  (The kinds of
XXX damage tested are randomized, so one run doesn't prove anything.)
parent 4d7128e5
...@@ -335,7 +335,7 @@ def recover(inp, outp, verbose=0, partial=False, force=False, pack=None): ...@@ -335,7 +335,7 @@ def recover(inp, outp, verbose=0, partial=False, force=False, pack=None):
l = len(r.data) l = len(r.data)
print "%7d %s %s" % (u64(r.oid), l, r.version) print "%7d %s %s" % (u64(r.oid), l, r.version)
ofs.restore(r.oid, r.serial, r.data, r.version, r.data_txn, ofs.restore(r.oid, r.tid, r.data, r.version, r.data_txn,
txn) txn)
nrec += 1 nrec += 1
except (KeyboardInterrupt, SystemExit): except (KeyboardInterrupt, SystemExit):
......
...@@ -76,22 +76,38 @@ class RecoverTest(unittest.TestCase): ...@@ -76,22 +76,38 @@ class RecoverTest(unittest.TestCase):
ITERATIONS = 5 ITERATIONS = 5
def recover(self, source, dest): # Run recovery, from self.path to self.dest. Return whatever
orig = sys.stdout # recovery printed to stdout, as a string.
def recover(self):
orig_stdout = sys.stdout
faux_stdout = StringIO.StringIO()
try: try:
sys.stdout = StringIO.StringIO() sys.stdout = faux_stdout
try: try:
recover(self.path, self.dest, recover(self.path, self.dest,
verbose=0, partial=1, force=0, pack=1) verbose=0, partial=1, force=0, pack=1)
except SystemExit: except SystemExit:
raise RuntimeError, "recover tried to exit" raise RuntimeError, "recover tried to exit"
finally: finally:
sys.stdout = orig sys.stdout = orig_stdout
return faux_stdout.getvalue()
# Caution: because recovery is robust against many kinds of damage,
# it's almost impossible for a call to self.recover() to raise an
# exception. As a result, these tests may pass even if fsrecover.py
# is broken badly. testNoDamage() tries to ensure that at least
# recovery doesn't produce any error msgs if the input .fs is in
# fact not damaged.
def testNoDamage(self):
output = self.recover()
self.assert_('error' not in output, output)
self.assert_('0 bytes removed during recovery' in output, output)
def testOneBlock(self): def testOneBlock(self):
for i in range(self.ITERATIONS): for i in range(self.ITERATIONS):
self.damage(1, 1024) self.damage(1, 1024)
self.recover(self.path, self.dest) output = self.recover()
self.assert_('error' in output)
self.recovered = FileStorage(self.dest) self.recovered = FileStorage(self.dest)
self.recovered.close() self.recovered.close()
os.remove(self.path) os.remove(self.path)
...@@ -100,7 +116,8 @@ class RecoverTest(unittest.TestCase): ...@@ -100,7 +116,8 @@ class RecoverTest(unittest.TestCase):
def testFourBlocks(self): def testFourBlocks(self):
for i in range(self.ITERATIONS): for i in range(self.ITERATIONS):
self.damage(4, 512) self.damage(4, 512)
self.recover(self.path, self.dest) output = self.recover()
self.assert_('error' in output)
self.recovered = FileStorage(self.dest) self.recovered = FileStorage(self.dest)
self.recovered.close() self.recovered.close()
os.remove(self.path) os.remove(self.path)
...@@ -109,7 +126,8 @@ class RecoverTest(unittest.TestCase): ...@@ -109,7 +126,8 @@ class RecoverTest(unittest.TestCase):
def testBigBlock(self): def testBigBlock(self):
for i in range(self.ITERATIONS): for i in range(self.ITERATIONS):
self.damage(1, 32 * 1024) self.damage(1, 32 * 1024)
self.recover(self.path, self.dest) output = self.recover()
self.assert_('error' in output)
self.recovered = FileStorage(self.dest) self.recovered = FileStorage(self.dest)
self.recovered.close() self.recovered.close()
os.remove(self.path) os.remove(self.path)
...@@ -134,7 +152,8 @@ class RecoverTest(unittest.TestCase): ...@@ -134,7 +152,8 @@ class RecoverTest(unittest.TestCase):
f.seek(pos1 - 50) f.seek(pos1 - 50)
f.write("\0" * 100) f.write("\0" * 100)
f.close() f.close()
self.recover(self.path, self.dest) output = self.recover()
self.assert_('error' in output)
self.recovered = FileStorage(self.dest) self.recovered = FileStorage(self.dest)
self.recovered.close() self.recovered.close()
os.remove(self.path) os.remove(self.path)
...@@ -145,7 +164,8 @@ class RecoverTest(unittest.TestCase): ...@@ -145,7 +164,8 @@ class RecoverTest(unittest.TestCase):
f.seek(pos2 + 10) f.seek(pos2 + 10)
f.write("\0" * 100) f.write("\0" * 100)
f.close() f.close()
self.recover(self.path, self.dest) output = self.recover()
self.assert_('error' in output)
self.recovered = FileStorage(self.dest) self.recovered = FileStorage(self.dest)
self.recovered.close() self.recovered.close()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment