Home | History | Annotate | Download | only in test
      1 # Copyright 2007 Google, Inc. All Rights Reserved.
      2 # Licensed to PSF under a Contributor Agreement.
      3 
      4 """Unit tests for abc.py."""
      5 
      6 import unittest, weakref
      7 from test import test_support
      8 
      9 import abc
     10 from inspect import isabstract
     11 
     12 
     13 class TestABC(unittest.TestCase):
     14 
     15     def test_abstractmethod_basics(self):
     16         @abc.abstractmethod
     17         def foo(self): pass
     18         self.assertTrue(foo.__isabstractmethod__)
     19         def bar(self): pass
     20         self.assertFalse(hasattr(bar, "__isabstractmethod__"))
     21 
     22     def test_abstractproperty_basics(self):
     23         @abc.abstractproperty
     24         def foo(self): pass
     25         self.assertTrue(foo.__isabstractmethod__)
     26         def bar(self): pass
     27         self.assertFalse(hasattr(bar, "__isabstractmethod__"))
     28 
     29         class C:
     30             __metaclass__ = abc.ABCMeta
     31             @abc.abstractproperty
     32             def foo(self): return 3
     33         class D(C):
     34             @property
     35             def foo(self): return super(D, self).foo
     36         self.assertEqual(D().foo, 3)
     37 
     38     def test_abstractmethod_integration(self):
     39         for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
     40             class C:
     41                 __metaclass__ = abc.ABCMeta
     42                 @abstractthing
     43                 def foo(self): pass  # abstract
     44                 def bar(self): pass  # concrete
     45             self.assertEqual(C.__abstractmethods__, set(["foo"]))
     46             self.assertRaises(TypeError, C)  # because foo is abstract
     47             self.assertTrue(isabstract(C))
     48             class D(C):
     49                 def bar(self): pass  # concrete override of concrete
     50             self.assertEqual(D.__abstractmethods__, set(["foo"]))
     51             self.assertRaises(TypeError, D)  # because foo is still abstract
     52             self.assertTrue(isabstract(D))
     53             class E(D):
     54                 def foo(self): pass
     55             self.assertEqual(E.__abstractmethods__, set())
     56             E()  # now foo is concrete, too
     57             self.assertFalse(isabstract(E))
     58             class F(E):
     59                 @abstractthing
     60                 def bar(self): pass  # abstract override of concrete
     61             self.assertEqual(F.__abstractmethods__, set(["bar"]))
     62             self.assertRaises(TypeError, F)  # because bar is abstract now
     63             self.assertTrue(isabstract(F))
     64 
     65     def test_subclass_oldstyle_class(self):
     66         class A:
     67             __metaclass__ = abc.ABCMeta
     68         class OldstyleClass:
     69             pass
     70         self.assertFalse(issubclass(OldstyleClass, A))
     71         self.assertFalse(issubclass(A, OldstyleClass))
     72 
     73     def test_isinstance_class(self):
     74         class A:
     75             __metaclass__ = abc.ABCMeta
     76         class OldstyleClass:
     77             pass
     78         self.assertFalse(isinstance(OldstyleClass, A))
     79         self.assertTrue(isinstance(OldstyleClass, type(OldstyleClass)))
     80         self.assertFalse(isinstance(A, OldstyleClass))
     81         # This raises a recursion depth error, but is low-priority:
     82         # self.assertTrue(isinstance(A, abc.ABCMeta))
     83 
     84     def test_registration_basics(self):
     85         class A:
     86             __metaclass__ = abc.ABCMeta
     87         class B(object):
     88             pass
     89         b = B()
     90         self.assertFalse(issubclass(B, A))
     91         self.assertFalse(issubclass(B, (A,)))
     92         self.assertNotIsInstance(b, A)
     93         self.assertNotIsInstance(b, (A,))
     94         A.register(B)
     95         self.assertTrue(issubclass(B, A))
     96         self.assertTrue(issubclass(B, (A,)))
     97         self.assertIsInstance(b, A)
     98         self.assertIsInstance(b, (A,))
     99         class C(B):
    100             pass
    101         c = C()
    102         self.assertTrue(issubclass(C, A))
    103         self.assertTrue(issubclass(C, (A,)))
    104         self.assertIsInstance(c, A)
    105         self.assertIsInstance(c, (A,))
    106 
    107     def test_isinstance_invalidation(self):
    108         class A:
    109             __metaclass__ = abc.ABCMeta
    110         class B(object):
    111             pass
    112         b = B()
    113         self.assertFalse(isinstance(b, A))
    114         self.assertFalse(isinstance(b, (A,)))
    115         A.register(B)
    116         self.assertTrue(isinstance(b, A))
    117         self.assertTrue(isinstance(b, (A,)))
    118 
    119     def test_registration_builtins(self):
    120         class A:
    121             __metaclass__ = abc.ABCMeta
    122         A.register(int)
    123         self.assertIsInstance(42, A)
    124         self.assertIsInstance(42, (A,))
    125         self.assertTrue(issubclass(int, A))
    126         self.assertTrue(issubclass(int, (A,)))
    127         class B(A):
    128             pass
    129         B.register(basestring)
    130         self.assertIsInstance("", A)
    131         self.assertIsInstance("", (A,))
    132         self.assertTrue(issubclass(str, A))
    133         self.assertTrue(issubclass(str, (A,)))
    134 
    135     def test_registration_edge_cases(self):
    136         class A:
    137             __metaclass__ = abc.ABCMeta
    138         A.register(A)  # should pass silently
    139         class A1(A):
    140             pass
    141         self.assertRaises(RuntimeError, A1.register, A)  # cycles not allowed
    142         class B(object):
    143             pass
    144         A1.register(B)  # ok
    145         A1.register(B)  # should pass silently
    146         class C(A):
    147             pass
    148         A.register(C)  # should pass silently
    149         self.assertRaises(RuntimeError, C.register, A)  # cycles not allowed
    150         C.register(B)  # ok
    151 
    152     def test_register_non_class(self):
    153         class A(object):
    154             __metaclass__ = abc.ABCMeta
    155         self.assertRaisesRegexp(TypeError, "Can only register classes",
    156                                 A.register, 4)
    157 
    158     def test_registration_transitiveness(self):
    159         class A:
    160             __metaclass__ = abc.ABCMeta
    161         self.assertTrue(issubclass(A, A))
    162         self.assertTrue(issubclass(A, (A,)))
    163         class B:
    164             __metaclass__ = abc.ABCMeta
    165         self.assertFalse(issubclass(A, B))
    166         self.assertFalse(issubclass(A, (B,)))
    167         self.assertFalse(issubclass(B, A))
    168         self.assertFalse(issubclass(B, (A,)))
    169         class C:
    170             __metaclass__ = abc.ABCMeta
    171         A.register(B)
    172         class B1(B):
    173             pass
    174         self.assertTrue(issubclass(B1, A))
    175         self.assertTrue(issubclass(B1, (A,)))
    176         class C1(C):
    177             pass
    178         B1.register(C1)
    179         self.assertFalse(issubclass(C, B))
    180         self.assertFalse(issubclass(C, (B,)))
    181         self.assertFalse(issubclass(C, B1))
    182         self.assertFalse(issubclass(C, (B1,)))
    183         self.assertTrue(issubclass(C1, A))
    184         self.assertTrue(issubclass(C1, (A,)))
    185         self.assertTrue(issubclass(C1, B))
    186         self.assertTrue(issubclass(C1, (B,)))
    187         self.assertTrue(issubclass(C1, B1))
    188         self.assertTrue(issubclass(C1, (B1,)))
    189         C1.register(int)
    190         class MyInt(int):
    191             pass
    192         self.assertTrue(issubclass(MyInt, A))
    193         self.assertTrue(issubclass(MyInt, (A,)))
    194         self.assertIsInstance(42, A)
    195         self.assertIsInstance(42, (A,))
    196 
    197     def test_all_new_methods_are_called(self):
    198         class A:
    199             __metaclass__ = abc.ABCMeta
    200         class B(object):
    201             counter = 0
    202             def __new__(cls):
    203                 B.counter += 1
    204                 return super(B, cls).__new__(cls)
    205         class C(A, B):
    206             pass
    207         self.assertEqual(B.counter, 0)
    208         C()
    209         self.assertEqual(B.counter, 1)
    210 
    211     def test_cache_leak(self):
    212         # See issue #2521.
    213         class A(object):
    214             __metaclass__ = abc.ABCMeta
    215             @abc.abstractmethod
    216             def f(self):
    217                 pass
    218         class C(A):
    219             def f(self):
    220                 A.f(self)
    221         r = weakref.ref(C)
    222         # Trigger cache.
    223         C().f()
    224         del C
    225         test_support.gc_collect()
    226         self.assertEqual(r(), None)
    227 
    228 def test_main():
    229     test_support.run_unittest(TestABC)
    230 
    231 
    232 if __name__ == "__main__":
    233     unittest.main()
    234