Commit 43007a55 authored by Jeremy Hylton's avatar Jeremy Hylton

Add a test specifically for damaged transaction headers.

We're still missing tests that cover important cases.  Unexecuted code
below:

>>>>>>             if l > len(data) - 8:
>>>>>>                 pos += l
>>>>>>                 break
>>>>>>             s = l + 1
>>>>>>             tl = u64(data[s:s+8])
>>>>>>             if tl < pos:
>>>>>>                 return pos + s + 8

>>>>>>         except:
>>>>>>             if partial and nrec:
>>>>>>                 ofs._status = 'p'
>>>>>>                 ofs.tpc_vote(transaction)
>>>>>>                 ofs.tpc_finish(transaction)
>>>>>>                 if verbose:
>>>>>>                     print 'partial'
                   else:
>>>>>>                 ofs.tpc_abort(transaction)
>>>>>>             print "\n%s: %s\n" % sys.exc_info()[:2]
>>>>>>             if not verbose:
>>>>>>                 progress(prog1)
>>>>>>             pos = scan(file, pos)
parent f1066d35
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
############################################################################## ##############################################################################
"""Tests of the file storage recovery script.""" """Tests of the file storage recovery script."""
import base64
import os import os
import random import random
import sys import sys
...@@ -38,11 +39,11 @@ class RecoverTest(unittest.TestCase): ...@@ -38,11 +39,11 @@ class RecoverTest(unittest.TestCase):
self.path = tempfile.mktemp(suffix=".fs") self.path = tempfile.mktemp(suffix=".fs")
self.storage = FileStorage(self.path) self.storage = FileStorage(self.path)
self.populate() self.populate()
self.storage.close()
self.dest = tempfile.mktemp(suffix=".fs") self.dest = tempfile.mktemp(suffix=".fs")
self.recovered = None self.recovered = None
def tearDown(self): def tearDown(self):
self.storage.close()
if self.recovered is not None: if self.recovered is not None:
self.recovered.close() self.recovered.close()
removefs(self.path) removefs(self.path)
...@@ -55,14 +56,15 @@ class RecoverTest(unittest.TestCase): ...@@ -55,14 +56,15 @@ class RecoverTest(unittest.TestCase):
# create a whole bunch of objects, # create a whole bunch of objects,
# looks like a Data.fs > 1MB # looks like a Data.fs > 1MB
for i in range(100): for i in range(50):
d = rt[i] = PersistentMapping() d = rt[i] = PersistentMapping()
get_transaction().commit() get_transaction().commit()
for j in range(100): for j in range(50):
d[j] = "a" * j d[j] = "a" * j
get_transaction().commit() get_transaction().commit()
def damage(self, num, size): def damage(self, num, size):
self.storage.close()
# Drop size null bytes into num random spots. # Drop size null bytes into num random spots.
for i in range(num): for i in range(num):
offset = random.randint(0, self.storage._pos - size) offset = random.randint(0, self.storage._pos - size)
...@@ -71,7 +73,7 @@ class RecoverTest(unittest.TestCase): ...@@ -71,7 +73,7 @@ class RecoverTest(unittest.TestCase):
f.write("\0" * size) f.write("\0" * size)
f.close() f.close()
ITERATIONS = 10 ITERATIONS = 5
def recover(self, source, dest): def recover(self, source, dest):
orig = sys.stdout orig = sys.stdout
...@@ -112,6 +114,41 @@ class RecoverTest(unittest.TestCase): ...@@ -112,6 +114,41 @@ class RecoverTest(unittest.TestCase):
os.remove(self.path) os.remove(self.path)
os.rename(self.dest, self.path) os.rename(self.dest, self.path)
def testBadTransaction(self):
# Find transaction headers and blast them.
L = self.storage.undoLog()
r = L[3]
tid = base64.decodestring(r["id"] + "\n")
pos1 = self.storage._txn_find(tid, False)
r = L[8]
tid = base64.decodestring(r["id"] + "\n")
pos2 = self.storage._txn_find(tid, False)
self.storage.close()
# Overwrite the entire header.
f = open(self.path, "a+b")
f.seek(pos1 - 50)
f.write("\0" * 100)
f.close()
self.recover(self.path, self.dest)
self.recovered = FileStorage(self.dest)
self.recovered.close()
os.remove(self.path)
os.rename(self.dest, self.path)
# Overwrite part of the header.
f = open(self.path, "a+b")
f.seek(pos2 + 10)
f.write("\0" * 100)
f.close()
self.recover(self.path, self.dest)
self.recovered = FileStorage(self.dest)
self.recovered.close()
def test_suite(): def test_suite():
return unittest.makeSuite(RecoverTest) return unittest.makeSuite(RecoverTest)
......
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