blob: 5d1fcf68a8800d4fe6ffe36a2aaf8441bcece67d [file] [log] [blame]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001from test import support, seq_tests
Zachary Wareac28b792015-12-04 23:32:23 -06002import unittest
Walter Dörwald1dde95d2003-12-08 11:38:45 +00003
Antoine Pitrou3a652b12009-03-23 18:52:06 +00004import gc
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00005import pickle
Antoine Pitrou3a652b12009-03-23 18:52:06 +00006
Walter Dörwald1dde95d2003-12-08 11:38:45 +00007class TupleTest(seq_tests.CommonTest):
8 type2test = tuple
9
Terry Jan Reedyffff1442014-08-02 01:30:37 -040010 def test_getitem_error(self):
11 msg = "tuple indices must be integers or slices"
12 with self.assertRaisesRegex(TypeError, msg):
13 ()['a']
14
Walter Dörwald1dde95d2003-12-08 11:38:45 +000015 def test_constructors(self):
Éric Araujoa63c2402010-12-23 19:13:05 +000016 super().test_constructors()
Walter Dörwald1dde95d2003-12-08 11:38:45 +000017 # calling built-in types without argument must return empty
18 self.assertEqual(tuple(), ())
Christian Heimes81ee3ef2008-05-04 22:42:01 +000019 t0_3 = (0, 1, 2, 3)
20 t0_3_bis = tuple(t0_3)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000021 self.assertTrue(t0_3 is t0_3_bis)
Christian Heimes81ee3ef2008-05-04 22:42:01 +000022 self.assertEqual(tuple([]), ())
23 self.assertEqual(tuple([0, 1, 2, 3]), (0, 1, 2, 3))
24 self.assertEqual(tuple(''), ())
25 self.assertEqual(tuple('spam'), ('s', 'p', 'a', 'm'))
Walter Dörwald1dde95d2003-12-08 11:38:45 +000026
27 def test_truth(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000028 super().test_truth()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000029 self.assertTrue(not ())
30 self.assertTrue((42, ))
Walter Dörwald1dde95d2003-12-08 11:38:45 +000031
32 def test_len(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000033 super().test_len()
Walter Dörwald1dde95d2003-12-08 11:38:45 +000034 self.assertEqual(len(()), 0)
35 self.assertEqual(len((0,)), 1)
36 self.assertEqual(len((0, 1, 2)), 3)
37
38 def test_iadd(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000039 super().test_iadd()
Walter Dörwald1dde95d2003-12-08 11:38:45 +000040 u = (0, 1)
41 u2 = u
42 u += (2, 3)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000043 self.assertTrue(u is not u2)
Walter Dörwald1dde95d2003-12-08 11:38:45 +000044
45 def test_imul(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000046 super().test_imul()
Walter Dörwald1dde95d2003-12-08 11:38:45 +000047 u = (0, 1)
48 u2 = u
49 u *= 3
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000050 self.assertTrue(u is not u2)
Walter Dörwald1dde95d2003-12-08 11:38:45 +000051
52 def test_tupleresizebug(self):
53 # Check that a specific bug in _PyTuple_Resize() is squashed.
54 def f():
55 for i in range(1000):
56 yield i
Guido van Rossum805365e2007-05-07 22:24:25 +000057 self.assertEqual(list(tuple(f())), list(range(1000)))
Walter Dörwald1dde95d2003-12-08 11:38:45 +000058
Raymond Hettinger41bd0222004-06-01 06:36:24 +000059 def test_hash(self):
60 # See SF bug 942952: Weakness in tuple hash
61 # The hash should:
62 # be non-commutative
63 # should spread-out closely spaced values
64 # should not exhibit cancellation in tuples like (x,(x,y))
65 # should be distinct from element hashes: hash(x)!=hash((x,))
66 # This test exercises those cases.
Tim Peters1f4bcf92004-06-01 18:58:04 +000067 # For a pure random hash and N=50, the expected number of occupied
68 # buckets when tossing 252,600 balls into 2**32 buckets
69 # is 252,592.6, or about 7.4 expected collisions. The
70 # standard deviation is 2.73. On a box with 64-bit hash
71 # codes, no collisions are expected. Here we accept no
72 # more than 15 collisions. Any worse and the hash function
73 # is sorely suspect.
Raymond Hettinger41bd0222004-06-01 06:36:24 +000074
75 N=50
Guido van Rossum805365e2007-05-07 22:24:25 +000076 base = list(range(N))
Raymond Hettinger41bd0222004-06-01 06:36:24 +000077 xp = [(i, j) for i in base for j in base]
78 inps = base + [(i, j) for i in base for j in xp] + \
Guido van Rossum801f0d72006-08-24 19:48:10 +000079 [(i, j) for i in xp for j in base] + xp + list(zip(base))
Raymond Hettinger41bd0222004-06-01 06:36:24 +000080 collisions = len(inps) - len(set(map(hash, inps)))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000081 self.assertTrue(collisions <= 15)
Walter Dörwald1dde95d2003-12-08 11:38:45 +000082
Raymond Hettinger5ea7e312004-09-30 07:47:20 +000083 def test_repr(self):
84 l0 = tuple()
85 l2 = (0, 1, 2)
86 a0 = self.type2test(l0)
87 a2 = self.type2test(l2)
88
89 self.assertEqual(str(a0), repr(l0))
90 self.assertEqual(str(a2), repr(l2))
91 self.assertEqual(repr(a0), "()")
92 self.assertEqual(repr(a2), "(0, 1, 2)")
93
Antoine Pitrou3a652b12009-03-23 18:52:06 +000094 def _not_tracked(self, t):
95 # Nested tuples can take several collections to untrack
96 gc.collect()
97 gc.collect()
98 self.assertFalse(gc.is_tracked(t), t)
99
100 def _tracked(self, t):
101 self.assertTrue(gc.is_tracked(t), t)
102 gc.collect()
103 gc.collect()
104 self.assertTrue(gc.is_tracked(t), t)
105
Benjamin Peterson02d78062010-06-27 22:44:51 +0000106 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000107 def test_track_literals(self):
108 # Test GC-optimization of tuple literals
109 x, y, z = 1.5, "a", []
110
111 self._not_tracked(())
112 self._not_tracked((1,))
113 self._not_tracked((1, 2))
114 self._not_tracked((1, 2, "a"))
115 self._not_tracked((1, 2, (None, True, False, ()), int))
116 self._not_tracked((object(),))
117 self._not_tracked(((1, x), y, (2, 3)))
118
119 # Tuples with mutable elements are always tracked, even if those
120 # elements are not tracked right now.
121 self._tracked(([],))
122 self._tracked(([1],))
123 self._tracked(({},))
124 self._tracked((set(),))
125 self._tracked((x, y, z))
126
127 def check_track_dynamic(self, tp, always_track):
128 x, y, z = 1.5, "a", []
129
130 check = self._tracked if always_track else self._not_tracked
131 check(tp())
132 check(tp([]))
133 check(tp(set()))
134 check(tp([1, x, y]))
135 check(tp(obj for obj in [1, x, y]))
136 check(tp(set([1, x, y])))
137 check(tp(tuple([obj]) for obj in [1, x, y]))
138 check(tuple(tp([obj]) for obj in [1, x, y]))
139
140 self._tracked(tp([z]))
141 self._tracked(tp([[x, y]]))
142 self._tracked(tp([{x: y}]))
143 self._tracked(tp(obj for obj in [x, y, z]))
144 self._tracked(tp(tuple([obj]) for obj in [x, y, z]))
145 self._tracked(tuple(tp([obj]) for obj in [x, y, z]))
146
Benjamin Peterson02d78062010-06-27 22:44:51 +0000147 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000148 def test_track_dynamic(self):
149 # Test GC-optimization of dynamically constructed tuples.
150 self.check_track_dynamic(tuple, False)
151
Benjamin Peterson02d78062010-06-27 22:44:51 +0000152 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000153 def test_track_subtypes(self):
154 # Tuple subtypes must always be tracked
155 class MyTuple(tuple):
156 pass
157 self.check_track_dynamic(MyTuple, True)
158
Benjamin Peterson02d78062010-06-27 22:44:51 +0000159 @support.cpython_only
Antoine Pitrou6b7dfc92009-12-12 19:18:27 +0000160 def test_bug7466(self):
161 # Trying to untrack an unfinished tuple could crash Python
162 self._not_tracked(tuple(gc.collect() for i in range(101)))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000163
Antoine Pitroueeb7eea2011-10-06 18:57:27 +0200164 def test_repr_large(self):
165 # Check the repr of large list objects
166 def check(n):
167 l = (0,) * n
168 s = repr(l)
169 self.assertEqual(s,
170 '(' + ', '.join(['0'] * n) + ')')
171 check(10) # check our checking code
172 check(1000000)
173
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000174 def test_iterator_pickle(self):
175 # Userlist iterators don't support pickling yet since
176 # they are based on generators.
177 data = self.type2test([4, 5, 6, 7])
Serhiy Storchakabad12572014-12-15 14:03:42 +0200178 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
179 itorg = iter(data)
180 d = pickle.dumps(itorg, proto)
181 it = pickle.loads(d)
182 self.assertEqual(type(itorg), type(it))
183 self.assertEqual(self.type2test(it), self.type2test(data))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000184
Serhiy Storchakabad12572014-12-15 14:03:42 +0200185 it = pickle.loads(d)
186 next(it)
187 d = pickle.dumps(it, proto)
188 self.assertEqual(self.type2test(it), self.type2test(data)[1:])
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000189
190 def test_reversed_pickle(self):
191 data = self.type2test([4, 5, 6, 7])
Serhiy Storchakabad12572014-12-15 14:03:42 +0200192 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
193 itorg = reversed(data)
194 d = pickle.dumps(itorg, proto)
195 it = pickle.loads(d)
196 self.assertEqual(type(itorg), type(it))
197 self.assertEqual(self.type2test(it), self.type2test(reversed(data)))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000198
Serhiy Storchakabad12572014-12-15 14:03:42 +0200199 it = pickle.loads(d)
200 next(it)
201 d = pickle.dumps(it, proto)
202 self.assertEqual(self.type2test(it), self.type2test(reversed(data))[1:])
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000203
Martin v. Löwis4c1730d2012-08-01 10:32:11 +0200204 def test_no_comdat_folding(self):
205 # Issue 8847: In the PGO build, the MSVC linker's COMDAT folding
206 # optimization causes failures in code that relies on distinct
207 # function addresses.
208 class T(tuple): pass
209 with self.assertRaises(TypeError):
210 [3,] + T((1,2))
211
Raymond Hettingere5bb5512014-03-30 10:12:09 -0700212 def test_lexicographic_ordering(self):
213 # Issue 21100
214 a = self.type2test([1, 2])
215 b = self.type2test([1, 2, 0])
216 c = self.type2test([1, 3])
217 self.assertLess(a, b)
218 self.assertLess(b, c)
219
Zachary Ware38c707e2015-04-13 15:00:43 -0500220if __name__ == "__main__":
221 unittest.main()