bpo-31130: IDLE -- stop leaks in test_configdialog. (#3016)

Initial patch by Victor Stinner.
This commit is contained in:
Terry Jan Reedy 2017-08-07 14:22:44 -04:00 committed by GitHub
parent 89225871d3
commit 733d0f63c5
3 changed files with 51 additions and 39 deletions

View file

@ -1856,6 +1856,7 @@ class VarTrace:
def clear(self): def clear(self):
"Clear lists (for tests)." "Clear lists (for tests)."
# Call after all tests in a module to avoid memory leaks.
self.untraced.clear() self.untraced.clear()
self.traced.clear() self.traced.clear()

View file

@ -9,7 +9,7 @@ requires('gui')
import unittest import unittest
from unittest import mock from unittest import mock
from idlelib.idle_test.mock_idle import Func from idlelib.idle_test.mock_idle import Func
from tkinter import Tk, Frame, IntVar, BooleanVar, DISABLED, NORMAL from tkinter import Tk, Frame, StringVar, IntVar, BooleanVar, DISABLED, NORMAL
from idlelib import config from idlelib import config
from idlelib.configdialog import idleConf, changes, tracers from idlelib.configdialog import idleConf, changes, tracers
@ -41,6 +41,8 @@ def tearDownModule():
global root, dialog global root, dialog
idleConf.userCfg = usercfg idleConf.userCfg = usercfg
tracers.detach() tracers.detach()
tracers.clear()
changes.clear()
del dialog del dialog
root.update_idletasks() root.update_idletasks()
root.destroy() root.destroy()
@ -442,15 +444,19 @@ class GenPageTest(unittest.TestCase):
class VarTraceTest(unittest.TestCase): class VarTraceTest(unittest.TestCase):
def setUp(self): @classmethod
changes.clear() def setUpClass(cls):
tracers.clear() cls.tracers = configdialog.VarTrace()
self.v1 = IntVar(root) cls.iv = IntVar(root)
self.v2 = BooleanVar(root) cls.bv = BooleanVar(root)
self.called = 0
def tearDown(self): @classmethod
del self.v1, self.v2 def tearDownClass(cls):
del cls.tracers, cls.iv, cls.bv
def setUp(self):
self.tracers.clear()
self.called = 0
def var_changed_increment(self, *params): def var_changed_increment(self, *params):
self.called += 13 self.called += 13
@ -459,64 +465,68 @@ class VarTraceTest(unittest.TestCase):
pass pass
def test_init(self): def test_init(self):
tracers.__init__() tr = self.tracers
self.assertEqual(tracers.untraced, []) tr.__init__()
self.assertEqual(tracers.traced, []) self.assertEqual(tr.untraced, [])
self.assertEqual(tr.traced, [])
def test_clear(self): def test_clear(self):
tracers.untraced.append(0) tr = self.tracers
tracers.traced.append(1) tr.untraced.append(0)
tracers.clear() tr.traced.append(1)
self.assertEqual(tracers.untraced, []) tr.clear()
self.assertEqual(tracers.traced, []) self.assertEqual(tr.untraced, [])
self.assertEqual(tr.traced, [])
def test_add(self): def test_add(self):
tr = tracers tr = self.tracers
func = Func() func = Func()
cb = tr.make_callback = mock.Mock(return_value=func) cb = tr.make_callback = mock.Mock(return_value=func)
v1 = tr.add(self.v1, self.var_changed_increment) iv = tr.add(self.iv, self.var_changed_increment)
self.assertIsInstance(v1, IntVar) self.assertIs(iv, self.iv)
v2 = tr.add(self.v2, self.var_changed_boolean) bv = tr.add(self.bv, self.var_changed_boolean)
self.assertIsInstance(v2, BooleanVar) self.assertIs(bv, self.bv)
v3 = IntVar(root) sv = StringVar(root)
v3 = tr.add(v3, ('main', 'section', 'option')) sv2 = tr.add(sv, ('main', 'section', 'option'))
self.assertIs(sv2, sv)
cb.assert_called_once() cb.assert_called_once()
cb.assert_called_with(v3, ('main', 'section', 'option')) cb.assert_called_with(sv, ('main', 'section', 'option'))
expected = [(v1, self.var_changed_increment), expected = [(iv, self.var_changed_increment),
(v2, self.var_changed_boolean), (bv, self.var_changed_boolean),
(v3, func)] (sv, func)]
self.assertEqual(tr.traced, []) self.assertEqual(tr.traced, [])
self.assertEqual(tr.untraced, expected) self.assertEqual(tr.untraced, expected)
del tr.make_callback del tr.make_callback
def test_make_callback(self): def test_make_callback(self):
cb = tracers.make_callback(self.v1, ('main', 'section', 'option')) cb = self.tracers.make_callback(self.iv, ('main', 'section', 'option'))
self.assertTrue(callable(cb)) self.assertTrue(callable(cb))
self.v1.set(42) self.iv.set(42)
# Not attached, so set didn't invoke the callback. # Not attached, so set didn't invoke the callback.
self.assertNotIn('section', changes['main']) self.assertNotIn('section', changes['main'])
# Invoke callback manually. # Invoke callback manually.
cb() cb()
self.assertIn('section', changes['main']) self.assertIn('section', changes['main'])
self.assertEqual(changes['main']['section']['option'], '42') self.assertEqual(changes['main']['section']['option'], '42')
changes.clear()
def test_attach_detach(self): def test_attach_detach(self):
tr = tracers tr = self.tracers
v1 = tr.add(self.v1, self.var_changed_increment) iv = tr.add(self.iv, self.var_changed_increment)
v2 = tr.add(self.v2, self.var_changed_boolean) bv = tr.add(self.bv, self.var_changed_boolean)
expected = [(v1, self.var_changed_increment), expected = [(iv, self.var_changed_increment),
(v2, self.var_changed_boolean)] (bv, self.var_changed_boolean)]
# Attach callbacks and test call increment. # Attach callbacks and test call increment.
tr.attach() tr.attach()
self.assertEqual(tr.untraced, []) self.assertEqual(tr.untraced, [])
self.assertCountEqual(tr.traced, expected) self.assertCountEqual(tr.traced, expected)
v1.set(1) iv.set(1)
self.assertEqual(v1.get(), 1) self.assertEqual(iv.get(), 1)
self.assertEqual(self.called, 13) self.assertEqual(self.called, 13)
# Check that only one callback is attached to a variable. # Check that only one callback is attached to a variable.
@ -524,7 +534,7 @@ class VarTraceTest(unittest.TestCase):
# would be called twice and the counter would be 2. # would be called twice and the counter would be 2.
self.called = 0 self.called = 0
tr.attach() tr.attach()
v1.set(1) iv.set(1)
self.assertEqual(self.called, 13) self.assertEqual(self.called, 13)
# Detach callbacks. # Detach callbacks.
@ -532,7 +542,7 @@ class VarTraceTest(unittest.TestCase):
tr.detach() tr.detach()
self.assertEqual(tr.traced, []) self.assertEqual(tr.traced, [])
self.assertCountEqual(tr.untraced, expected) self.assertCountEqual(tr.untraced, expected)
v1.set(1) iv.set(1)
self.assertEqual(self.called, 0) self.assertEqual(self.called, 0)

View file

@ -0,0 +1 @@
IDLE -- stop leaks in test_configdialog. Initial patch by Victor Stinner.