Convert the weakref test suite to PyUNIT, and add tests that exercise weak
references on function objects and both bound and unbound methods.
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index a468575..1e193f1 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -1,137 +1,202 @@
 import sys
+import unittest
 import weakref
 
-from test_support import TestFailed, verify
+from test_support import run_unittest, verify
 
 
 class C:
-    pass
+    def method(self):
+        pass
 
 
-print "Basic Weak References"
+class Callable:
+    bar = None
 
-print "-- Liveness and referent identity"
-
-o = C()
-ref = weakref.ref(o)
-verify(ref() is not None, "weak reference to live object should be live")
-o2 = ref()
-verify(ref() is not None, "weak ref should still be live")
-verify(o is o2, "<ref>() should return original object if live")
-del o, o2
-del ref
-
-cbcalled = 0
-def callback(o):
-    global cbcalled
-    cbcalled = 1
-
-o = C()
-ref2 = weakref.ref(o, callback)
-del o
-verify(cbcalled,
-       "callback did not properly set 'cbcalled'")
-verify(ref2() is None,
-       "ref2 should be dead after deleting object reference")
-del ref2
+    def __call__(self, x):
+        self.bar = x
 
 
-print "-- Reference objects with callbacks"
-o = C()
-o.bar = 1
-ref1 = weakref.ref(o, id)
-ref2 = weakref.ref(o, id)
-del o
-verify(ref1() is None,
-       "expected reference to be invalidated")
-verify(ref2() is None,
-       "expected reference to be invalidated")
+def create_function():
+    def f(): pass
+    return f
+
+def create_bound_method():
+    return C().method
+
+def create_unbound_method():
+    return C.method
 
 
-print "-- Proxy objects with callbacks"
-o = C()
-o.bar = 1
-ref1 = weakref.proxy(o, id)
-ref2 = weakref.proxy(o, id)
-del o
-try:
-    ref1.bar
-except weakref.ReferenceError:
-    pass
-else:
-    raise TestFailed("expected ReferenceError exception")
-try:
-    ref2.bar
-except weakref.ReferenceError:
-    pass
-else:
-    raise TestFailed("expected ReferenceError exception")
+class TestBase(unittest.TestCase):
+
+    def setUp(self):
+        self.cbcalled = 0
+
+    def callback(self, ref):
+        self.cbcalled += 1
 
 
-print "-- Re-use of weak reference objects"
-print "     reference objects"
+class ReferencesTestCase(TestBase):
 
-o = C()
-ref1 = weakref.ref(o)
-# create a proxy to make sure that there's an intervening creation
-# between these two; it should make no difference
-proxy = weakref.proxy(o)
-ref2 = weakref.ref(o)
-verify(ref1 is ref2,
-       "reference object w/out callback should have been re-used")
+    def test_basic_ref(self):
+        self.check_basic_ref(C)
+        self.check_basic_ref(create_function)
+        self.check_basic_ref(create_bound_method)
+        self.check_basic_ref(create_unbound_method)
 
-o = C()
-proxy = weakref.proxy(o)
-ref1 = weakref.ref(o)
-ref2 = weakref.ref(o)
-verify(ref1 is ref2,
-       "reference object w/out callback should have been re-used")
-verify(weakref.getweakrefcount(o) == 2,
-       "wrong weak ref count for object")
-del proxy
-verify(weakref.getweakrefcount(o) == 1,
-       "wrong weak ref count for object after deleting proxy")
+    def test_basic_callback(self):
+        self.check_basic_callback(C)
+        self.check_basic_callback(create_function)
+        self.check_basic_callback(create_bound_method)
+        self.check_basic_callback(create_unbound_method)
 
-print "     proxy objects"
+    def test_multiple_callbacks(self):
+        o = C()
+        ref1 = weakref.ref(o, self.callback)
+        ref2 = weakref.ref(o, self.callback)
+        del o
+        self.assert_(ref1() is None,
+                     "expected reference to be invalidated")
+        self.assert_(ref2() is None,
+                     "expected reference to be invalidated")
+        self.assert_(self.cbcalled == 2,
+                     "callback not called the right number of times")
 
-o = C()
-ref3 = weakref.proxy(o)
-ref4 = weakref.proxy(o)
-verify(ref3 is ref4,
-       "proxy object w/out callback should have been re-used")
+    def test_proxy_ref(self):
+        o = C()
+        o.bar = 1
+        ref1 = weakref.proxy(o, self.callback)
+        ref2 = weakref.proxy(o, self.callback)
+        del o
 
+        def check(proxy):
+            proxy.bar
 
-def clearing1(r):
-    print "clearing ref 1"
+        self.assertRaises(weakref.ReferenceError, check, ref1)
+        self.assertRaises(weakref.ReferenceError, check, ref2)
+        self.assert_(self.cbcalled == 2)
 
-def clearing2(r):
-    print "clearing ref 2"
+    def check_basic_ref(self, factory):
+        o = factory()
+        ref = weakref.ref(o)
+        self.assert_(ref() is not None,
+                     "weak reference to live object should be live")
+        o2 = ref()
+        self.assert_(o is o2,
+                     "<ref>() should return original object if live")
 
