[Zodb-checkins] SVN: ZODB/trunk/src/ Fixed analyze.py and added test.

Laurence Rowe l at lrowe.co.uk
Tue May 26 12:10:58 EDT 2009


Log message for revision 100422:
  Fixed analyze.py and added test.

Changed:
  U   ZODB/trunk/src/CHANGES.txt
  U   ZODB/trunk/src/ZODB/scripts/analyze.py
  U   ZODB/trunk/src/ZODB/tests/testFileStorage.py

-=-
Modified: ZODB/trunk/src/CHANGES.txt
===================================================================
--- ZODB/trunk/src/CHANGES.txt	2009-05-26 16:02:30 UTC (rev 100421)
+++ ZODB/trunk/src/CHANGES.txt	2009-05-26 16:10:57 UTC (rev 100422)
@@ -12,6 +12,8 @@
 
 - Fixed intermittent failures in the MVCCMappingStorage tests.
 
+- Fixed analyze.py and added test.
+
 3.9.0b1 (2009-05-04)
 ====================
 

Modified: ZODB/trunk/src/ZODB/scripts/analyze.py
===================================================================
--- ZODB/trunk/src/ZODB/scripts/analyze.py	2009-05-26 16:02:30 UTC (rev 100421)
+++ ZODB/trunk/src/ZODB/scripts/analyze.py	2009-05-26 16:10:57 UTC (rev 100422)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.3
+#!/usr/bin/env python2.4
 
 # Based on a transaction analyzer by Matt Kromer.
 
@@ -7,7 +7,18 @@
 import sys
 import types
 from ZODB.FileStorage import FileStorage
+from cStringIO import StringIO
 
+class FakeError(Exception):
+    def __init__(self, module, name):
+        Exception.__init__(self)
+        self.module = module
+        self.name = name
+
+class FakeUnpickler(pickle.Unpickler):
+    def find_class(self, module, name):
+        raise FakeError(module, name)
+
 class Report:
     def __init__(self):
         self.OIDMAP = {}
@@ -87,15 +98,12 @@
 
 def get_type(record):
     try:
-        classinfo = pickle.loads(record.data)[0]
-    except SystemError, err:
-        s = str(err)
-        mo = re.match('Failed to import class (\S+) from module (\S+)', s)
-        if mo is None:
-            raise
-        else:
-            klass, mod = mo.group(1, 2)
-            return "%s.%s" % (mod, klass)
+        unpickled = FakeUnpickler(StringIO(record.data)).load()
+    except FakeError, err:
+        return "%s.%s" % (err.module, err.name)
+    except:
+        raise
+    classinfo = unpickled[0]
     if isinstance(classinfo, types.TupleType):
         mod, klass = classinfo
         return "%s.%s" % (mod, klass)
@@ -130,9 +138,6 @@
     except Exception, err:
         print err
 
-def main():
+if __name__ == "__main__":
     path = sys.argv[1]
     report(analyze(path))
-
-if __name__ == "__main__":
-    main()

Modified: ZODB/trunk/src/ZODB/tests/testFileStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/testFileStorage.py	2009-05-26 16:02:30 UTC (rev 100421)
+++ ZODB/trunk/src/ZODB/tests/testFileStorage.py	2009-05-26 16:10:57 UTC (rev 100422)
@@ -336,6 +336,72 @@
         pass
 
 
+class AnalyzeDotPyTest(StorageTestBase.StorageTestBase):
+
+    def setUp(self):
+        StorageTestBase.StorageTestBase.setUp(self)
+        self._storage = ZODB.FileStorage.FileStorage("Source.fs", create=True)
+
+    def checkanalyze(self):
+        import new, sys, pickle
+        from BTrees.OOBTree import OOBTree
+        from ZODB.scripts import analyze
+        
+        # Set up a module to act as a broken import
+        module_name = 'brokenmodule'
+        module = new.module(module_name)
+        sys.modules[module_name] = module
+        
+        class Broken(MinPO):
+            __module__ = module_name
+        module.Broken = Broken
+        
+        oids = [[self._storage.new_oid(), None] for i in range(3)]
+        for i in range(2):
+            t = transaction.Transaction()
+            self._storage.tpc_begin(t)
+            
+            # sometimes data is in this format
+            j = 0
+            oid, revid = oids[j]
+            serial = self._storage.store(oid, revid, pickle.dumps(OOBTree, 1), "", t) 
+            oids[j][1] = serial
+            
+            # and it could be from a broken module
+            j = 1
+            oid, revid = oids[j]
+            serial = self._storage.store(oid, revid, pickle.dumps(Broken, 1), "", t) 
+            oids[j][1] = serial
+            
+            # but mostly it looks like this
+            j = 2
+            o = MinPO(j)
+            oid, revid = oids[j]
+            serial = self._storage.store(oid, revid, zodb_pickle(o), "", t)
+            oids[j][1] = serial
+
+            self._storage.tpc_vote(t)
+            self._storage.tpc_finish(t)
+            
+        # now break the import of the Broken class
+        del sys.modules[module_name]
+        
+        # from ZODB.scripts.analyze.analyze
+        fsi = self._storage.iterator()
+        rep = analyze.Report()
+        for txn in fsi:
+            analyze.analyze_trans(rep, txn)
+        
+        # from ZODB.scripts.analyze.report
+        typemap = rep.TYPEMAP.keys()
+        typemap.sort()
+        cumpct = 0.0
+        for t in typemap:
+            pct = rep.TYPESIZE[t] * 100.0 / rep.DBYTES
+            cumpct += pct
+       
+        self.assertAlmostEqual(cumpct, 100.0, 0, "Failed to analyze some records")
+
 # Raise an exception if the tids in FileStorage fs aren't
 # strictly increasing.
 def checkIncreasingTids(fs):
@@ -573,7 +639,7 @@
     suite = unittest.TestSuite()
     for klass in [FileStorageTests, Corruption.FileStorageCorruptTests,
                   FileStorageRecoveryTest, FileStorageNoRestoreRecoveryTest,
-                  FileStorageTestsWithBlobsEnabled,
+                  FileStorageTestsWithBlobsEnabled, AnalyzeDotPyTest,
                   ]:
         suite.addTest(unittest.makeSuite(klass, "check"))
     suite.addTest(doctest.DocTestSuite(



More information about the Zodb-checkins mailing list