[Zodb-checkins]
SVN: ZODB/branches/ctheune-blobsupport/src/ZODB/Blobs/tests/transaction.txt
Add more tests.
Chris McDonough
chrism at plope.com
Fri Mar 25 09:12:26 EST 2005
Log message for revision 29681:
Add more tests.
Changed:
U ZODB/branches/ctheune-blobsupport/src/ZODB/Blobs/tests/transaction.txt
-=-
Modified: ZODB/branches/ctheune-blobsupport/src/ZODB/Blobs/tests/transaction.txt
===================================================================
--- ZODB/branches/ctheune-blobsupport/src/ZODB/Blobs/tests/transaction.txt 2005-03-25 13:27:29 UTC (rev 29680)
+++ ZODB/branches/ctheune-blobsupport/src/ZODB/Blobs/tests/transaction.txt 2005-03-25 14:12:26 UTC (rev 29681)
@@ -20,6 +20,7 @@
>>> from ZODB.MappingStorage import MappingStorage
>>> from ZODB.Blobs.BlobStorage import BlobStorage
>>> from ZODB.DB import DB
+ >>> import transaction
>>> from tempfile import mkdtemp
>>> base_storage = MappingStorage("test")
>>> blob_dir = mkdtemp()
@@ -28,72 +29,119 @@
Putting a Blob into a Connection works like any other Persistent object:
- >>> connection = database.open()
- >>> root = connection.root()
+ >>> connection1 = database.open()
+ >>> root1 = connection1.root()
>>> from ZODB.Blobs.Blob import Blob
- >>> blob = Blob()
- >>> blob.open('w').write('abc')
- >>> root['myblob'] = blob
- >>> import transaction
+ >>> blob1 = Blob()
+ >>> blob1.open('w').write('this is blob 1')
+ >>> root1['blob1'] = blob1
>>> transaction.commit()
Opening a blob gives us a filehandle. Getting data out of the
resulting filehandle is accomplished via the filehandle's read method:
>>> connection2 = database.open()
- >>> root = connection2.root()
- >>> blob2 = root['myblob']
- >>> blob2._p_blob_refcounts()
+ >>> root2 = connection2.root()
+ >>> blob1a = root2['blob1']
+ >>> blob1a._p_blob_refcounts()
(0, 0)
>>>
- >>> b1 = blob2.open("r")
- >>> b1.read()
- 'abc'
- >>> # we reach into the implementation here, dont try this at home
- >>> b1.blob._p_blob_refcounts()[0]
- 1
+ >>> blob1afh1 = blob1a.open("r")
+ >>> blob1afh1.read()
+ 'this is blob 1'
+ >>> # The filehandle keeps a reference to its blob object
+ >>> blob1afh1.blob._p_blob_refcounts()
+ (1, 0)
-Let's make another filehandle for read only to blob2, this should bump
+Let's make another filehandle for read only to blob1a, this should bump
up its refcount by one, and each file handle has a reference to the
(same) underlying blob:
- >>> b2 = blob2.open("r")
- >>> b2.blob._p_blob_refcounts()
+ >>> blob1afh2 = blob1a.open("r")
+ >>> blob1afh2.blob._p_blob_refcounts()
(2, 0)
- >>> b1.blob._p_blob_refcounts()
+ >>> blob1afh1.blob._p_blob_refcounts()
(2, 0)
+ >>> blob1afh2.blob is blob1afh1.blob
+ True
Let's close the first filehandle we got from the blob, this should decrease
its refcount by one:
- >>> b1.close()
- >>> b1.blob._p_blob_refcounts()
+ >>> blob1afh1.close()
+ >>> blob1a._p_blob_refcounts()
(1, 0)
- >>> b1.blob._p_blob_refcounts()
- (1, 0)
Let's abort this transaction, and ensure that the filehandles that we
opened are now closed and that the filehandle refcounts on the blob
object are cleared.
>>> transaction.abort()
- >>> b1.blob._p_blob_refcounts()
+ >>> blob1afh1.blob._p_blob_refcounts()
(0, 0)
- >>> b2.blob._p_blob_refcounts()
+ >>> blob1afh2.blob._p_blob_refcounts()
(0, 0)
- >>> b2.read()
+ >>> blob1a._p_blob_refcounts()
+ (0, 0)
+ >>> blob1afh2.read()
Traceback (most recent call last):
...
ValueError: I/O operation on closed file
-If we open a blob for writing, its write refcount should be nonzero:
+If we open a blob for append, its write refcount should be nonzero.
+Additionally, writing any number of bytes to the blobfile should
+result in the blob being marked "dirty" in the connection (we just
+aborted above, so the object should be "clean" when we start):
+ >>> bool(blob1a._p_changed)
+ False
+ >>> blob1afh3 = blob1a.open('a')
+ >>> blob1afh3.write('woot!')
+ >>> blob1a._p_blob_refcounts()
+ (0, 1)
+ >>> bool(blob1a._p_changed)
+ True
+
+We can open more than one blob object during the course of a single
+transaction:
+
+ >>> blob2 = Blob()
+ >>> blob2.open('w').write('this is blob 3')
+ >>> root2['blob2'] = blob2
+ >>> transaction.commit()
>>> blob2._p_blob_refcounts()
(0, 0)
- >>> b2 = blob2.open('a')
- >>> blob2._p_blob_refcounts()
- (0, 1)
+Since we committed the current transaction above, the aggregate
+changes we've made to blob, blob1a (these refer to the same object) and
+blob2 (a different object) should be evident:
+
+ >>> blob1.open('r').read()
+ 'this is blob 1woot!'
+ >>> blob1a.open('r').read()
+ 'this is blob 1woot!'
+ >>> blob2.open('r').read()
+ 'this is blob 3'
+
+Attempting to change a blob simultaneously from two different
+connections should result in a write conflict error (this test is
+broken currently because I need to figure out how to commit the
+changes made in each connection independently):
+
+ >>> transaction.abort()
+ >>> blob1c1 = root1['blob1']
+ >>> blob1c2 = root2['blob1']
+ >>> blob1c1fh1 = blob1c1.open('a')
+ >>> blob1c2fh1 = blob1c2.open('a')
+ >>> blob1c1fh1.write('this is from connection 1')
+ >>> blob1c2fh1.write('this is from connection 2')
+ >>> transaction.commit()
+ Traceback (most recent call last):
+ ...
+ ConflictError
+
+If we modify the same blob in two different connections
+
While we are testing this, we don't need the storage directory and databases
anymore:
More information about the Zodb-checkins
mailing list