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     def testUnaryOps(self):
    354         testme = AllTests()
    355 
    356         callLst[:] = []
    357         -testme
    358         self.assertCallStack([('__neg__', (testme,))])
    359         callLst[:] = []
    360         +testme
    361         self.assertCallStack([('__pos__', (testme,))])
    362         callLst[:] = []
    363         abs(testme)
    364         self.assertCallStack([('__abs__', (testme,))])
    365         callLst[:] = []
    366         int(testme)
    367         self.assertCallStack([('__int__', (testme,))])
    368         callLst[:] = []
    369         long(testme)
    370         self.assertCallStack([('__long__', (testme,))])
    371         callLst[:] = []
    372         float(testme)
    373         self.assertCallStack([('__float__', (testme,))])
    374         callLst[:] = []
    375         oct(testme)
    376         self.assertCallStack([('__oct__', (testme,))])
    377         callLst[:] = []
    378         hex(testme)
    379         self.assertCallStack([('__hex__', (testme,))])
    380 
    381 
    382     def testMisc(self):
    383         testme = AllTests()
    384 
    385         callLst[:] = []
    386         hash(testme)
    387         self.assertCallStack([('__hash__', (testme,))])
    388 
    389         callLst[:] = []
    390         repr(testme)
    391         self.assertCallStack([('__repr__', (testme,))])
    392 
    393         callLst[:] = []
    394         str(testme)
    395         self.assertCallStack([('__str__', (testme,))])
    396 
    397         callLst[:] = []
    398         testme == 1
    399         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    400 
    401         callLst[:] = []
    402         testme < 1
    403         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    404 
    405         callLst[:] = []
    406         testme > 1
    407         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    408 
    409         callLst[:] = []
    410         eval('testme <> 1')  # XXX kill this in py3k

    411         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    412 
    413         callLst[:] = []
    414         testme != 1
    415         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
    416 
    417         callLst[:] = []
    418         1 == testme
    419         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    420 
    421         callLst[:] = []
    422         1 < testme
    423         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    424 
    425         callLst[:] = []
    426         1 > testme
    427         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    428 
    429         callLst[:] = []
    430         eval('1 <> testme')
    431         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    432 
    433         callLst[:] = []
    434         1 != testme
    435         self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
    436 
    437 
    438     def testGetSetAndDel(self):
    439         # Interfering tests

    440         class ExtraTests(AllTests):
    441             @trackCall
    442             def __getattr__(self, *args):
    443                 return "SomeVal"
    444 
    445             @trackCall
    446             def __setattr__(self, *args):
    447                 pass
    448 
    449             @trackCall
    450             def __delattr__(self, *args):
    451                 pass
    452 
    453         testme = ExtraTests()
    454 
    455         callLst[:] = []
    456         testme.spam
    457         self.assertCallStack([('__getattr__', (testme, "spam"))])
    458 
    459         callLst[:] = []
    460         testme.eggs = "spam, spam, spam and ham"
    461         self.assertCallStack([('__setattr__', (testme, "eggs",
    462                                                "spam, spam, spam and ham"))])
    463 
    464         callLst[:] = []
    465         del testme.cardinal
    466         self.assertCallStack([('__delattr__', (testme, "cardinal"))])
    467 
    468     def testDel(self):
    469         x = []
    470 
    471         class DelTest:
    472             def __del__(self):
    473                 x.append("crab people, crab people")
    474         testme = DelTest()
    475         del testme
    476         import gc
    477         gc.collect()
    478         self.assertEqual(["crab people, crab people"], x)
    479 
    480     def testBadTypeReturned(self):
    481         # return values of some method are type-checked

    482         class BadTypeClass:
    483             def __int__(self):
    484                 return None
    485             __float__ = __int__
    486             __long__ = __int__
    487             __str__ = __int__
    488             __repr__ = __int__
    489             __oct__ = __int__
    490             __hex__ = __int__
    491 
    492         for f in [int, float, long, str, repr, oct, hex]:
    493             self.assertRaises(TypeError, f, BadTypeClass())
    494 
    495     def testMixIntsAndLongs(self):
    496         # mixing up ints and longs is okay

    497         class IntLongMixClass:
    498             @trackCall
    499             def __int__(self):
    500                 return 42L
    501 
    502             @trackCall
    503             def __long__(self):
    504                 return 64
    505 
    506         mixIntAndLong = IntLongMixClass()
    507 
    508         callLst[:] = []
    509         as_int = int(mixIntAndLong)
    510         self.assertEqual(type(as_int), long)
    511         self.assertEqual(as_int, 42L)
    512         self.assertCallStack([('__int__', (mixIntAndLong,))])
    513 
    514         callLst[:] = []
    515         as_long = long(mixIntAndLong)
    516         self.assertEqual(type(as_long), long)
    517         self.assertEqual(as_long, 64)
    518         self.assertCallStack([('__long__', (mixIntAndLong,))])
    519 
    520     def testHashStuff(self):
    521         # Test correct errors from hash() on objects with comparisons but

    522         #  no __hash__

    523 
    524         class C0:
    525             pass
    526 
    527         hash(C0()) # This should work; the next two should raise TypeError

    528 
    529         class C1:
    530             def __cmp__(self, other): return 0
    531 
    532         self.assertRaises(TypeError, hash, C1())
    533 
    534         class C2:
    535             def __eq__(self, other): return 1
    536 
    537         self.assertRaises(TypeError, hash, C2())
    538 
    539 
    540     def testSFBug532646(self):
    541         # Test for SF bug 532646

    542 
    543         class A:
    544             pass
    545         A.__call__ = A()
    546         a = A()
    547 
    548         try:
    549             a() # This should not segfault

    550         except RuntimeError:
    551             pass
    552         else:
    553             self.fail("Failed to raise RuntimeError")
    554 
    555     def testForExceptionsRaisedInInstanceGetattr2(self):
    556         # Tests for exceptions raised in instance_getattr2().

    557 
    558         def booh(self):
    559             raise AttributeError("booh")
    560 
    561         class A:
    562             a = property(booh)
    563         try:
    564             A().a # Raised AttributeError: A instance has no attribute 'a'

    565         except AttributeError, x:
    566             if str(x) != "booh":
    567                 self.fail("attribute error for A().a got masked: %s" % x)
    568 
    569         class E:
    570             __eq__ = property(booh)
    571         E() == E() # In debug mode, caused a C-level assert() to fail

    572 
    573         class I:
    574             __init__ = property(booh)
    575         try:
    576             # In debug mode, printed XXX undetected error and

    577             #  raises AttributeError

    578             I()
    579         except AttributeError, x:
    580             pass
    581         else:
    582             self.fail("attribute error for I.__init__ got masked")
    583 
    584     def testHashComparisonOfMethods(self):
    585         # Test comparison and hash of methods

    586         class A:
    587             def __init__(self, x):
    588                 self.x = x
    589             def f(self):
    590                 pass
    591             def g(self):
    592                 pass
    593             def __eq__(self, other):
    594                 return self.x == other.x
    595             def __hash__(self):
    596                 return self.x
    597         class B(A):
    598             pass
    599 
    600         a1 = A(1)
    601         a2 = A(2)
    602         self.assertEqual(a1.f, a1.f)
    603         self.assertNotEqual(a1.f, a2.f)
    604         self.assertNotEqual(a1.f, a1.g)
    605         self.assertEqual(a1.f, A(1).f)
    606         self.assertEqual(hash(a1.f), hash(a1.f))
    607         self.assertEqual(hash(a1.f), hash(A(1).f))
    608 
    609         self.assertNotEqual(A.f, a1.f)
    610         self.assertNotEqual(A.f, A.g)
    611         self.assertEqual(B.f, A.f)
    612         self.assertEqual(hash(B.f), hash(A.f))
    613 
    614         # the following triggers a SystemError in 2.4

    615         a = A(hash(A.f.im_func)^(-1))
    616         hash(a.f)
    617 
    618 def test_main():
    619     with test_support.check_py3k_warnings(
    620             (".+__(get|set|del)slice__ has been removed", DeprecationWarning),
    621             ("classic int division", DeprecationWarning),
    622             ("<> not supported", DeprecationWarning)):
    623         test_support.run_unittest(ClassTests)
    624 
    625 if __name__=='__main__':
    626     test_main()
    627