[Zope-Checkins] CVS: ZODB3/ZEO/tests - InvalidationTests.py:1.1.4.12

Tim Peters tim.one at comcast.net
Tue Aug 26 16:29:33 EDT 2003


Update of /cvs-repository/ZODB3/ZEO/tests
In directory cvs.zope.org:/tmp/cvs-serv30774/ZEO/tests

Modified Files:
      Tag: ZODB3-3_1-branch
	InvalidationTests.py 
Log Message:
Widespread:  The checkConcurrent.*Update tests used to run for 15
seconds, then fail if any thread didn't manage to commit a change in that
time.  But due to the vagaries of thread scheduling, it was too often
the case that a thread didn't manage to commit, and especially on Windows,
and especially on Win2K, and especially with Berkeley as the underlying
storage.

So, new strategy for all these tests:

1. Run for at least 10 seconds.

2. If some thread hasn't managed to commit, and 300 seconds haven't
   elapsed yet, sleep for a couple seconds and repeat this step.

3. Else all threads managed to commit, or 300 seconds have elapsed.
   Stop the test in either case.

The net result is that the tests should usually complete faster now,
but will sometimes take much longer (unpredictable from run to run,
and should fail much less often (especially on Windows, and etc --
but "thread so-and-so didn't add any keys" failures weren't rare on
Linux either).


=== ZODB3/ZEO/tests/InvalidationTests.py 1.1.4.11 => 1.1.4.12 ===
--- ZODB3/ZEO/tests/InvalidationTests.py:1.1.4.11	Mon Aug 25 18:42:53 2003
+++ ZODB3/ZEO/tests/InvalidationTests.py	Tue Aug 26 15:29:33 2003
@@ -45,8 +45,8 @@
     # to 'tree' until Event stop is set.  If sleep is given, sleep
     # that long after each append.  At the end, instance var .added_keys
     # is a list of the ints the thread believes it added successfully.
-    def __init__(self, testcase, db, stop, threadnum, startnum,
-                 step=2, sleep=None):
+    def __init__(self, testcase, db, stop, threadnum, commitdict,
+                 startnum, step=2, sleep=None):
         TestThread.__init__(self, testcase)
         self.db = db
         self.stop = stop
@@ -55,6 +55,7 @@
         self.step = step
         self.sleep = sleep
         self.added_keys = []
+        self.commitdict = commitdict
 
     def testrun(self):
         cn = self.db.open()
@@ -71,6 +72,7 @@
                 tree[key] = self.threadnum
                 get_transaction().note("add key %s" % key)
                 get_transaction().commit()
+                self.commitdict[self] = 1
                 if self.sleep:
                     time.sleep(self.sleep)
             except (ReadConflictError, ConflictError), msg:
@@ -91,7 +93,7 @@
     # more than 25 objects so that it can test code that runs vote
     # in a separate thread when it modifies more than 25 objects.
 
-    def __init__(self, testcase, db, stop, threadnum, startnum,
+    def __init__(self, testcase, db, stop, threadnum, commitdict, startnum,
                  step=2, sleep=None):
         TestThread.__init__(self, testcase)
         self.db = db
@@ -101,6 +103,7 @@
         self.step = step
         self.sleep = sleep
         self.added_keys = []
+        self.commitdict = commitdict
 
     def testrun(self):
         cn = self.db.open()
@@ -140,6 +143,7 @@
                 get_transaction().note("keys %s" % ", ".join(map(str, keys)))
                 try:
                     get_transaction().commit()
+                    self.commitdict[self] = 1
                     if self.sleep:
                         time.sleep(self.sleep)
                 except ConflictError, msg:
@@ -160,7 +164,7 @@
 
 class VersionStressThread(TestThread):
 
-    def __init__(self, testcase, db, stop, threadnum, startnum,
+    def __init__(self, testcase, db, stop, threadnum, commitdict, startnum,
                  step=2, sleep=None):
         TestThread.__init__(self, testcase)
         self.db = db
@@ -170,6 +174,7 @@
         self.step = step
         self.sleep = sleep
         self.added_keys = []
+        self.commitdict = commitdict
 
     def testrun(self):
         commit = 0
@@ -179,6 +184,7 @@
             commit = not commit
             if self.oneupdate(version, key, commit):
                 self.added_keys.append(key)
+                self.commitdict[self] = 1
             key += self.step
 
     def oneupdate(self, version, key, commit=1):
@@ -234,7 +240,17 @@
 class InvalidationTests:
 
     level = 2
-    DELAY = 15  # number of seconds the main thread lets the workers run
+
+    # Minimum # of seconds the main thread lets the workers run.  The
+    # test stops as soon as this much time has elapsed, and all threads
+    # have managed to commit a change.
+    MINTIME = 10
+
+    # Maximum # of seconds the main thread lets the workers run.  We
+    # stop after this long has elapsed regardless of whether all threads
+    # have mangaged to commit a change.
+    MAXTIME = 300
+
     StressThread = StressThread
 
     def _check_tree(self, cn, tree):
@@ -279,11 +295,18 @@
             display(tree)
             self.fail('\n'.join(errormsgs))
 
-    def go(self, stop, *threads):
+    def go(self, stop, commitdict, *threads):
         # Run the threads
         for t in threads:
             t.start()
-        time.sleep(self.DELAY)
+        delay = self.MINTIME
+        start = time.time()
+        while time.time() - start <= self.MAXTIME:
+            time.sleep(delay)
+            delay = 2.0
+            if len(commitdict) >= len(threads):
+                break
+            # Some thread still hasn't managed to commit anything.
         stop.set()
         for t in threads:
             t.cleanup()
@@ -300,9 +323,10 @@
         get_transaction().commit()
 
         # Run two threads that update the BTree
-        t1 = self.StressThread(self, db1, stop, 1, 1)
-        t2 = self.StressThread(self, db2, stop, 2, 2)
-        self.go(stop, t1, t2)
+        cd = {}
+        t1 = self.StressThread(self, db1, stop, 1, cd, 1)
+        t2 = self.StressThread(self, db2, stop, 2, cd, 2)
+        self.go(stop, cd, t1, t2)
 
         cn.sync()
         self._check_tree(cn, tree)
@@ -322,9 +346,10 @@
         get_transaction().commit()
 
         # Run two threads that update the BTree
-        t1 = self.StressThread(self, db1, stop, 1, 1, sleep=0.001)
-        t2 = self.StressThread(self, db1, stop, 2, 2, sleep=0.001)
-        self.go(stop, t1, t2)
+        cd = {}
+        t1 = self.StressThread(self, db1, stop, 1, cd, 1, sleep=0.001)
+        t2 = self.StressThread(self, db1, stop, 2, cd, 2, sleep=0.001)
+        self.go(stop, cd, t1, t2)
 
         cn.sync()
         self._check_tree(cn, tree)
@@ -348,10 +373,11 @@
         # is possible for both threads to read the same object
         # at the same time.
 
-        t1 = self.StressThread(self, db1, stop, 1, 1, 3)
-        t2 = self.StressThread(self, db2, stop, 2, 2, 3, 0.001)
-        t3 = self.StressThread(self, db2, stop, 3, 3, 3, 0.001)
-        self.go(stop, t1, t2, t3)
+        cd = {}
+        t1 = self.StressThread(self, db1, stop, 1, cd, 1, 3)
+        t2 = self.StressThread(self, db2, stop, 2, cd, 2, 3, 0.001)
+        t3 = self.StressThread(self, db2, stop, 3, cd, 3, 3, 0.001)
+        self.go(stop, cd, t1, t2, t3)
 
         cn.sync()
         self._check_tree(cn, tree)
@@ -376,10 +402,11 @@
         # is possible for both threads to read the same object
         # at the same time.
 
-        t1 = VersionStressThread(self, db1, stop, 1, 1, 3)
-        t2 = VersionStressThread(self, db2, stop, 2, 2, 3, 0.001)
-        t3 = VersionStressThread(self, db2, stop, 3, 3, 3, 0.001)
-        self.go(stop, t1, t2, t3)
+        cd = {}
+        t1 = VersionStressThread(self, db1, stop, 1, cd, 1, 3)
+        t2 = VersionStressThread(self, db2, stop, 2, cd, 2, 3, 0.001)
+        t3 = VersionStressThread(self, db2, stop, 3, cd, 3, 3, 0.001)
+        self.go(stop, cd, t1, t2, t3)
 
         cn.sync()
         self._check_tree(cn, tree)
@@ -407,10 +434,11 @@
         # is possible for both threads to read the same object
         # at the same time.
 
-        t1 = LargeUpdatesThread(self, db1, stop, 1, 1, 3, 0.001)
-        t2 = LargeUpdatesThread(self, db2, stop, 2, 2, 3, 0.001)
-        t3 = LargeUpdatesThread(self, db2, stop, 3, 3, 3, 0.001)
-        self.go(stop, t1, t2, t3)
+        cd = {}
+        t1 = LargeUpdatesThread(self, db1, stop, 1, cd, 1, 3, 0.001)
+        t2 = LargeUpdatesThread(self, db2, stop, 2, cd, 2, 3, 0.001)
+        t3 = LargeUpdatesThread(self, db2, stop, 3, cd, 3, 3, 0.001)
+        self.go(stop, cd, t1, t2, t3)
 
         cn.sync()
         self._check_tree(cn, tree)




More information about the Zope-Checkins mailing list