diff --git a/pyqtgraph/tests/test_ref_cycles.py b/pyqtgraph/tests/test_ref_cycles.py index ac65eaf9..87e0d71d 100644 --- a/pyqtgraph/tests/test_ref_cycles.py +++ b/pyqtgraph/tests/test_ref_cycles.py @@ -4,7 +4,7 @@ Test for unwanted reference cycles """ import pyqtgraph as pg import numpy as np -import gc +import gc, weakref app = pg.mkQApp() def processEvents(): @@ -15,31 +15,46 @@ def processEvents(): # manually. app.sendPostedEvents(None, pg.QtCore.QEvent.DeferredDelete) -def test_PlotItem(): - for i in range(10): - plt = pg.PlotItem() - plt.plot(np.random.normal(size=10000)) - processEvents() +#def test_PlotItem(): + #for i in range(10): + #plt = pg.PlotItem() + #plt.plot(np.random.normal(size=10000)) + #processEvents() - ot = pg.debug.ObjTracker() + #ot = pg.debug.ObjTracker() - plots = [] - for i in range(10): - plt = pg.PlotItem() - plt.plot(np.random.normal(size=10000)) - plots.append(plt) - processEvents() + #plots = [] + #for i in range(10): + #plt = pg.PlotItem() + #plt.plot(np.random.normal(size=10000)) + #plots.append(plt) + #processEvents() - ot.diff() + #ot.diff() - del plots - processEvents() + #del plots + #processEvents() - ot.diff() + #ot.diff() - return ot + #return ot +def test_PlotWidget(): + def mkref(*args, **kwds): + iv = pg.PlotWidget(*args, **kwds) + return weakref.ref(iv) + + for i in range(100): + assert mkref()() is None + +def test_ImageView(): + def mkref(*args, **kwds): + iv = pg.ImageView(*args, **kwds) + return weakref.ref(iv) + + for i in range(100): + assert mkref()() is None if __name__ == '__main__': ot = test_PlotItem() diff --git a/pyqtgraph/tests/test_stability.py b/pyqtgraph/tests/test_stability.py index 3838af7d..709080ac 100644 --- a/pyqtgraph/tests/test_stability.py +++ b/pyqtgraph/tests/test_stability.py @@ -6,34 +6,146 @@ the tear them down repeatedly. The purpose of this is to attempt to generate segmentation faults. """ +from PyQt4.QtTest import QTest import pyqtgraph as pg -import random +from random import seed, randint +import sys, gc, weakref -random.seed(12345) +app = pg.mkQApp() -widgetTypes = [pg.PlotWidget, pg.ImageView, pg.GraphicsView, pg.QtGui.QWidget, - pg.QtGui.QTreeWidget, pg.QtGui.QPushButton] +seed(12345) -itemTypes = [pg.PlotCurveItem, pg.ImageItem, pg.PlotDataItem, pg.ViewBox, - pg.QtGui.QGraphicsRectItem] +widgetTypes = [ + pg.PlotWidget, + pg.ImageView, + pg.GraphicsView, + pg.QtGui.QWidget, + pg.QtGui.QTreeWidget, + pg.QtGui.QPushButton, + ] + +itemTypes = [ + pg.PlotCurveItem, + pg.ImageItem, + pg.PlotDataItem, + pg.ViewBox, + pg.QtGui.QGraphicsRectItem + ] + +widgets = [] +items = [] +allWidgets = weakref.WeakSet() + +def test_stability(): + global allWidgets + try: + gc.disable() + actions = [ + createWidget, + #setParent, + forgetWidget, + showWidget, + processEvents, + #raiseException, + #addReference, + ] + + thread = WorkThread() + #thread.start() + + while True: + try: + action = randItem(actions) + action() + print('[%d widgets alive]' % len(allWidgets)) + except KeyboardInterrupt: + thread.kill() + break + except: + sys.excepthook(*sys.exc_info()) + finally: + gc.enable() + + + +class WorkThread(pg.QtCore.QThread): + '''Intended to give the gc an opportunity to run from a non-gui thread.''' + def run(self): + i = 0 + while True: + i += 1 + if (i % 1000000) == 0: + print('--worker--') + + +def randItem(items): + return items[randint(0, len(items)-1)] + +def p(msg): + print(msg) + sys.stdout.flush() + +def createWidget(): + p('create widget') + global widgets, allWidgets + widget = randItem(widgetTypes)() + widgets.append(widget) + allWidgets.add(widget) + p(" %s" % widget) + return widget + +def setParent(): + p('set parent') + global widgets + if len(widgets) < 2: + return + child = parent = None + while child is parent: + child = randItem(widgets) + parent = randItem(widgets) + p(" %s parent of %s" % (parent, child)) + child.setParent(parent) + +def forgetWidget(): + p('forget widget') + global widgets + if len(widgets) < 1: + return + widget = randItem(widgets) + p(' %s' % widget) + widgets.remove(widget) + +def showWidget(): + p('show widget') + global widgets + if len(widgets) < 1: + return + widget = randItem(widgets) + p(' %s' % widget) + widget.show() + +def processEvents(): + p('process events') + QTest.qWait(25) + +class TestException(Exception): + pass + +def raiseException(): + p('raise exception') + raise TestException("A test exception") + +def addReference(): + p('add reference') + global widgets + if len(widgets) < 1: + return + obj1 = randItem(widgets) + obj2 = randItem(widgets) + p(' %s -> %s' % (obj1, obj2)) + obj1._testref = obj2 + -while True: - action = random.randint(0,5) - if action == 0: - # create a widget - pass - elif action == 1: - # set parent (widget or None), possibly create a reference in either direction - pass - elif action == 2: - # - pass - elif action == 3: - pass - - - - - - +if __name__ == '__main__': + test_stability() \ No newline at end of file