Back to index

plone3  3.1.7
test_athistoryaware.py
Go to the documentation of this file.
00001 import os
00002 import shutil
00003 import tempfile
00004 import unittest
00005 
00006 import Acquisition
00007 import BTrees
00008 import transaction
00009 import OFS
00010 import persistent
00011 import ZODB
00012 from ZODB.FileStorage import FileStorage
00013 
00014 from Products.Archetypes.annotations import AT_ANN_STORAGE
00015 from Products.Archetypes.athistoryaware import ATHistoryAwareMixin
00016 
00017 KEY1 = AT_ANN_STORAGE + '-monty'
00018 KEY2 = AT_ANN_STORAGE + '-python'
00019 KEY3 = AT_ANN_STORAGE + '-lumberjack'
00020 
00021 class DummyAnnotation(persistent.Persistent):
00022     spam = 'eggs'
00023 
00024 class DummyObject(Acquisition.Implicit, persistent.Persistent,
00025                   ATHistoryAwareMixin):
00026     foo = 'bar'
00027     
00028     def __init__(self):
00029         annotations = BTrees.OOBTree.OOBTree()
00030         annotations[KEY1] = DummyAnnotation()
00031         annotations[KEY2] = DummyAnnotation()
00032         setattr(self, '__annotations__', annotations)
00033 
00034 class ATHistoryAwareTests(unittest.TestCase):
00035     def setUp(self):
00036         # Set up a ZODB and Application object. We can't use DemoStorage 
00037         # as it doesn't support the history() API.
00038         self._dir = tempfile.mkdtemp()
00039         self._storage = FileStorage(
00040             os.path.join(self._dir,'test_athistoryaware.fs'),
00041             create=True)
00042         self._connection = ZODB.DB(self._storage).open()
00043         root = self._connection.root()
00044         root['Application'] = OFS.Application.Application()
00045         self.app = root['Application']
00046         
00047         # Our basic testing object
00048         self.app.object = DummyObject()
00049         self.object = self.app.object
00050         t = transaction.get()
00051         t.description = None # clear initial transaction note
00052         t.note('Transaction 1')
00053         t.setUser('User 1')
00054         t.commit()
00055         
00056         # Alter object and annotations over several transactions
00057         annotations = self.object.__annotations__
00058         self.object.foo = 'baz'
00059         annotations[KEY1].spam = 'python'
00060         t = transaction.get()
00061         t.note('Transaction 2')
00062         t.setUser('User 2')
00063         t.commit()
00064         
00065         annotations[KEY3] = DummyAnnotation()
00066         t = transaction.get()
00067         t.note('Transaction 3')
00068         t.setUser('User 3')
00069         t.commit()
00070         
00071         del annotations[KEY3]
00072         annotations[KEY2].spam = 'lumberjack'
00073         t = transaction.get()
00074         t.note('Transaction 4')
00075         t.setUser('User 4')
00076         t.commit()
00077         
00078         self.object.foo = 'mit'
00079         annotations[KEY1].spam = 'trout'
00080         t = transaction.get()
00081         t.note('Transaction 5')
00082         t.setUser('User 5')
00083         t.commit()
00084         
00085     def tearDown(self):
00086         transaction.abort()
00087         del self.app
00088         self._connection.close()
00089         del self._connection
00090         self._storage.close()
00091         del self._storage
00092         shutil.rmtree(self._dir)
00093         
00094     def test_historyMetadata(self):
00095         """Each revision entry has unique metadata"""
00096         for i, entry in enumerate(self.object.getHistories()):
00097             # History is returned in reverse order, so Transaction 5 is first
00098             self.assertEqual(entry[2], 'Transaction %d' % (5 - i))
00099             self.assertEqual(entry[3], '/ User %d' % (5 - i))
00100             
00101     def test_objectContext(self):
00102         """Objects are returned with an acquisition context"""
00103         for entry in self.object.getHistories():
00104             self.assertEqual(entry[0].aq_parent, self.app)
00105         
00106     def test_simpleAttributes(self):
00107         """Simple, non-persistent attributes are tracked"""
00108         foo_history = (e[0].foo for e in self.object.getHistories())
00109         expected = ('mit', 'baz', 'baz', 'baz', 'bar')
00110         self.assertEqual(tuple(foo_history), expected)
00111         
00112     def test_annotation(self):
00113         """Persistent subkeys of the __annotations__ object"""
00114         key1_history = (e[0].__annotations__[KEY1].spam
00115                         for e in self.object.getHistories())
00116         expected = ('trout', 'python', 'python', 'python', 'eggs')
00117         self.assertEqual(tuple(key1_history), expected)
00118         
00119         key2_history = (e[0].__annotations__[KEY2].spam
00120                         for e in self.object.getHistories())
00121         expected = ('lumberjack', 'lumberjack', 'eggs', 'eggs', 'eggs')
00122         self.assertEqual(tuple(key2_history), expected)
00123         
00124     def test_annotationlifetime(self):
00125         """Addition and deletion of subkeys is tracked"""
00126         key3_history = (bool(e[0].__annotations__.has_key(KEY3))
00127                         for e in self.object.getHistories())
00128         expected = (False, False, True, False, False)
00129         self.assertEqual(tuple(key3_history), expected)
00130         
00131     def test_maxReturned(self):
00132         history = list(self.object.getHistories(max=2))
00133         self.assertEqual(len(history), 2)
00134         
00135 def test_suite():
00136     suite = unittest.TestSuite()
00137     suite.addTests((
00138         unittest.makeSuite(ATHistoryAwareTests),
00139     ))
00140     return suite
00141 
00142 if __name__ == '__main__':
00143     unittest.main()