|
1 # test the invariant that |
|
2 # iff a==b then hash(a)==hash(b) |
|
3 # |
|
4 # Also test that hash implementations are inherited as expected |
|
5 |
|
6 import unittest |
|
7 from test import test_support |
|
8 from collections import Hashable |
|
9 |
|
10 |
|
11 class HashEqualityTestCase(unittest.TestCase): |
|
12 |
|
13 def same_hash(self, *objlist): |
|
14 # Hash each object given and fail if |
|
15 # the hash values are not all the same. |
|
16 hashed = map(hash, objlist) |
|
17 for h in hashed[1:]: |
|
18 if h != hashed[0]: |
|
19 self.fail("hashed values differ: %r" % (objlist,)) |
|
20 |
|
21 def test_numeric_literals(self): |
|
22 self.same_hash(1, 1L, 1.0, 1.0+0.0j) |
|
23 self.same_hash(0, 0L, 0.0, 0.0+0.0j) |
|
24 self.same_hash(-1, -1L, -1.0, -1.0+0.0j) |
|
25 self.same_hash(-2, -2L, -2.0, -2.0+0.0j) |
|
26 |
|
27 def test_coerced_integers(self): |
|
28 self.same_hash(int(1), long(1), float(1), complex(1), |
|
29 int('1'), float('1.0')) |
|
30 self.same_hash(int(-2**31), long(-2**31), float(-2**31)) |
|
31 self.same_hash(int(1-2**31), long(1-2**31), float(1-2**31)) |
|
32 self.same_hash(int(2**31-1), long(2**31-1), float(2**31-1)) |
|
33 # for 64-bit platforms |
|
34 self.same_hash(int(2**31), long(2**31), float(2**31)) |
|
35 self.same_hash(int(-2**63), long(-2**63), float(-2**63)) |
|
36 self.same_hash(int(1-2**63), long(1-2**63)) |
|
37 self.same_hash(int(2**63-1), long(2**63-1)) |
|
38 |
|
39 def test_coerced_floats(self): |
|
40 self.same_hash(long(1.23e300), float(1.23e300)) |
|
41 self.same_hash(float(0.5), complex(0.5, 0.0)) |
|
42 |
|
43 |
|
44 _default_hash = object.__hash__ |
|
45 class DefaultHash(object): pass |
|
46 |
|
47 _FIXED_HASH_VALUE = 42 |
|
48 class FixedHash(object): |
|
49 def __hash__(self): |
|
50 return _FIXED_HASH_VALUE |
|
51 |
|
52 class OnlyEquality(object): |
|
53 def __eq__(self, other): |
|
54 return self is other |
|
55 # Trick to suppress Py3k warning in 2.x |
|
56 __hash__ = None |
|
57 del OnlyEquality.__hash__ |
|
58 |
|
59 class OnlyInequality(object): |
|
60 def __ne__(self, other): |
|
61 return self is not other |
|
62 |
|
63 class OnlyCmp(object): |
|
64 def __cmp__(self, other): |
|
65 return cmp(id(self), id(other)) |
|
66 # Trick to suppress Py3k warning in 2.x |
|
67 __hash__ = None |
|
68 del OnlyCmp.__hash__ |
|
69 |
|
70 class InheritedHashWithEquality(FixedHash, OnlyEquality): pass |
|
71 class InheritedHashWithInequality(FixedHash, OnlyInequality): pass |
|
72 class InheritedHashWithCmp(FixedHash, OnlyCmp): pass |
|
73 |
|
74 class NoHash(object): |
|
75 __hash__ = None |
|
76 |
|
77 class HashInheritanceTestCase(unittest.TestCase): |
|
78 default_expected = [object(), |
|
79 DefaultHash(), |
|
80 OnlyEquality(), |
|
81 OnlyInequality(), |
|
82 OnlyCmp(), |
|
83 ] |
|
84 fixed_expected = [FixedHash(), |
|
85 InheritedHashWithEquality(), |
|
86 InheritedHashWithInequality(), |
|
87 InheritedHashWithCmp(), |
|
88 ] |
|
89 error_expected = [NoHash()] |
|
90 |
|
91 def test_default_hash(self): |
|
92 for obj in self.default_expected: |
|
93 self.assertEqual(hash(obj), _default_hash(obj)) |
|
94 |
|
95 def test_fixed_hash(self): |
|
96 for obj in self.fixed_expected: |
|
97 self.assertEqual(hash(obj), _FIXED_HASH_VALUE) |
|
98 |
|
99 def test_error_hash(self): |
|
100 for obj in self.error_expected: |
|
101 self.assertRaises(TypeError, hash, obj) |
|
102 |
|
103 def test_hashable(self): |
|
104 objects = (self.default_expected + |
|
105 self.fixed_expected) |
|
106 for obj in objects: |
|
107 self.assert_(isinstance(obj, Hashable), repr(obj)) |
|
108 |
|
109 def test_not_hashable(self): |
|
110 for obj in self.error_expected: |
|
111 self.assertFalse(isinstance(obj, Hashable), repr(obj)) |
|
112 |
|
113 |
|
114 def test_main(): |
|
115 test_support.run_unittest(HashEqualityTestCase, |
|
116 HashInheritanceTestCase) |
|
117 |
|
118 |
|
119 if __name__ == "__main__": |
|
120 test_main() |