[Neo-report] r2687 jm - in /trunk/neo: lib/ tests/ tests/functional/
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed Mar 23 11:45:09 CET 2011
Author: jm
Date: Wed Mar 23 11:45:09 2011
New Revision: 2687
Log:
tests: make (i)pdb multiprocess-safe
- do not kill processes being debugged
- pause timeout while debugging
Modified:
trunk/neo/lib/debug.py
trunk/neo/tests/__init__.py
trunk/neo/tests/functional/__init__.py
Modified: trunk/neo/lib/debug.py
==============================================================================
--- trunk/neo/lib/debug.py [iso-8859-1] (original)
+++ trunk/neo/lib/debug.py [iso-8859-1] Wed Mar 23 11:45:09 2011
@@ -62,6 +62,15 @@ def debugHandler(sig, frame):
neo.__path__)
imp.load_module('neo.debug', file, filename, (suffix, mode, type))
+def getPdb():
+ try: # try ipython if available
+ import IPython
+ IPython.Shell.IPShell(argv=[])
+ return IPython.Debugger.Tracer().debugger
+ except ImportError:
+ import pdb
+ return pdb.Pdb()
+
_debugger = None
@decorate
@@ -71,13 +80,7 @@ def pdbHandler(sig, frame):
except ImportError:
global _debugger
if _debugger is None:
- try: # try ipython if available
- import IPython
- IPython.Shell.IPShell(argv=[])
- _debugger = IPython.Debugger.Tracer().debugger
- except ImportError:
- import pdb
- _debugger = pdb.Pdb()
+ _debugger = getPdb()
return debugger.set_trace(frame)
# WKRD: rpdb2 take an integer (depth) instead of a frame as parameter,
# so we must hardcode the value, taking the decorator into account
Modified: trunk/neo/tests/__init__.py
==============================================================================
--- trunk/neo/tests/__init__.py [iso-8859-1] (original)
+++ trunk/neo/tests/__init__.py [iso-8859-1] Wed Mar 23 11:45:09 2011
@@ -15,6 +15,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+import __builtin__
import errno
import os
import random
@@ -31,6 +32,7 @@ from neo.lib.protocol import Packets
from neo.lib.util import getAddressType
from time import time, gmtime, sleep
from struct import pack, unpack
+from functools import wraps
DB_PREFIX = os.getenv('NEO_DB_PREFIX', 'test_neo_')
DB_ADMIN = os.getenv('NEO_DB_ADMIN', 'root')
@@ -518,3 +520,51 @@ class SocketLock(object):
s = self._socket
del self._socket
s.close()
+
+
+class ClusterPdb(object):
+ # TODO: monkey-patch normal code not to timeout
+ # if another node is being debugged
+
+ def __init__(self):
+ self._r, self._w = os.pipe()
+ self.release(0)
+
+ def __getattr__(self, attr):
+ try:
+ debugger = self.__dict__['_debugger']
+ except KeyError:
+ self._debugger = debugger = debug.getPdb()
+ def hook(name):
+ hook = getattr(self, name)
+ hooked = getattr(debugger, name)
+ def wrapper(*args, **kw):
+ return hook(hooked, *args, **kw)
+ setattr(debugger, name, wraps(hooked)(wrapper))
+ hook('interaction')
+ return getattr(debugger, attr)
+
+ def acquire(self):
+ return unpack('d', os.read(self._r, 8))[0]
+
+ def release(self, delay):
+ os.write(self._w, pack('d', delay))
+
+ def interaction(self, hooked, *args, **kw):
+ delay = self.acquire() - time()
+ try:
+ return hooked(*args, **kw)
+ finally:
+ self.release(delay + time())
+
+ def wait(self, test, timeout, period):
+ end_time = time() + timeout
+ while not test():
+ delay = self.acquire()
+ self.release(delay)
+ if time() > end_time + delay:
+ return False
+ sleep(period)
+ return True
+
+__builtin__.pdb = ClusterPdb()
Modified: trunk/neo/tests/functional/__init__.py
==============================================================================
--- trunk/neo/tests/functional/__init__.py [iso-8859-1] (original)
+++ trunk/neo/tests/functional/__init__.py [iso-8859-1] Wed Mar 23 11:45:09 2011
@@ -153,10 +153,14 @@ class NEOProcess(object):
def kill(self, sig=signal.SIGTERM):
if self.pid:
+ delay = pdb.acquire()
try:
- os.kill(self.pid, sig)
- except OSError:
- traceback.print_last()
+ try:
+ os.kill(self.pid, sig)
+ except OSError:
+ traceback.print_last()
+ finally:
+ pdb.release(delay)
else:
raise AlreadyStopped
@@ -340,16 +344,14 @@ class NEOCluster(object):
if process not in except_storages:
process.start()
# wait for the admin node availability
- end_time = time.time() + MAX_START_TIME
- while True:
- if time.time() > end_time:
- raise AssertionError, 'Timeout when starting cluster'
+ def test():
try:
self.neoctl.getClusterState()
except NotReadyException:
- time.sleep(0.5)
- else:
- break
+ return False
+ return True
+ if not pdb.wait(test, MAX_START_TIME, 0.5):
+ raise AssertionError('Timeout when starting cluster')
self.port_allocator.reset()
def start(self, except_storages=()):
@@ -358,18 +360,16 @@ class NEOCluster(object):
neoctl = self.neoctl
neoctl.startCluster()
target_count = len(self.db_list) - len(except_storages)
- end_time = time.time() + MAX_START_TIME
- while True:
- storage_node_list = neoctl.getNodeList(
+ storage_node_list = []
+ def test():
+ storage_node_list[:] = neoctl.getNodeList(
node_type=NodeTypes.STORAGE)
# wait at least number of started storages, admin node can know
# more nodes when the cluster restart with an existing partition
# table referencing non-running nodes
- if len(storage_node_list) >= target_count:
- break
- time.sleep(0.5)
- if time.time() > end_time:
- raise AssertionError, 'Timeout when starting cluster'
+ return len(storage_node_list) >= target_count
+ if not pdb.wait(test, MAX_START_TIME, 0.5):
+ raise AssertionError('Timeout when starting cluster')
if storage_node_list:
self.expectClusterRunning()
neoctl.enableStorageList([x[2] for x in storage_node_list])
@@ -497,20 +497,18 @@ class NEOCluster(object):
def expectCondition(self, condition, timeout=0, delay=.5, on_fail=None):
end = time.time() + timeout + DELAY_SAFETY_MARGIN
- opaque = None
- opaque_history = []
- while time.time() < end:
- reached, opaque = condition(opaque)
- if reached:
- break
- else:
+ opaque_history = [None]
+ def test():
+ reached, opaque = condition(opaque_history[-1])
+ if not reached:
opaque_history.append(opaque)
- time.sleep(delay)
- else:
+ return reached
+ if not pdb.wait(test, timeout + DELAY_SAFETY_MARGIN, delay):
+ del opaque_history[0]
if on_fail is not None:
on_fail(opaque_history)
- raise AssertionError, 'Timeout while expecting condition. ' \
- 'History: %s' % (opaque_history, )
+ raise AssertionError('Timeout while expecting condition. '
+ 'History: %s' % opaque_history)
def expectAllMasters(self, node_count, state=None, *args, **kw):
def callback(last_try):
More information about the Neo-report
mailing list