]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | # test the invariant that\r |
2 | # iff a==b then hash(a)==hash(b)\r | |
3 | #\r | |
4 | # Also test that hash implementations are inherited as expected\r | |
5 | \r | |
6 | import unittest\r | |
7 | from test import test_support\r | |
8 | from collections import Hashable\r | |
9 | \r | |
10 | \r | |
11 | class HashEqualityTestCase(unittest.TestCase):\r | |
12 | \r | |
13 | def same_hash(self, *objlist):\r | |
14 | # Hash each object given and fail if\r | |
15 | # the hash values are not all the same.\r | |
16 | hashed = map(hash, objlist)\r | |
17 | for h in hashed[1:]:\r | |
18 | if h != hashed[0]:\r | |
19 | self.fail("hashed values differ: %r" % (objlist,))\r | |
20 | \r | |
21 | def test_numeric_literals(self):\r | |
22 | self.same_hash(1, 1L, 1.0, 1.0+0.0j)\r | |
23 | self.same_hash(0, 0L, 0.0, 0.0+0.0j)\r | |
24 | self.same_hash(-1, -1L, -1.0, -1.0+0.0j)\r | |
25 | self.same_hash(-2, -2L, -2.0, -2.0+0.0j)\r | |
26 | \r | |
27 | def test_coerced_integers(self):\r | |
28 | self.same_hash(int(1), long(1), float(1), complex(1),\r | |
29 | int('1'), float('1.0'))\r | |
30 | self.same_hash(int(-2**31), long(-2**31), float(-2**31))\r | |
31 | self.same_hash(int(1-2**31), long(1-2**31), float(1-2**31))\r | |
32 | self.same_hash(int(2**31-1), long(2**31-1), float(2**31-1))\r | |
33 | # for 64-bit platforms\r | |
34 | self.same_hash(int(2**31), long(2**31), float(2**31))\r | |
35 | self.same_hash(int(-2**63), long(-2**63), float(-2**63))\r | |
36 | self.same_hash(int(1-2**63), long(1-2**63))\r | |
37 | self.same_hash(int(2**63-1), long(2**63-1))\r | |
38 | self.same_hash(long(2**63), float(2**63))\r | |
39 | \r | |
40 | def test_coerced_floats(self):\r | |
41 | self.same_hash(long(1.23e300), float(1.23e300))\r | |
42 | self.same_hash(float(0.5), complex(0.5, 0.0))\r | |
43 | \r | |
44 | \r | |
45 | _default_hash = object.__hash__\r | |
46 | class DefaultHash(object): pass\r | |
47 | \r | |
48 | _FIXED_HASH_VALUE = 42\r | |
49 | class FixedHash(object):\r | |
50 | def __hash__(self):\r | |
51 | return _FIXED_HASH_VALUE\r | |
52 | \r | |
53 | class OnlyEquality(object):\r | |
54 | def __eq__(self, other):\r | |
55 | return self is other\r | |
56 | # Trick to suppress Py3k warning in 2.x\r | |
57 | __hash__ = None\r | |
58 | del OnlyEquality.__hash__\r | |
59 | \r | |
60 | class OnlyInequality(object):\r | |
61 | def __ne__(self, other):\r | |
62 | return self is not other\r | |
63 | \r | |
64 | class OnlyCmp(object):\r | |
65 | def __cmp__(self, other):\r | |
66 | return cmp(id(self), id(other))\r | |
67 | # Trick to suppress Py3k warning in 2.x\r | |
68 | __hash__ = None\r | |
69 | del OnlyCmp.__hash__\r | |
70 | \r | |
71 | class InheritedHashWithEquality(FixedHash, OnlyEquality): pass\r | |
72 | class InheritedHashWithInequality(FixedHash, OnlyInequality): pass\r | |
73 | class InheritedHashWithCmp(FixedHash, OnlyCmp): pass\r | |
74 | \r | |
75 | class NoHash(object):\r | |
76 | __hash__ = None\r | |
77 | \r | |
78 | class HashInheritanceTestCase(unittest.TestCase):\r | |
79 | default_expected = [object(),\r | |
80 | DefaultHash(),\r | |
81 | OnlyEquality(),\r | |
82 | OnlyInequality(),\r | |
83 | OnlyCmp(),\r | |
84 | ]\r | |
85 | fixed_expected = [FixedHash(),\r | |
86 | InheritedHashWithEquality(),\r | |
87 | InheritedHashWithInequality(),\r | |
88 | InheritedHashWithCmp(),\r | |
89 | ]\r | |
90 | error_expected = [NoHash()]\r | |
91 | \r | |
92 | def test_default_hash(self):\r | |
93 | for obj in self.default_expected:\r | |
94 | self.assertEqual(hash(obj), _default_hash(obj))\r | |
95 | \r | |
96 | def test_fixed_hash(self):\r | |
97 | for obj in self.fixed_expected:\r | |
98 | self.assertEqual(hash(obj), _FIXED_HASH_VALUE)\r | |
99 | \r | |
100 | def test_error_hash(self):\r | |
101 | for obj in self.error_expected:\r | |
102 | self.assertRaises(TypeError, hash, obj)\r | |
103 | \r | |
104 | def test_hashable(self):\r | |
105 | objects = (self.default_expected +\r | |
106 | self.fixed_expected)\r | |
107 | for obj in objects:\r | |
108 | self.assertIsInstance(obj, Hashable)\r | |
109 | \r | |
110 | def test_not_hashable(self):\r | |
111 | for obj in self.error_expected:\r | |
112 | self.assertNotIsInstance(obj, Hashable)\r | |
113 | \r | |
114 | \r | |
115 | # Issue #4701: Check that some builtin types are correctly hashable\r | |
116 | # (This test only used to fail in Python 3.0, but has been included\r | |
117 | # in 2.x along with the lazy call to PyType_Ready in PyObject_Hash)\r | |
118 | class DefaultIterSeq(object):\r | |
119 | seq = range(10)\r | |
120 | def __len__(self):\r | |
121 | return len(self.seq)\r | |
122 | def __getitem__(self, index):\r | |
123 | return self.seq[index]\r | |
124 | \r | |
125 | class HashBuiltinsTestCase(unittest.TestCase):\r | |
126 | hashes_to_check = [xrange(10),\r | |
127 | enumerate(xrange(10)),\r | |
128 | iter(DefaultIterSeq()),\r | |
129 | iter(lambda: 0, 0),\r | |
130 | ]\r | |
131 | \r | |
132 | def test_hashes(self):\r | |
133 | _default_hash = object.__hash__\r | |
134 | for obj in self.hashes_to_check:\r | |
135 | self.assertEqual(hash(obj), _default_hash(obj))\r | |
136 | \r | |
137 | def test_main():\r | |
138 | test_support.run_unittest(HashEqualityTestCase,\r | |
139 | HashInheritanceTestCase,\r | |
140 | HashBuiltinsTestCase)\r | |
141 | \r | |
142 | \r | |
143 | if __name__ == "__main__":\r | |
144 | test_main()\r |