-o = C()
-ref1 = weakref.ref(o, clearing1)
-ref2 = weakref.ref(o, clearing2)
-verify(weakref.getweakrefcount(o) == 2,
-       "got wrong number of weak reference objects")
-del o
+    def check_basic_callback(self, factory):
+        self.cbcalled = 0
+        o = factory()
+        ref = weakref.ref(o, self.callback)
+        del o
+        verify(self.cbcalled == 1,
+               "callback did not properly set 'cbcalled'")
+        verify(ref() is None,
+               "ref2 should be dead after deleting object reference")
 
-o = C()
-ref1 = weakref.ref(o, clearing1)
-ref2 = weakref.ref(o, clearing2)
-del ref1
-verify(weakref.getweakrefs(o) == [ref2],
-       "list of refs does not match")
-del o
+    def test_ref_reuse(self):
+        o = C()
+        ref1 = weakref.ref(o)
+        # create a proxy to make sure that there's an intervening creation
+        # between these two; it should make no difference
+        proxy = weakref.proxy(o)
+        ref2 = weakref.ref(o)
+        self.assert_(ref1 is ref2,
+                     "reference object w/out callback should be re-used")
 
-o = C()
-ref1 = weakref.ref(o, clearing1)
-ref2 = weakref.ref(o, clearing2)
-del ref2
-verify(weakref.getweakrefs(o) == [ref1],
-       "list of refs does not match")
-del o
+        o = C()
+        proxy = weakref.proxy(o)
+        ref1 = weakref.ref(o)
+        ref2 = weakref.ref(o)
+        self.assert_(ref1 is ref2,
+                     "reference object w/out callback should be re-used")
+        self.assert_(weakref.getweakrefcount(o) == 2,
+                     "wrong weak ref count for object")
+        del proxy
+        self.assert_(weakref.getweakrefcount(o) == 1,
+                     "wrong weak ref count for object after deleting proxy")
 
-print
-print "Weak Valued Dictionaries"
+    def test_proxy_reuse(self):
+        o = C()
+        proxy1 = weakref.proxy(o)
+        ref = weakref.ref(o)
+        proxy2 = weakref.proxy(o)
+        self.assert_(proxy1 is proxy2,
+                     "proxy object w/out callback should have been re-used")
+
+    def test_basic_proxy(self):
+        o = C()
+        self.check_proxy(o, weakref.proxy(o))
+
+    def test_callable_proxy(self):
+        o = Callable()
+        ref1 = weakref.proxy(o)
+
+        self.check_proxy(o, ref1)
+
+        self.assert_(type(ref1) is weakref.CallableProxyType,
+                     "proxy is not of callable type")
+        ref1('twinkies!')
+        self.assert_(o.bar == 'twinkies!',
+                     "call through proxy not passed through to original")
+
+        # expect due to too few args
+        self.assertRaises(TypeError, ref1)
+
+        # expect due to too many args
+        self.assertRaises(TypeError, ref1, 1, 2, 3)
+
+    def check_proxy(self, o, proxy):
+        o.foo = 1
+        self.assert_(proxy.foo == 1,
+                     "proxy does not reflect attribute addition")
+        o.foo = 2
+        self.assert_(proxy.foo == 2,
+                     "proxy does not reflect attribute modification")
+        del o.foo
+        self.assert_(not hasattr(proxy, 'foo'),
+                     "proxy does not reflect attribute removal")
+
+        proxy.foo = 1
+        self.assert_(o.foo == 1,
+                     "object does not reflect attribute addition via proxy")
+        proxy.foo = 2
+        self.assert_(
+            o.foo == 2,
+            "object does not reflect attribute modification via proxy")
+        del proxy.foo
+        self.assert_(not hasattr(o, 'foo'),
+                     "object does not reflect attribute removal via proxy")
+
+    def test_getweakrefcount(self):
+        o = C()
+        ref1 = weakref.ref(o)
+        ref2 = weakref.ref(o, self.callback)
+        self.assert_(weakref.getweakrefcount(o) == 2,
+                     "got wrong number of weak reference objects")
+
+        proxy1 = weakref.proxy(o)
+        proxy2 = weakref.proxy(o, self.callback)
+        self.assert_(weakref.getweakrefcount(o) == 4,
+                     "got wrong number of weak reference objects")
+
+    def test_getweakrefs(self):
+        o = C()
+        ref1 = weakref.ref(o, self.callback)
+        ref2 = weakref.ref(o, self.callback)
+        del ref1
+        self.assert_(weakref.getweakrefs(o) == [ref2],
+                     "list of refs does not match")
+
+        o = C()
+        ref1 = weakref.ref(o, self.callback)
+        ref2 = weakref.ref(o, self.callback)
+        del ref2
+        self.assert_(weakref.getweakrefs(o) == [ref1],
+                     "list of refs does not match")
+
 
 class Object:
     def __init__(self, arg):
@@ -139,112 +204,63 @@
     def __repr__(self):
         return "<Object %r>" % self.arg
 
