Home | History | Annotate | Download | only in test
      1 "Test the functionality of Python classes implementing operators."
      2 
      3 import unittest
      4 
      5 from test import test_support
      6 
      7 testmeths = [
      8 
      9 # Binary operations
     10     "add",
     11     "radd",
     12     "sub",
     13     "rsub",
     14     "mul",
     15     "rmul",
     16     "div",
     17     "rdiv",
     18     "mod",
     19     "rmod",
     20     "divmod",
     21     "rdivmod",
     22     "pow",
     23     "rpow",
     24     "rshift",
     25     "rrshift",
     26     "lshift",
     27     "rlshift",
     28     "and",
     29     "rand",
     30     "or",
     31     "ror",
     32     "xor",
     33     "rxor",
     34 
     35 # List/dict operations
     36     "contains",
     37     "getitem",
     38     "getslice",
     39     "setitem",
     40     "setslice",
     41     "delitem",
     42     "delslice",
     43 
     44 # Unary operations
     45     "neg",
     46     "pos",
     47     "abs",
     48 
     49 # generic operations
     50     "init",
     51     ]
     52 
     53 # These need to return something other than None
     54 #    "coerce",
     55 #    "hash",
     56 #    "str",
     57 #    "repr",
     58 #    "int",
     59 #    "long",
     60 #    "float",
     61 #    "oct",
     62 #    "hex",
     63 
     64 # These are separate because they can influence the test of other methods.
     65 #    "getattr",
     66 #    "setattr",
     67 #    "delattr",
     68 
     69 callLst = []
     70 def trackCall(f):
     71     def track(*args, **kwargs):
     72         callLst.append((f.__name__, args))
     73         return f(*args, **kwargs)
     74     return track
     75 
     76 class AllTests:
     77     trackCall = trackCall
     78 
     79     @trackCall
     80     def __coerce__(self, *args):
     81         return (self,) + args
     82 
     83     @trackCall
     84     def __hash__(self, *args):
     85         return hash(id(self))
     86 
     87     @trackCall
     88     def __str__(self, *args):
     89         return "AllTests"
     90 
     91     @trackCall
     92     def __repr__(self, *args):
     93         return "AllTests"
     94 
     95     @trackCall
     96     def __int__(self, *args):
     97         return 1
     98 
     99     @trackCall
    100     def __float__(self, *args):
    101         return 1.0
    102 
    103     @trackCall
    104     def __long__(self, *args):
    105         return 1L
    106 
    107     @trackCall
    108     def __oct__(self, *args):
    109         return '01'
    110 
    111     @trackCall
    112     def __hex__(self, *args):
    113         return '0x1'
    114 
    115     @trackCall
    116     def __cmp__(self, *args):
    117         return 0
    118 
    119 # Synthesize all the other AllTests methods from the names in testmeths.
    120 
    121 method_template = """\
    122 @trackCall
    123 def __%(method)s__(self, *args):
    124     pass
    125 """
    126 
    127 for method in testmeths:
    128     exec method_template % locals() in AllTests.__dict__
    129 
    130 del method, method_template
    131 
    132 class ClassTests(unittest.TestCase):
    133     def setUp(self):
    134         callLst[:] = []
    135 
    136     def assertCallStack(self, expected_calls):
    137         actualCallList = callLst[:]  # need to copy because the comparison below will add
    138                                      # additional calls to callLst
    139         if expected_calls != actualCallList:
    140             self.fail("Expected call list:\n  %s\ndoes not match actual call list\n  %s" %
    141                       (expected_calls, actualCallList))
    142 
    143     def testInit(self):
    144         foo = AllTests()
    145         self.assertCallStack([("__init__", (foo,))])
    146 
    147     def testBinaryOps(self):
    148         testme = AllTests()
    149         # Binary operations
    150 
    151         callLst[:] = []
    152         testme + 1
    153         self.assertCallStack([("__coerce__", (testme, 1)), ("__add__", (testme, 1))])
    154 
    155         callLst[:] = []
    156         1 + testme
    157         self.assertCallStack([("__coerce__", (testme, 1)), ("__radd__", (testme, 1))])
    158 
    159         callLst[:] = []
    160         testme - 1
    161         self.assertCallStack([("__coerce__", (testme, 1)), ("__sub__", (testme, 1))])
    162 
    163         callLst[:] = []
    164         1 - testme
    165         self.assertCallStack([("__coerce__", (testme, 1)), ("__rsub__", (testme, 1))])
    166 
    167         callLst[:] = []
    168         testme * 1
    169         self.assertCallStack([("__coerce__", (testme, 1)), ("__mul__", (testme, 1))])
    170 
    171         callLst[:] = []
    172         1 * testme
    173         self.assertCallStack([("__coerce__", (testme, 1)), ("__rmul__", (testme, 1))])
    174 
    175         if 1/2 == 0:
    176             callLst[:] = []
    177             testme / 1
    178             self.assertCallStack([("__coerce__", (testme, 1)), ("__div__", (testme, 1))])
    179 
    180 
    181             callLst[:] = []
    182             1 / testme
    183             self.assertCallStack([("__coerce__", (testme, 1)), ("__rdiv__", (testme, 1))])
    184 
    185         callLst[:] = []
    186         testme % 1
    187         self.assertCallStack([("__coerce__", (testme, 1)), ("__mod__", (testme, 1))])
    188 
    189         callLst[:] = []
    190         1 % testme
    191         self.assertCallStack([("__coerce__", (testme, 1)), ("__rmod__", (testme, 1))])
    192 
    193 
    194         callLst[:] = []
    195         divmod(testme,1)
    196         self.assertCallStack([("__coerce__", (testme, 1)), ("__divmod__", (testme, 1))])
    197 
    198         callLst[:] = []
    199         divmod(1, testme)
    200         self.assertCallStack([("__coerce__", (testme, 1)), ("__rdivmod__", (testme, 1))])
    201 
    202         callLst[:] = []
    203         testme ** 1
    204         self.assertCallStack([("__coerce__", (testme, 1)), ("__pow__", (testme, 1))])
    205 
    206         callLst[:] = []
    207         1 ** testme
    208         self.assertCallStack([("__coerce__", (testme, 1)), ("__rpow__", (testme, 1))])
    209 
    210         callLst[:] = []
    211         testme >> 1
    212         self.assertCallStack([("__coerce__", (testme, 1)), ("__rshift__", (testme, 1))])
    213 
    214         callLst[:] = []
    215         1 >> testme
    216         self.assertCallStack([("__coerce__", (testme, 1)), ("__rrshift__", (testme, 1))])
    217 
    218         callLst[:] = []
    219         testme << 1
    220         self.assertCallStack([("__coerce__", (testme, 1)), ("__lshift__", (testme, 1))])
    221 
    222         callLst[:] = []
    223         1 << testme
    224         self.assertCallStack([("__coerce__", (testme, 1)), ("__rlshift__", (testme, 1))])
    225 
    226         callLst[:] = []
    227         testme & 1
    228         self.assertCallStack([("__coerce__", (testme, 1)), ("__and__", (testme, 1))])
    229 
    230         callLst[:] = []
    231         1 & testme
    232         self.assertCallStack([("__coerce__", (testme, 1)), ("__rand__", (testme, 1))])
    233 
    234         callLst[:] = []
    235         testme | 1
    236         self.assertCallStack([("__coerce__", (testme, 1)), ("__or__", (testme, 1))])
    237 
    238         callLst[:] = []
    239         1 | testme
    240         self.assertCallStack([("__coerce__", (testme, 1)), ("__ror__", (testme, 1))])
    241 
    242         callLst[:] = []
    243         testme ^ 1
    244         self.assertCallStack([("__coerce__", (testme, 1)), ("__xor__", (testme, 1))])
    245 
    246         callLst[:] = []
    247         1 ^ testme
    248         self.assertCallStack([("__coerce__", (testme, 1)), ("__rxor__", (testme, 1))])
    249 
    250     def testListAndDictOps(self):
    251         testme = AllTests()
    252 
    253         # List/dict operations
    254 
    255         class Empty: pass
    256 
    257         try:
    258             1 in Empty()
    259             self.fail('failed, should have raised TypeError')
    260         except TypeError:
    261             pass
    262 
    263         callLst[:] = []
    264         1 in testme
    265         self.assertCallStack([('__contains__', (testme, 1))])
    266 
    267         callLst[:] = []
    268         testme[1]
    269         self.assertCallStack([('__getitem__', (testme, 1))])
    270 
    271         callLst[:] = []
    272         testme[1] = 1
    273         self.assertCallStack([('__setitem__', (testme, 1, 1))])
    274 
    275         callLst[:] = []
    276         del testme[1]
    277         self.assertCallStack([('__delitem__', (testme, 1))])
    278 
    279         callLst[:] = []
    280         testme[:42]
    281         self.assertCallStack([('__getslice__', (testme, 0, 42))])
    282 
    283         callLst[:] = []
    284         testme[:42] = "The Answer"
    285         self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))])
    286 
    287         callLst[:] = []
    288         del testme[:42]
    289         self.assertCallStack([('__delslice__', (testme, 0, 42))])
    290 
    291         callLst[:] = []
    292         testme[2:1024:10]
    293         self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
    294 
    295         callLst[:] = []
    296         testme[2:1024:10] = "A lot"
    297         self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
    298                                                                     "A lot"))])
    299         callLst[:] = []
    300         del testme[2:1024:10]
    301         self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
    302 
    303         callLst[:] = []
    304         testme[:42, ..., :24:, 24, 100]
    305         self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
    306                                                         Ellipsis,
    307                                                         slice(None, 24, None),
    308                                                         24, 100)))])
    309         callLst[:] = []
    310         testme[:42, ..., :24:, 24, 100] = "Strange"
    311         self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
    312                                                         Ellipsis,
    313                                                         slice(None, 24, None),
    314                                                         24, 100), "Strange"))])
    315         callLst[:] = []
    316         del testme[:42, ..., :24:, 24, 100]
    317         self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
    318                                                         Ellipsis,
    319                                                         slice(None, 24, None),
    320                                                         24, 100)))])
    321 
    322         # Now remove the slice hooks to see if converting normal slices to
    323         #  slice object works.
    324 
    325         getslice = AllTests.__getslice__
    326         del AllTests.__getslice__
    327         setslice = AllTests.__setslice__
    328         del AllTests.__setslice__
    329         delslice = AllTests.__delslice__
    330         del AllTests.__delslice__
    331 
    332         # XXX when using new-style classes the slice testme[:42] produces
    333         #  slice(None, 42, None) instead of slice(0, 42, None). py3k will have
    334         #  to change this test.
    335         callLst[:] = []
    336         testme[:42]
    337         self.assertCallStack([('__getitem__', (testme, slice(0, 42, None)))])
    338 
    339         callLst[:] = []
    340         testme[:42] = "The Answer"
    341         self.assertCallStack([('__setitem__', (testme, slice(0, 42, None),
    342                                                                 "The Answer"))])
    343         callLst[:] = []
    344         del testme[:42]
    345         self.assertCallStack([('__delitem__', (testme, slice(0, 42, None)))])
    346 
    347         # Restore the slice methods, or the tests will fail with regrtest -R.
    348         AllTests.__getslice__ = getslice
    349         AllTests.__setslice__ = setslice
    350         AllTests.__delslice__ = delslice
    351 
    352 
    353     @test_support.cpython_only
    354     def testDelItem(self):
    355         class A:
    356             ok = False
    357             def __delitem__(self, key):
    358                 self.ok = True
    359         a = A()
    360         # Subtle: we need to call PySequence_SetItem, not PyMapping_SetItem.
    361         from _testcapi import sequence_delitem
    362         sequence_delitem(a, 2)
    363         self.assertTrue(a.ok)
    364 
    365 
    366     def testUnaryOps(self):
    367         testme = AllTests()
    368 
    369         callLst[:] = []
    370         -testme
    371         self.assertCallStack([('__neg__', (testme,))])
    372         callLst[:] = []
    373         +testme
    374         self.assertCallStack([('__pos__', (testme,))])
    375         callLst[:] = []
    376         abs(testme)
    377         self.assertCallStack([('__abs__', (testme,))])
    378         callLst[:] = []
    379         int(testme)
    380         self.assertCallStack([('__int__', (testme,))])
    381         callLst[:] = []
    382         long(testme)
    383         self.assertCallStack([('__long__', (testme,))])
    384         callLst[:] = []
    385         float(testme)
    386         self.assertCallStack([('__float__', (testme,))])
    387         callLst[:] = []
    388         oct(testme)
    389         self.assertCallStack([('__oct__', (testme,))])
    390         callLst[:] = []
    391         hex(testme)
    392         self.assertCallStack([('__hex__', (testme,))])
    393 
    394 
    395     def testMisc(self):
    396         testme = AllTests()
    397 
    398         callLst[:] = []
    399         hash(testme)
    400         self.assertCallStack([('__hash__', (testme,))])
    401 
    402         callLst[:] = []
    403         repr(testme)
    404         self.assertCallStack([('__repr__', (testme,))])
    405 
    406         callLst[:] = []
    407         str(testme)
    408         self.assertCallStack([('__str__', (testme,))])
    409 
    410         callLst[:] = []
    411         testme == 1
    412         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    413 
    414         callLst[:] = []
    415         testme < 1
    416         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    417 
    418         callLst[:] = []
    419         testme > 1
    420         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    421 
    422         callLst[:] = []
    423         eval('testme <> 1')  # XXX kill this in py3k
    424         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    425 
    426         callLst[:] = []
    427         testme != 1
    428         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    429 
    430         callLst[:] = []
    431         1 == testme
    432         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    433 
    434         callLst[:] = []
    435         1 < testme
    436         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    437 
    438         callLst[:] = []
    439         1 > testme
    440         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    441 
    442         callLst[:] = []
    443         eval('1 <> testme')
    444         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    445 
    446         callLst[:] = []
    447         1 != testme
    448         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    449 
    450 
    451     def testGetSetAndDel(self):
    452         # Interfering tests
    453         class ExtraTests(AllTests):
    454             @trackCall
    455             def __getattr__(self, *args):
    456                 return "SomeVal"
    457 
    458             @trackCall
    459             def __setattr__(self, *args):
    460                 pass
    461 
    462             @trackCall
    463             def __delattr__(self, *args):
    464                 pass
    465 
    466         testme = ExtraTests()
    467 
    468         callLst[:] = []
    469         testme.spam
    470         self.assertCallStack([('__getattr__', (testme, "spam"))])
    471 
    472         callLst[:] = []
    473         testme.eggs = "spam, spam, spam and ham"
    474         self.assertCallStack([('__setattr__', (testme, "eggs",
    475                                                "spam, spam, spam and ham"))])
    476 
    477         callLst[:] = []
    478         del testme.cardinal
    479         self.assertCallStack([('__delattr__', (testme, "cardinal"))])
    480 
    481     def testDel(self):
    482         x = []
    483 
    484         class DelTest:
    485             def __del__(self):
    486                 x.append("crab people, crab people")
    487         testme = DelTest()
    488         del testme
    489         import gc
    490         gc.collect()
    491         self.assertEqual(["crab people, crab people"], x)
    492 
    493     def testBadTypeReturned(self):
    494         # return values of some method are type-checked
    495         class BadTypeClass:
    496             def __int__(self):
    497                 return None
    498             __float__ = __int__
    499             __long__ = __int__
    500             __str__ = __int__
    501             __repr__ = __int__
    502             __oct__ = __int__
    503             __hex__ = __int__
    504 
    505         for f in [int, float, long, str, repr, oct, hex]:
    506             self.assertRaises(TypeError, f, BadTypeClass())
    507 
    508     def testMixIntsAndLongs(self):
    509         # mixing up ints and longs is okay
    510         class IntLongMixClass:
    511             @trackCall
    512             def __int__(self):
    513                 return 42L
    514 
    515             @trackCall
    516             def __long__(self):
    517                 return 64
    518 
    519         mixIntAndLong = IntLongMixClass()
    520 
    521         callLst[:] = []
    522         as_int = int(mixIntAndLong)
    523         self.assertEqual(type(as_int), long)
    524         self.assertEqual(as_int, 42L)
    525         self.assertCallStack([('__int__', (mixIntAndLong,))])
    526 
    527         callLst[:] = []
    528         as_long = long(mixIntAndLong)
    529         self.assertEqual(type(as_long), long)
    530         self.assertEqual(as_long, 64)
    531         self.assertCallStack([('__long__', (mixIntAndLong,))])
    532 
    533     def testHashStuff(self):
    534         # Test correct errors from hash() on objects with comparisons but
    535         #  no __hash__
    536 
    537         class C0:
    538             pass
    539 
    540         hash(C0()) # This should work; the next two should raise TypeError
    541 
    542         class C1:
    543             def __cmp__(self, other): return 0
    544 
    545         self.assertRaises(TypeError, hash, C1())
    546 
    547         class C2:
    548             def __eq__(self, other): return 1
    549 
    550         self.assertRaises(TypeError, hash, C2())
    551 
    552 
    553     def testSFBug532646(self):
    554         # Test for SF bug 532646
    555 
    556         class A:
    557             pass
    558         A.__call__ = A()
    559         a = A()
    560 
    561         try:
    562             a() # This should not segfault
    563         except RuntimeError:
    564             pass
    565         else:
    566             self.fail("Failed to raise RuntimeError")
    567 
    568     def testForExceptionsRaisedInInstanceGetattr2(self):
    569         # Tests for exceptions raised in instance_getattr2().
    570 
    571         def booh(self):
    572             raise AttributeError("booh")
    573 
    574         class A:
    575             a = property(booh)
    576         try:
    577             A().a # Raised AttributeError: A instance has no attribute 'a'
    578         except AttributeError, x:
    579             if str(x) != "booh":
    580                 self.fail("attribute error for A().a got masked: %s" % x)
    581 
    582         class E:
    583             __eq__ = property(booh)
    584         E() == E() # In debug mode, caused a C-level assert() to fail
    585 
    586         class I:
    587             __init__ = property(booh)
    588         try:
    589             # In debug mode, printed XXX undetected error and
    590             #  raises AttributeError
    591             I()
    592         except AttributeError, x:
    593             pass
    594         else:
    595             self.fail("attribute error for I.__init__ got masked")
    596 
    597     def testHashComparisonOfMethods(self):
    598         # Test comparison and hash of methods
    599         class A:
    600             def __init__(self, x):
    601                 self.x = x
    602             def f(self):
    603                 pass
    604             def g(self):
    605                 pass
    606             def __eq__(self, other):
    607                 return self.x == other.x
    608             def __hash__(self):
    609                 return self.x
    610         class B(A):
    611             pass
    612 
    613         a1 = A(1)
    614         a2 = A(2)
    615         self.assertEqual(a1.f, a1.f)
    616         self.assertNotEqual(a1.f, a2.f)
    617         self.assertNotEqual(a1.f, a1.g)
    618         self.assertEqual(a1.f, A(1).f)
    619         self.assertEqual(hash(a1.f), hash(a1.f))
    620         self.assertEqual(hash(a1.f), hash(A(1).f))
    621 
    622         self.assertNotEqual(A.f, a1.f)
    623         self.assertNotEqual(A.f, A.g)
    624         self.assertEqual(B.f, A.f)
    625         self.assertEqual(hash(B.f), hash(A.f))
    626 
    627         # the following triggers a SystemError in 2.4
    628         a = A(hash(A.f.im_func)^(-1))
    629         hash(a.f)
    630 
    631     def testAttrSlots(self):
    632         class C:
    633             pass
    634         for c in C, C():
    635             self.assertRaises(TypeError, type(c).__getattribute__, c, [])
    636             self.assertRaises(TypeError, type(c).__setattr__, c, [], [])
    637 
    638 def test_main():
    639     with test_support.check_py3k_warnings(
    640             (".+__(get|set|del)slice__ has been removed", DeprecationWarning),
    641             ("classic int division", DeprecationWarning),
    642             ("<> not supported", DeprecationWarning)):
    643         test_support.run_unittest(ClassTests)
    644 
    645 if __name__=='__main__':
    646     test_main()
    647