Commit 8e693703 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 552ebebf
......@@ -310,138 +310,6 @@ def test_zconn_at():
assert zconn_at(conn_at0) == at0
# verify that zconn_at is robust wrt races.
# see e.g.
# - https://github.com/zopefoundation/ZODB/issues/290
# - https://github.com/zopefoundation/ZODB/pull/307#discussion_r434145034
# - https://github.com/zopefoundation/ZEO/issues/155
# for what kind of data corruption issues might be there.
@xfail(zmajor < 4, reason="zconn_at is TODO for ZODB3")
@func
def test_zconn_at_vs_races():
# XXX doc
stor0 = testdb.getZODBStorage()
db0 = DB(stor0)
defer(db0.close)
def dbopen():
# in ZODB/py FileStorage does not support opening the database from several clients
if isinstance(stor0, FileStorage):
return db0
stor = testdb.getZODBStorage()
db = DB(stor)
return db
def dbclose(db):
# see ^^^ about FileStorage
if db is db0:
return
db.close()
# init the database with two integer objects - obj1/obj2 that are set to 0.
@func
def _():
db = dbopen()
defer(lambda: dbclose(db))
transaction.begin()
conn = db.open()
root = conn.root()
root['obj1'] = XInt(0)
root['obj2'] = XInt(0)
transaction.commit()
conn.close()
_()
# T is a worker that accesses obj1/obj2 in a loop and verifies
# `obj1.i == obj2.i` invariant.
#
# access to obj1 is organized to go through zconn.
# access to obj2 goes through zconn2 that is opened with at=zconn_at(zconn).
#
# this verifies that at=zconn_at(zconn) is consistent with database state observed by zconn.
#
# Once in a while T tries to modify obj{1,2}.i maintaining the invariant as
# test source of changes for other workers.
@func
def T(ctx, name, N):
db = dbopen()
defer(lambda: dbclose(db))
@func
def t1():
transaction.begin()
zconn = db.open()
defer(zconn.close)
tm2 = TransactionManager()
at = zconn_at(zconn)
zconn2 = db.open(at=at, transaction_manager=tm2)
defer(zconn2.close)
defer(tm2.abort)
root = zconn.root()
obj1 = root['obj1']
root2 = zconn2.root()
obj2_ = root['obj2']
#obj2_._p_invalidate()
# both objects must have the same values (zconn vs zconn2)
i1 = obj1.i
i2_ = obj2_.i
if i1 != i2_:
raise AssertionError("T%s: obj1.i (%d) != obj2_.i (%d)" % (name, i1, i2_))
# ----//---- (zconn vs zconn)
obj2 = root['obj2']
i2 = obj2.i
if i1 != i2:
raise AssertionError("T%s: obj1.i (%d) != obj2.i (%d)" % (name, i1, i2))
# change objects once in a while
if randint(0,4) == 0:
#print("T%s: modify" % name)
obj1.i += 1
obj2.i += 1
# verify that zconn_at result stays the same during lifetime of one transaction
at_ = zconn_at(zconn)
if at_ != at:
raise AssertionError("T%s: at_ (%r) != at (%r)" % (name, at_, at))
assert at_ == at
try:
transaction.commit()
except POSException.ConflictError:
#print('conflict -> ignore')
transaction.abort()
for i in range(N):
e = ctx.err()
if e is not None:
raise e
#print('T%s.%d' % (name, i))
t1()
# run 8 T workers concurrently. As of 20200123, likely due to race conditions XXX
# in ZEO, it triggers the bug where T sees stale obj2 with obj1.i != obj2.i
N = 1000
wg = sync.WorkGroup(context.background())
for x in range(8):
wg.go(T, x, N)
wg.wait()
print('OK')
# verify that ZODB.Connection.onResyncCallback works
@xfail(zmajor < 4, reason="ZODB.Connection.onResyncCallback is TODO for ZODB3")
@func
......
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