-dict = weakref.mapping()
-objects = map(Object, range(10))
-for o in objects:
-    dict[o.arg] = o
-print "objects are stored in weak dict"
-for o in objects:
-    verify(weakref.getweakrefcount(o) == 1,
-           "wrong number of weak references to %r!" % o)
-    verify(o is dict[o.arg],
-           "wrong object returned by weak dict!")
-items1 = dict.items()
-items2 = dict.copy().items()
-items1.sort()
-items2.sort()
-verify(items1 == items2,
-       "cloning of weak-valued dictionary did not work!")
-del items1, items2
-dict.clear()
-print "weak dict test complete"
 
-print
-print "Weak Keyed Dictionaries"
+class MappingTestCase(TestBase):
 
-dict = weakref.mapping(weakkeys=1)
-objects = map(Object, range(10))
-for o in objects:
-    dict[o] = o.arg
-print "objects are stored in weak dict"
-for o in objects:
-    verify(weakref.getweakrefcount(o) == 1,
-           "wrong number of weak references to %r!" % o)
-    verify(o.arg is dict[o],
-           "wrong object returned by weak dict!")
-items1 = dict.items()
-items2 = dict.copy().items()
-items1.sort()
-items2.sort()
-verify(items1 == items2,
-       "cloning of weak-keyed dictionary did not work!")
-del items1, items2
-del objects, o
-verify(len(dict)==0, "deleting the keys did not clear the dictionary")
-print "weak key dict test complete"
+    COUNT = 10
+
+    def test_weak_values(self):
+        dict = weakref.mapping()
+        objects = map(Object, range(self.COUNT))
+        for o in objects:
+            dict[o.arg] = o
+
+        for o in objects:
+            self.assert_(weakref.getweakrefcount(o) == 1,
+                         "wrong number of weak references to %r!" % o)
+            self.assert_(o is dict[o.arg],
+                         "wrong object returned by weak dict!")
+        items1 = dict.items()
+        items2 = dict.copy().items()
+        items1.sort()
+        items2.sort()
+        self.assert_(items1 == items2,
+                     "cloning of weak-valued dictionary did not work!")
+        del items1, items2
+        self.assert_(len(dict) == self.COUNT)
+        del objects[0]
+        self.assert_(len(dict) == (self.COUNT - 1),
+                     "deleting object did not cause dictionary update")
+        del objects, o
+        self.assert_(len(dict) == 0,
+                     "deleting the values did not clear the dictionary")
+
+    def test_weak_keys(self):
+        dict = weakref.mapping(weakkeys=1)
+        objects = map(Object, range(self.COUNT))
+        for o in objects:
+            dict[o] = o.arg
+
+        for o in objects:
+            self.assert_(weakref.getweakrefcount(o) == 1,
+                         "wrong number of weak references to %r!" % o)
+            self.assert_(o.arg is dict[o],
+                         "wrong object returned by weak dict!")
+        items1 = dict.items()
+        items2 = dict.copy().items()
+        items1.sort()
+        items2.sort()
+        self.assert_(items1 == items2,
+                     "cloning of weak-keyed dictionary did not work!")
+        del items1, items2
+        self.assert_(len(dict) == self.COUNT)
+        del objects[0]
+        self.assert_(len(dict) == (self.COUNT - 1),
+                     "deleting object did not cause dictionary update")
+        del objects, o
+        self.assert_(len(dict) == 0,
+                     "deleting the keys did not clear the dictionary")
 
 
-print
-print "Non-callable Proxy References"
-print "XXX -- tests not written!"
-
-
-def test_proxy(o, proxy):
-    o.foo = 1
-    verify(proxy.foo == 1,
-           "proxy does not reflect attribute addition")
-    o.foo = 2
-    verify(proxy.foo == 2,
-           "proxy does not reflect attribute modification")
-    del o.foo
-    verify(not hasattr(proxy, 'foo'),
-           "proxy does not reflect attribute removal")
-
-    proxy.foo = 1
-    verify(o.foo == 1,
-           "object does not reflect attribute addition via proxy")
-    proxy.foo = 2
-    verify(o.foo == 2,
-           "object does not reflect attribute modification via proxy")
-    del proxy.foo
-    verify(not hasattr(o, 'foo'),
-           "object does not reflect attribute removal via proxy")
-
-
-o = C()
-test_proxy(o, weakref.proxy(o))
-
-print
-print "Callable Proxy References"
-
-class Callable:
-    bar = None
-    def __call__(self, x):
-        self.bar = x
-
-o = Callable()
-ref1 = weakref.proxy(o)
-
-test_proxy(o, ref1)
-
-verify(type(ref1) is weakref.CallableProxyType,
-       "proxy is not of callable type")
-ref1('twinkies!')
-verify(o.bar == 'twinkies!',
-       "call through proxy not passed through to original")
-
-try:
-    ref1()
-except TypeError:
-    # expect due to too few args
-    pass
-else:
-    raise TestFailed("did not catch expected TypeError -- too few args")
-
-try:
-    ref1(1, 2, 3)
-except TypeError:
-    # expect due to too many args
-    pass
-else:
-    raise TestFailed("did not catch expected TypeError -- too many args")
+run_unittest(ReferencesTestCase)
+run_unittest(MappingTestCase)