1"""
2Common tests shared by test_str, test_unicode, test_userstring and test_string.
3"""
4
5import unittest, string, sys, struct
6from test import test_support
7from UserList import UserList
8import _testcapi
9
10class Sequence:
11    def __init__(self, seq='wxyz'): self.seq = seq
12    def __len__(self): return len(self.seq)
13    def __getitem__(self, i): return self.seq[i]
14
15class BadSeq1(Sequence):
16    def __init__(self): self.seq = [7, 'hello', 123L]
17
18class BadSeq2(Sequence):
19    def __init__(self): self.seq = ['a', 'b', 'c']
20    def __len__(self): return 8
21
22class CommonTest(unittest.TestCase):
23    # This testcase contains test that can be used in all
24    # stringlike classes. Currently this is str, unicode
25    # UserString and the string module.
26
27    # The type to be tested
28    # Change in subclasses to change the behaviour of fixtesttype()
29    type2test = None
30
31    # All tests pass their arguments to the testing methods
32    # as str objects. fixtesttype() can be used to propagate
33    # these arguments to the appropriate type
34    def fixtype(self, obj):
35        if isinstance(obj, str):
36            return self.__class__.type2test(obj)
37        elif isinstance(obj, list):
38            return [self.fixtype(x) for x in obj]
39        elif isinstance(obj, tuple):
40            return tuple([self.fixtype(x) for x in obj])
41        elif isinstance(obj, dict):
42            return dict([
43               (self.fixtype(key), self.fixtype(value))
44               for (key, value) in obj.iteritems()
45            ])
46        else:
47            return obj
48
49    # check that object.method(*args) returns result
50    def checkequal(self, result, object, methodname, *args):
51        result = self.fixtype(result)
52        object = self.fixtype(object)
53        args = self.fixtype(args)
54        realresult = getattr(object, methodname)(*args)
55        self.assertEqual(
56            result,
57            realresult
58        )
59        # if the original is returned make sure that
60        # this doesn't happen with subclasses
61        if object == realresult:
62            class subtype(self.__class__.type2test):
63                pass
64            object = subtype(object)
65            realresult = getattr(object, methodname)(*args)
66            self.assertTrue(object is not realresult)
67
68    # check that object.method(*args) raises exc
69    def checkraises(self, exc, object, methodname, *args):
70        object = self.fixtype(object)
71        args = self.fixtype(args)
72        self.assertRaises(
73            exc,
74            getattr(object, methodname),
75            *args
76        )
77
78    # call object.method(*args) without any checks
79    def checkcall(self, object, methodname, *args):
80        object = self.fixtype(object)
81        args = self.fixtype(args)
82        getattr(object, methodname)(*args)
83
84    def test_hash(self):
85        # SF bug 1054139:  += optimization was not invalidating cached hash value
86        a = self.type2test('DNSSEC')
87        b = self.type2test('')
88        for c in a:
89            b += c
90            hash(b)
91        self.assertEqual(hash(a), hash(b))
92
93    def test_capitalize(self):
94        self.checkequal(' hello ', ' hello ', 'capitalize')
95        self.checkequal('Hello ', 'Hello ','capitalize')
96        self.checkequal('Hello ', 'hello ','capitalize')
97        self.checkequal('Aaaa', 'aaaa', 'capitalize')
98        self.checkequal('Aaaa', 'AaAa', 'capitalize')
99
100        self.checkraises(TypeError, 'hello', 'capitalize', 42)
101
102    def test_count(self):
103        self.checkequal(3, 'aaa', 'count', 'a')
104        self.checkequal(0, 'aaa', 'count', 'b')
105        self.checkequal(3, 'aaa', 'count', 'a')
106        self.checkequal(0, 'aaa', 'count', 'b')
107        self.checkequal(3, 'aaa', 'count', 'a')
108        self.checkequal(0, 'aaa', 'count', 'b')
109        self.checkequal(0, 'aaa', 'count', 'b')
110        self.checkequal(2, 'aaa', 'count', 'a', 1)
111        self.checkequal(0, 'aaa', 'count', 'a', 10)
112        self.checkequal(1, 'aaa', 'count', 'a', -1)
113        self.checkequal(3, 'aaa', 'count', 'a', -10)
114        self.checkequal(1, 'aaa', 'count', 'a', 0, 1)
115        self.checkequal(3, 'aaa', 'count', 'a', 0, 10)
116        self.checkequal(2, 'aaa', 'count', 'a', 0, -1)
117        self.checkequal(0, 'aaa', 'count', 'a', 0, -10)
118        self.checkequal(3, 'aaa', 'count', '', 1)
119        self.checkequal(1, 'aaa', 'count', '', 3)
120        self.checkequal(0, 'aaa', 'count', '', 10)
121        self.checkequal(2, 'aaa', 'count', '', -1)
122        self.checkequal(4, 'aaa', 'count', '', -10)
123
124        self.checkequal(1, '', 'count', '')
125        self.checkequal(0, '', 'count', '', 1, 1)
126        self.checkequal(0, '', 'count', '', sys.maxint, 0)
127
128        self.checkequal(0, '', 'count', 'xx')
129        self.checkequal(0, '', 'count', 'xx', 1, 1)
130        self.checkequal(0, '', 'count', 'xx', sys.maxint, 0)
131
132        self.checkraises(TypeError, 'hello', 'count')
133        self.checkraises(TypeError, 'hello', 'count', 42)
134
135        # For a variety of combinations,
136        #    verify that str.count() matches an equivalent function
137        #    replacing all occurrences and then differencing the string lengths
138        charset = ['', 'a', 'b']
139        digits = 7
140        base = len(charset)
141        teststrings = set()
142        for i in xrange(base ** digits):
143            entry = []
144            for j in xrange(digits):
145                i, m = divmod(i, base)
146                entry.append(charset[m])
147            teststrings.add(''.join(entry))
148        teststrings = list(teststrings)
149        for i in teststrings:
150            i = self.fixtype(i)
151            n = len(i)
152            for j in teststrings:
153                r1 = i.count(j)
154                if j:
155                    r2, rem = divmod(n - len(i.replace(j, '')), len(j))
156                else:
157                    r2, rem = len(i)+1, 0
158                if rem or r1 != r2:
159                    self.assertEqual(rem, 0, '%s != 0 for %s' % (rem, i))
160                    self.assertEqual(r1, r2, '%s != %s for %s' % (r1, r2, i))
161
162    def test_find(self):
163        self.checkequal(0, 'abcdefghiabc', 'find', 'abc')
164        self.checkequal(9, 'abcdefghiabc', 'find', 'abc', 1)
165        self.checkequal(-1, 'abcdefghiabc', 'find', 'def', 4)
166
167        self.checkequal(0, 'abc', 'find', '', 0)
168        self.checkequal(3, 'abc', 'find', '', 3)
169        self.checkequal(-1, 'abc', 'find', '', 4)
170
171        # to check the ability to pass None as defaults
172        self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a')
173        self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4)
174        self.checkequal(-1, 'rrarrrrrrrrra', 'find', 'a', 4, 6)
175        self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4, None)
176        self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a', None, 6)
177
178        self.checkraises(TypeError, 'hello', 'find')
179        self.checkraises(TypeError, 'hello', 'find', 42)
180
181        self.checkequal(0, '', 'find', '')
182        self.checkequal(-1, '', 'find', '', 1, 1)
183        self.checkequal(-1, '', 'find', '', sys.maxint, 0)
184
185        self.checkequal(-1, '', 'find', 'xx')
186        self.checkequal(-1, '', 'find', 'xx', 1, 1)
187        self.checkequal(-1, '', 'find', 'xx', sys.maxint, 0)
188
189        # issue 7458
190        self.checkequal(-1, 'ab', 'find', 'xxx', sys.maxsize + 1, 0)
191
192        # For a variety of combinations,
193        #    verify that str.find() matches __contains__
194        #    and that the found substring is really at that location
195        charset = ['', 'a', 'b', 'c']
196        digits = 5
197        base = len(charset)
198        teststrings = set()
199        for i in xrange(base ** digits):
200            entry = []
201            for j in xrange(digits):
202                i, m = divmod(i, base)
203                entry.append(charset[m])
204            teststrings.add(''.join(entry))
205        teststrings = list(teststrings)
206        for i in teststrings:
207            i = self.fixtype(i)
208            for j in teststrings:
209                loc = i.find(j)
210                r1 = (loc != -1)
211                r2 = j in i
212                self.assertEqual(r1, r2)
213                if loc != -1:
214                    self.assertEqual(i[loc:loc+len(j)], j)
215
216    def test_rfind(self):
217        self.checkequal(9,  'abcdefghiabc', 'rfind', 'abc')
218        self.checkequal(12, 'abcdefghiabc', 'rfind', '')
219        self.checkequal(0, 'abcdefghiabc', 'rfind', 'abcd')
220        self.checkequal(-1, 'abcdefghiabc', 'rfind', 'abcz')
221
222        self.checkequal(3, 'abc', 'rfind', '', 0)
223        self.checkequal(3, 'abc', 'rfind', '', 3)
224        self.checkequal(-1, 'abc', 'rfind', '', 4)
225
226        # to check the ability to pass None as defaults
227        self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a')
228        self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4)
229        self.checkequal(-1, 'rrarrrrrrrrra', 'rfind', 'a', 4, 6)
230        self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4, None)
231        self.checkequal( 2, 'rrarrrrrrrrra', 'rfind', 'a', None, 6)
232
233        self.checkraises(TypeError, 'hello', 'rfind')
234        self.checkraises(TypeError, 'hello', 'rfind', 42)
235
236        # For a variety of combinations,
237        #    verify that str.rfind() matches __contains__
238        #    and that the found substring is really at that location
239        charset = ['', 'a', 'b', 'c']
240        digits = 5
241        base = len(charset)
242        teststrings = set()
243        for i in xrange(base ** digits):
244            entry = []
245            for j in xrange(digits):
246                i, m = divmod(i, base)
247                entry.append(charset[m])
248            teststrings.add(''.join(entry))
249        teststrings = list(teststrings)
250        for i in teststrings:
251            i = self.fixtype(i)
252            for j in teststrings:
253                loc = i.rfind(j)
254                r1 = (loc != -1)
255                r2 = j in i
256                self.assertEqual(r1, r2)
257                if loc != -1:
258                    self.assertEqual(i[loc:loc+len(j)], self.fixtype(j))
259
260        # issue 7458
261        self.checkequal(-1, 'ab', 'rfind', 'xxx', sys.maxsize + 1, 0)
262
263    def test_index(self):
264        self.checkequal(0, 'abcdefghiabc', 'index', '')
265        self.checkequal(3, 'abcdefghiabc', 'index', 'def')
266        self.checkequal(0, 'abcdefghiabc', 'index', 'abc')
267        self.checkequal(9, 'abcdefghiabc', 'index', 'abc', 1)
268
269        self.checkraises(ValueError, 'abcdefghiabc', 'index', 'hib')
270        self.checkraises(ValueError, 'abcdefghiab', 'index', 'abc', 1)
271        self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', 8)
272        self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', -1)
273
274        # to check the ability to pass None as defaults
275        self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a')
276        self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4)
277        self.checkraises(ValueError, 'rrarrrrrrrrra', 'index', 'a', 4, 6)
278        self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4, None)
279        self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a', None, 6)
280
281        self.checkraises(TypeError, 'hello', 'index')
282        self.checkraises(TypeError, 'hello', 'index', 42)
283
284    def test_rindex(self):
285        self.checkequal(12, 'abcdefghiabc', 'rindex', '')
286        self.checkequal(3,  'abcdefghiabc', 'rindex', 'def')
287        self.checkequal(9,  'abcdefghiabc', 'rindex', 'abc')
288        self.checkequal(0,  'abcdefghiabc', 'rindex', 'abc', 0, -1)
289
290        self.checkraises(ValueError, 'abcdefghiabc', 'rindex', 'hib')
291        self.checkraises(ValueError, 'defghiabc', 'rindex', 'def', 1)
292        self.checkraises(ValueError, 'defghiabc', 'rindex', 'abc', 0, -1)
293        self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, 8)
294        self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, -1)
295
296        # to check the ability to pass None as defaults
297        self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a')
298        self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4)
299        self.checkraises(ValueError, 'rrarrrrrrrrra', 'rindex', 'a', 4, 6)
300        self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4, None)
301        self.checkequal( 2, 'rrarrrrrrrrra', 'rindex', 'a', None, 6)
302
303        self.checkraises(TypeError, 'hello', 'rindex')
304        self.checkraises(TypeError, 'hello', 'rindex', 42)
305
306    def test_lower(self):
307        self.checkequal('hello', 'HeLLo', 'lower')
308        self.checkequal('hello', 'hello', 'lower')
309        self.checkraises(TypeError, 'hello', 'lower', 42)
310
311    def test_upper(self):
312        self.checkequal('HELLO', 'HeLLo', 'upper')
313        self.checkequal('HELLO', 'HELLO', 'upper')
314        self.checkraises(TypeError, 'hello', 'upper', 42)
315
316    def test_expandtabs(self):
317        self.checkequal('abc\rab      def\ng       hi', 'abc\rab\tdef\ng\thi', 'expandtabs')
318        self.checkequal('abc\rab      def\ng       hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 8)
319        self.checkequal('abc\rab  def\ng   hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 4)
320        self.checkequal('abc\r\nab  def\ng   hi', 'abc\r\nab\tdef\ng\thi', 'expandtabs', 4)
321        self.checkequal('abc\rab      def\ng       hi', 'abc\rab\tdef\ng\thi', 'expandtabs')
322        self.checkequal('abc\rab      def\ng       hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 8)
323        self.checkequal('abc\r\nab\r\ndef\ng\r\nhi', 'abc\r\nab\r\ndef\ng\r\nhi', 'expandtabs', 4)
324        self.checkequal('  a\n b', ' \ta\n\tb', 'expandtabs', 1)
325
326        self.checkraises(TypeError, 'hello', 'expandtabs', 42, 42)
327        # This test is only valid when sizeof(int) == sizeof(void*) == 4.
328        if sys.maxint < (1 << 32) and struct.calcsize('P') == 4:
329            self.checkraises(OverflowError,
330                             '\ta\n\tb', 'expandtabs', sys.maxint)
331
332    def test_split(self):
333        self.checkequal(['this', 'is', 'the', 'split', 'function'],
334            'this is the split function', 'split')
335
336        # by whitespace
337        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'split')
338        self.checkequal(['a', 'b c d'], 'a b c d', 'split', None, 1)
339        self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', None, 2)
340        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 3)
341        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 4)
342        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None,
343                        sys.maxint-1)
344        self.checkequal(['a b c d'], 'a b c d', 'split', None, 0)
345        self.checkequal(['a b c d'], '  a b c d', 'split', None, 0)
346        self.checkequal(['a', 'b', 'c  d'], 'a  b  c  d', 'split', None, 2)
347
348        self.checkequal([], '         ', 'split')
349        self.checkequal(['a'], '  a    ', 'split')
350        self.checkequal(['a', 'b'], '  a    b   ', 'split')
351        self.checkequal(['a', 'b   '], '  a    b   ', 'split', None, 1)
352        self.checkequal(['a', 'b   c   '], '  a    b   c   ', 'split', None, 1)
353        self.checkequal(['a', 'b', 'c   '], '  a    b   c   ', 'split', None, 2)
354        self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'split')
355        aaa = ' a '*20
356        self.checkequal(['a']*20, aaa, 'split')
357        self.checkequal(['a'] + [aaa[4:]], aaa, 'split', None, 1)
358        self.checkequal(['a']*19 + ['a '], aaa, 'split', None, 19)
359
360        # by a char
361        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|')
362        self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0)
363        self.checkequal(['a', 'b|c|d'], 'a|b|c|d', 'split', '|', 1)
364        self.checkequal(['a', 'b', 'c|d'], 'a|b|c|d', 'split', '|', 2)
365        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|', 3)
366        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|', 4)
367        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|',
368                        sys.maxint-2)
369        self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0)
370        self.checkequal(['a', '', 'b||c||d'], 'a||b||c||d', 'split', '|', 2)
371        self.checkequal(['endcase ', ''], 'endcase |', 'split', '|')
372        self.checkequal(['', ' startcase'], '| startcase', 'split', '|')
373        self.checkequal(['', 'bothcase', ''], '|bothcase|', 'split', '|')
374        self.checkequal(['a', '', 'b\x00c\x00d'], 'a\x00\x00b\x00c\x00d', 'split', '\x00', 2)
375
376        self.checkequal(['a']*20, ('a|'*20)[:-1], 'split', '|')
377        self.checkequal(['a']*15 +['a|a|a|a|a'],
378                                   ('a|'*20)[:-1], 'split', '|', 15)
379
380        # by string
381        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//')
382        self.checkequal(['a', 'b//c//d'], 'a//b//c//d', 'split', '//', 1)
383        self.checkequal(['a', 'b', 'c//d'], 'a//b//c//d', 'split', '//', 2)
384        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//', 3)
385        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//', 4)
386        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//',
387                        sys.maxint-10)
388        self.checkequal(['a//b//c//d'], 'a//b//c//d', 'split', '//', 0)
389        self.checkequal(['a', '', 'b////c////d'], 'a////b////c////d', 'split', '//', 2)
390        self.checkequal(['endcase ', ''], 'endcase test', 'split', 'test')
391        self.checkequal(['', ' begincase'], 'test begincase', 'split', 'test')
392        self.checkequal(['', ' bothcase ', ''], 'test bothcase test',
393                        'split', 'test')
394        self.checkequal(['a', 'bc'], 'abbbc', 'split', 'bb')
395        self.checkequal(['', ''], 'aaa', 'split', 'aaa')
396        self.checkequal(['aaa'], 'aaa', 'split', 'aaa', 0)
397        self.checkequal(['ab', 'ab'], 'abbaab', 'split', 'ba')
398        self.checkequal(['aaaa'], 'aaaa', 'split', 'aab')
399        self.checkequal([''], '', 'split', 'aaa')
400        self.checkequal(['aa'], 'aa', 'split', 'aaa')
401        self.checkequal(['A', 'bobb'], 'Abbobbbobb', 'split', 'bbobb')
402        self.checkequal(['A', 'B', ''], 'AbbobbBbbobb', 'split', 'bbobb')
403
404        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'split', 'BLAH')
405        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'split', 'BLAH', 19)
406        self.checkequal(['a']*18 + ['aBLAHa'], ('aBLAH'*20)[:-4],
407                        'split', 'BLAH', 18)
408
409        # mixed use of str and unicode
410        self.checkequal([u'a', u'b', u'c d'], 'a b c d', 'split', u' ', 2)
411
412        # argument type
413        self.checkraises(TypeError, 'hello', 'split', 42, 42, 42)
414
415        # null case
416        self.checkraises(ValueError, 'hello', 'split', '')
417        self.checkraises(ValueError, 'hello', 'split', '', 0)
418
419    def test_rsplit(self):
420        self.checkequal(['this', 'is', 'the', 'rsplit', 'function'],
421                         'this is the rsplit function', 'rsplit')
422
423        # by whitespace
424        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'rsplit')
425        self.checkequal(['a b c', 'd'], 'a b c d', 'rsplit', None, 1)
426        self.checkequal(['a b', 'c', 'd'], 'a b c d', 'rsplit', None, 2)
427        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 3)
428        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 4)
429        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None,
430                        sys.maxint-20)
431        self.checkequal(['a b c d'], 'a b c d', 'rsplit', None, 0)
432        self.checkequal(['a b c d'], 'a b c d  ', 'rsplit', None, 0)
433        self.checkequal(['a  b', 'c', 'd'], 'a  b  c  d', 'rsplit', None, 2)
434
435        self.checkequal([], '         ', 'rsplit')
436        self.checkequal(['a'], '  a    ', 'rsplit')
437        self.checkequal(['a', 'b'], '  a    b   ', 'rsplit')
438        self.checkequal(['  a', 'b'], '  a    b   ', 'rsplit', None, 1)
439        self.checkequal(['  a    b','c'], '  a    b   c   ', 'rsplit',
440                        None, 1)
441        self.checkequal(['  a', 'b', 'c'], '  a    b   c   ', 'rsplit',
442                        None, 2)
443        self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'rsplit', None, 88)
444        aaa = ' a '*20
445        self.checkequal(['a']*20, aaa, 'rsplit')
446        self.checkequal([aaa[:-4]] + ['a'], aaa, 'rsplit', None, 1)
447        self.checkequal([' a  a'] + ['a']*18, aaa, 'rsplit', None, 18)
448
449
450        # by a char
451        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|')
452        self.checkequal(['a|b|c', 'd'], 'a|b|c|d', 'rsplit', '|', 1)
453        self.checkequal(['a|b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|', 2)
454        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|', 3)
455        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|', 4)
456        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|',
457                        sys.maxint-100)
458        self.checkequal(['a|b|c|d'], 'a|b|c|d', 'rsplit', '|', 0)
459        self.checkequal(['a||b||c', '', 'd'], 'a||b||c||d', 'rsplit', '|', 2)
460        self.checkequal(['', ' begincase'], '| begincase', 'rsplit', '|')
461        self.checkequal(['endcase ', ''], 'endcase |', 'rsplit', '|')
462        self.checkequal(['', 'bothcase', ''], '|bothcase|', 'rsplit', '|')
463
464        self.checkequal(['a\x00\x00b', 'c', 'd'], 'a\x00\x00b\x00c\x00d', 'rsplit', '\x00', 2)
465
466        self.checkequal(['a']*20, ('a|'*20)[:-1], 'rsplit', '|')
467        self.checkequal(['a|a|a|a|a']+['a']*15,
468                        ('a|'*20)[:-1], 'rsplit', '|', 15)
469
470        # by string
471        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//')
472        self.checkequal(['a//b//c', 'd'], 'a//b//c//d', 'rsplit', '//', 1)
473        self.checkequal(['a//b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//', 2)
474        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//', 3)
475        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//', 4)
476        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//',
477                        sys.maxint-5)
478        self.checkequal(['a//b//c//d'], 'a//b//c//d', 'rsplit', '//', 0)
479        self.checkequal(['a////b////c', '', 'd'], 'a////b////c////d', 'rsplit', '//', 2)
480        self.checkequal(['', ' begincase'], 'test begincase', 'rsplit', 'test')
481        self.checkequal(['endcase ', ''], 'endcase test', 'rsplit', 'test')
482        self.checkequal(['', ' bothcase ', ''], 'test bothcase test',
483                        'rsplit', 'test')
484        self.checkequal(['ab', 'c'], 'abbbc', 'rsplit', 'bb')
485        self.checkequal(['', ''], 'aaa', 'rsplit', 'aaa')
486        self.checkequal(['aaa'], 'aaa', 'rsplit', 'aaa', 0)
487        self.checkequal(['ab', 'ab'], 'abbaab', 'rsplit', 'ba')
488        self.checkequal(['aaaa'], 'aaaa', 'rsplit', 'aab')
489        self.checkequal([''], '', 'rsplit', 'aaa')
490        self.checkequal(['aa'], 'aa', 'rsplit', 'aaa')
491        self.checkequal(['bbob', 'A'], 'bbobbbobbA', 'rsplit', 'bbobb')
492        self.checkequal(['', 'B', 'A'], 'bbobbBbbobbA', 'rsplit', 'bbobb')
493
494        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'rsplit', 'BLAH')
495        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'rsplit', 'BLAH', 19)
496        self.checkequal(['aBLAHa'] + ['a']*18, ('aBLAH'*20)[:-4],
497                        'rsplit', 'BLAH', 18)
498
499        # mixed use of str and unicode
500        self.checkequal([u'a b', u'c', u'd'], 'a b c d', 'rsplit', u' ', 2)
501
502        # argument type
503        self.checkraises(TypeError, 'hello', 'rsplit', 42, 42, 42)
504
505        # null case
506        self.checkraises(ValueError, 'hello', 'rsplit', '')
507        self.checkraises(ValueError, 'hello', 'rsplit', '', 0)
508
509    def test_strip(self):
510        self.checkequal('hello', '   hello   ', 'strip')
511        self.checkequal('hello   ', '   hello   ', 'lstrip')
512        self.checkequal('   hello', '   hello   ', 'rstrip')
513        self.checkequal('hello', 'hello', 'strip')
514
515        # strip/lstrip/rstrip with None arg
516        self.checkequal('hello', '   hello   ', 'strip', None)
517        self.checkequal('hello   ', '   hello   ', 'lstrip', None)
518        self.checkequal('   hello', '   hello   ', 'rstrip', None)
519        self.checkequal('hello', 'hello', 'strip', None)
520
521        # strip/lstrip/rstrip with str arg
522        self.checkequal('hello', 'xyzzyhelloxyzzy', 'strip', 'xyz')
523        self.checkequal('helloxyzzy', 'xyzzyhelloxyzzy', 'lstrip', 'xyz')
524        self.checkequal('xyzzyhello', 'xyzzyhelloxyzzy', 'rstrip', 'xyz')
525        self.checkequal('hello', 'hello', 'strip', 'xyz')
526
527        # strip/lstrip/rstrip with unicode arg
528        if test_support.have_unicode:
529            self.checkequal(unicode('hello', 'ascii'), 'xyzzyhelloxyzzy',
530                 'strip', unicode('xyz', 'ascii'))
531            self.checkequal(unicode('helloxyzzy', 'ascii'), 'xyzzyhelloxyzzy',
532                 'lstrip', unicode('xyz', 'ascii'))
533            self.checkequal(unicode('xyzzyhello', 'ascii'), 'xyzzyhelloxyzzy',
534                 'rstrip', unicode('xyz', 'ascii'))
535            # XXX
536            #self.checkequal(unicode('hello', 'ascii'), 'hello',
537            #     'strip', unicode('xyz', 'ascii'))
538
539        self.checkraises(TypeError, 'hello', 'strip', 42, 42)
540        self.checkraises(TypeError, 'hello', 'lstrip', 42, 42)
541        self.checkraises(TypeError, 'hello', 'rstrip', 42, 42)
542
543    def test_ljust(self):
544        self.checkequal('abc       ', 'abc', 'ljust', 10)
545        self.checkequal('abc   ', 'abc', 'ljust', 6)
546        self.checkequal('abc', 'abc', 'ljust', 3)
547        self.checkequal('abc', 'abc', 'ljust', 2)
548        self.checkequal('abc*******', 'abc', 'ljust', 10, '*')
549        self.checkraises(TypeError, 'abc', 'ljust')
550
551    def test_rjust(self):
552        self.checkequal('       abc', 'abc', 'rjust', 10)
553        self.checkequal('   abc', 'abc', 'rjust', 6)
554        self.checkequal('abc', 'abc', 'rjust', 3)
555        self.checkequal('abc', 'abc', 'rjust', 2)
556        self.checkequal('*******abc', 'abc', 'rjust', 10, '*')
557        self.checkraises(TypeError, 'abc', 'rjust')
558
559    def test_center(self):
560        self.checkequal('   abc    ', 'abc', 'center', 10)
561        self.checkequal(' abc  ', 'abc', 'center', 6)
562        self.checkequal('abc', 'abc', 'center', 3)
563        self.checkequal('abc', 'abc', 'center', 2)
564        self.checkequal('***abc****', 'abc', 'center', 10, '*')
565        self.checkraises(TypeError, 'abc', 'center')
566
567    def test_swapcase(self):
568        self.checkequal('hEllO CoMPuTErS', 'HeLLo cOmpUteRs', 'swapcase')
569
570        self.checkraises(TypeError, 'hello', 'swapcase', 42)
571
572    def test_replace(self):
573        EQ = self.checkequal
574
575        # Operations on the empty string
576        EQ("", "", "replace", "", "")
577        EQ("A", "", "replace", "", "A")
578        EQ("", "", "replace", "A", "")
579        EQ("", "", "replace", "A", "A")
580        EQ("", "", "replace", "", "", 100)
581        EQ("", "", "replace", "", "", sys.maxint)
582
583        # interleave (from=="", 'to' gets inserted everywhere)
584        EQ("A", "A", "replace", "", "")
585        EQ("*A*", "A", "replace", "", "*")
586        EQ("*1A*1", "A", "replace", "", "*1")
587        EQ("*-#A*-#", "A", "replace", "", "*-#")
588        EQ("*-A*-A*-", "AA", "replace", "", "*-")
589        EQ("*-A*-A*-", "AA", "replace", "", "*-", -1)
590        EQ("*-A*-A*-", "AA", "replace", "", "*-", sys.maxint)
591        EQ("*-A*-A*-", "AA", "replace", "", "*-", 4)
592        EQ("*-A*-A*-", "AA", "replace", "", "*-", 3)
593        EQ("*-A*-A", "AA", "replace", "", "*-", 2)
594        EQ("*-AA", "AA", "replace", "", "*-", 1)
595        EQ("AA", "AA", "replace", "", "*-", 0)
596
597        # single character deletion (from=="A", to=="")
598        EQ("", "A", "replace", "A", "")
599        EQ("", "AAA", "replace", "A", "")
600        EQ("", "AAA", "replace", "A", "", -1)
601        EQ("", "AAA", "replace", "A", "", sys.maxint)
602        EQ("", "AAA", "replace", "A", "", 4)
603        EQ("", "AAA", "replace", "A", "", 3)
604        EQ("A", "AAA", "replace", "A", "", 2)
605        EQ("AA", "AAA", "replace", "A", "", 1)
606        EQ("AAA", "AAA", "replace", "A", "", 0)
607        EQ("", "AAAAAAAAAA", "replace", "A", "")
608        EQ("BCD", "ABACADA", "replace", "A", "")
609        EQ("BCD", "ABACADA", "replace", "A", "", -1)
610        EQ("BCD", "ABACADA", "replace", "A", "", sys.maxint)
611        EQ("BCD", "ABACADA", "replace", "A", "", 5)
612        EQ("BCD", "ABACADA", "replace", "A", "", 4)
613        EQ("BCDA", "ABACADA", "replace", "A", "", 3)
614        EQ("BCADA", "ABACADA", "replace", "A", "", 2)
615        EQ("BACADA", "ABACADA", "replace", "A", "", 1)
616        EQ("ABACADA", "ABACADA", "replace", "A", "", 0)
617        EQ("BCD", "ABCAD", "replace", "A", "")
618        EQ("BCD", "ABCADAA", "replace", "A", "")
619        EQ("BCD", "BCD", "replace", "A", "")
620        EQ("*************", "*************", "replace", "A", "")
621        EQ("^A^", "^"+"A"*1000+"^", "replace", "A", "", 999)
622
623        # substring deletion (from=="the", to=="")
624        EQ("", "the", "replace", "the", "")
625        EQ("ater", "theater", "replace", "the", "")
626        EQ("", "thethe", "replace", "the", "")
627        EQ("", "thethethethe", "replace", "the", "")
628        EQ("aaaa", "theatheatheathea", "replace", "the", "")
629        EQ("that", "that", "replace", "the", "")
630        EQ("thaet", "thaet", "replace", "the", "")
631        EQ("here and re", "here and there", "replace", "the", "")
632        EQ("here and re and re", "here and there and there",
633           "replace", "the", "", sys.maxint)
634        EQ("here and re and re", "here and there and there",
635           "replace", "the", "", -1)
636        EQ("here and re and re", "here and there and there",
637           "replace", "the", "", 3)
638        EQ("here and re and re", "here and there and there",
639           "replace", "the", "", 2)
640        EQ("here and re and there", "here and there and there",
641           "replace", "the", "", 1)
642        EQ("here and there and there", "here and there and there",
643           "replace", "the", "", 0)
644        EQ("here and re and re", "here and there and there", "replace", "the", "")
645
646        EQ("abc", "abc", "replace", "the", "")
647        EQ("abcdefg", "abcdefg", "replace", "the", "")
648
649        # substring deletion (from=="bob", to=="")
650        EQ("bob", "bbobob", "replace", "bob", "")
651        EQ("bobXbob", "bbobobXbbobob", "replace", "bob", "")
652        EQ("aaaaaaa", "aaaaaaabob", "replace", "bob", "")
653        EQ("aaaaaaa", "aaaaaaa", "replace", "bob", "")
654
655        # single character replace in place (len(from)==len(to)==1)
656        EQ("Who goes there?", "Who goes there?", "replace", "o", "o")
657        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O")
658        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", sys.maxint)
659        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", -1)
660        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", 3)
661        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", 2)
662        EQ("WhO goes there?", "Who goes there?", "replace", "o", "O", 1)
663        EQ("Who goes there?", "Who goes there?", "replace", "o", "O", 0)
664
665        EQ("Who goes there?", "Who goes there?", "replace", "a", "q")
666        EQ("who goes there?", "Who goes there?", "replace", "W", "w")
667        EQ("wwho goes there?ww", "WWho goes there?WW", "replace", "W", "w")
668        EQ("Who goes there!", "Who goes there?", "replace", "?", "!")
669        EQ("Who goes there!!", "Who goes there??", "replace", "?", "!")
670
671        EQ("Who goes there?", "Who goes there?", "replace", ".", "!")
672
673        # substring replace in place (len(from)==len(to) > 1)
674        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**")
675        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", sys.maxint)
676        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", -1)
677        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", 4)
678        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", 3)
679        EQ("Th** ** a tissue", "This is a tissue", "replace", "is", "**", 2)
680        EQ("Th** is a tissue", "This is a tissue", "replace", "is", "**", 1)
681        EQ("This is a tissue", "This is a tissue", "replace", "is", "**", 0)
682        EQ("cobob", "bobob", "replace", "bob", "cob")
683        EQ("cobobXcobocob", "bobobXbobobob", "replace", "bob", "cob")
684        EQ("bobob", "bobob", "replace", "bot", "bot")
685
686        # replace single character (len(from)==1, len(to)>1)
687        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK")
688        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK", -1)
689        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK", sys.maxint)
690        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK", 2)
691        EQ("ReyKKjavik", "Reykjavik", "replace", "k", "KK", 1)
692        EQ("Reykjavik", "Reykjavik", "replace", "k", "KK", 0)
693        EQ("A----B----C----", "A.B.C.", "replace", ".", "----")
694
695        EQ("Reykjavik", "Reykjavik", "replace", "q", "KK")
696
697        # replace substring (len(from)>1, len(to)!=len(from))
698        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
699           "replace", "spam", "ham")
700        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
701           "replace", "spam", "ham", sys.maxint)
702        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
703           "replace", "spam", "ham", -1)
704        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
705           "replace", "spam", "ham", 4)
706        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
707           "replace", "spam", "ham", 3)
708        EQ("ham, ham, eggs and spam", "spam, spam, eggs and spam",
709           "replace", "spam", "ham", 2)
710        EQ("ham, spam, eggs and spam", "spam, spam, eggs and spam",
711           "replace", "spam", "ham", 1)
712        EQ("spam, spam, eggs and spam", "spam, spam, eggs and spam",
713           "replace", "spam", "ham", 0)
714
715        EQ("bobob", "bobobob", "replace", "bobob", "bob")
716        EQ("bobobXbobob", "bobobobXbobobob", "replace", "bobob", "bob")
717        EQ("BOBOBOB", "BOBOBOB", "replace", "bob", "bobby")
718
719        with test_support.check_py3k_warnings():
720            ba = buffer('a')
721            bb = buffer('b')
722        EQ("bbc", "abc", "replace", ba, bb)
723        EQ("aac", "abc", "replace", bb, ba)
724
725        #
726        self.checkequal('one@two!three!', 'one!two!three!', 'replace', '!', '@', 1)
727        self.checkequal('onetwothree', 'one!two!three!', 'replace', '!', '')
728        self.checkequal('one@two@three!', 'one!two!three!', 'replace', '!', '@', 2)
729        self.checkequal('one@two@three@', 'one!two!three!', 'replace', '!', '@', 3)
730        self.checkequal('one@two@three@', 'one!two!three!', 'replace', '!', '@', 4)
731        self.checkequal('one!two!three!', 'one!two!three!', 'replace', '!', '@', 0)
732        self.checkequal('one@two@three@', 'one!two!three!', 'replace', '!', '@')
733        self.checkequal('one!two!three!', 'one!two!three!', 'replace', 'x', '@')
734        self.checkequal('one!two!three!', 'one!two!three!', 'replace', 'x', '@', 2)
735        self.checkequal('-a-b-c-', 'abc', 'replace', '', '-')
736        self.checkequal('-a-b-c', 'abc', 'replace', '', '-', 3)
737        self.checkequal('abc', 'abc', 'replace', '', '-', 0)
738        self.checkequal('', '', 'replace', '', '')
739        self.checkequal('abc', 'abc', 'replace', 'ab', '--', 0)
740        self.checkequal('abc', 'abc', 'replace', 'xy', '--')
741        # Next three for SF bug 422088: [OSF1 alpha] string.replace(); died with
742        # MemoryError due to empty result (platform malloc issue when requesting
743        # 0 bytes).
744        self.checkequal('', '123', 'replace', '123', '')
745        self.checkequal('', '123123', 'replace', '123', '')
746        self.checkequal('x', '123x123', 'replace', '123', '')
747
748        self.checkraises(TypeError, 'hello', 'replace')
749        self.checkraises(TypeError, 'hello', 'replace', 42)
750        self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
751        self.checkraises(TypeError, 'hello', 'replace', 'h', 42)
752
753    def test_replace_overflow(self):
754        # Check for overflow checking on 32 bit machines
755        if sys.maxint != 2147483647 or struct.calcsize("P") > 4:
756            return
757        A2_16 = "A" * (2**16)
758        self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
759        self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
760        self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
761
762    def test_zfill(self):
763        self.checkequal('123', '123', 'zfill', 2)
764        self.checkequal('123', '123', 'zfill', 3)
765        self.checkequal('0123', '123', 'zfill', 4)
766        self.checkequal('+123', '+123', 'zfill', 3)
767        self.checkequal('+123', '+123', 'zfill', 4)
768        self.checkequal('+0123', '+123', 'zfill', 5)
769        self.checkequal('-123', '-123', 'zfill', 3)
770        self.checkequal('-123', '-123', 'zfill', 4)
771        self.checkequal('-0123', '-123', 'zfill', 5)
772        self.checkequal('000', '', 'zfill', 3)
773        self.checkequal('34', '34', 'zfill', 1)
774        self.checkequal('0034', '34', 'zfill', 4)
775
776        self.checkraises(TypeError, '123', 'zfill')
777
778# XXX alias for py3k forward compatibility
779BaseTest = CommonTest
780
781class MixinStrUnicodeUserStringTest:
782    # additional tests that only work for
783    # stringlike objects, i.e. str, unicode, UserString
784    # (but not the string module)
785
786    def test_islower(self):
787        self.checkequal(False, '', 'islower')
788        self.checkequal(True, 'a', 'islower')
789        self.checkequal(False, 'A', 'islower')
790        self.checkequal(False, '\n', 'islower')
791        self.checkequal(True, 'abc', 'islower')
792        self.checkequal(False, 'aBc', 'islower')
793        self.checkequal(True, 'abc\n', 'islower')
794        self.checkraises(TypeError, 'abc', 'islower', 42)
795
796    def test_isupper(self):
797        self.checkequal(False, '', 'isupper')
798        self.checkequal(False, 'a', 'isupper')
799        self.checkequal(True, 'A', 'isupper')
800        self.checkequal(False, '\n', 'isupper')
801        self.checkequal(True, 'ABC', 'isupper')
802        self.checkequal(False, 'AbC', 'isupper')
803        self.checkequal(True, 'ABC\n', 'isupper')
804        self.checkraises(TypeError, 'abc', 'isupper', 42)
805
806    def test_istitle(self):
807        self.checkequal(False, '', 'istitle')
808        self.checkequal(False, 'a', 'istitle')
809        self.checkequal(True, 'A', 'istitle')
810        self.checkequal(False, '\n', 'istitle')
811        self.checkequal(True, 'A Titlecased Line', 'istitle')
812        self.checkequal(True, 'A\nTitlecased Line', 'istitle')
813        self.checkequal(True, 'A Titlecased, Line', 'istitle')
814        self.checkequal(False, 'Not a capitalized String', 'istitle')
815        self.checkequal(False, 'Not\ta Titlecase String', 'istitle')
816        self.checkequal(False, 'Not--a Titlecase String', 'istitle')
817        self.checkequal(False, 'NOT', 'istitle')
818        self.checkraises(TypeError, 'abc', 'istitle', 42)
819
820    def test_isspace(self):
821        self.checkequal(False, '', 'isspace')
822        self.checkequal(False, 'a', 'isspace')
823        self.checkequal(True, ' ', 'isspace')
824        self.checkequal(True, '\t', 'isspace')
825        self.checkequal(True, '\r', 'isspace')
826        self.checkequal(True, '\n', 'isspace')
827        self.checkequal(True, ' \t\r\n', 'isspace')
828        self.checkequal(False, ' \t\r\na', 'isspace')
829        self.checkraises(TypeError, 'abc', 'isspace', 42)
830
831    def test_isalpha(self):
832        self.checkequal(False, '', 'isalpha')
833        self.checkequal(True, 'a', 'isalpha')
834        self.checkequal(True, 'A', 'isalpha')
835        self.checkequal(False, '\n', 'isalpha')
836        self.checkequal(True, 'abc', 'isalpha')
837        self.checkequal(False, 'aBc123', 'isalpha')
838        self.checkequal(False, 'abc\n', 'isalpha')
839        self.checkraises(TypeError, 'abc', 'isalpha', 42)
840
841    def test_isalnum(self):
842        self.checkequal(False, '', 'isalnum')
843        self.checkequal(True, 'a', 'isalnum')
844        self.checkequal(True, 'A', 'isalnum')
845        self.checkequal(False, '\n', 'isalnum')
846        self.checkequal(True, '123abc456', 'isalnum')
847        self.checkequal(True, 'a1b3c', 'isalnum')
848        self.checkequal(False, 'aBc000 ', 'isalnum')
849        self.checkequal(False, 'abc\n', 'isalnum')
850        self.checkraises(TypeError, 'abc', 'isalnum', 42)
851
852    def test_isdigit(self):
853        self.checkequal(False, '', 'isdigit')
854        self.checkequal(False, 'a', 'isdigit')
855        self.checkequal(True, '0', 'isdigit')
856        self.checkequal(True, '0123456789', 'isdigit')
857        self.checkequal(False, '0123456789a', 'isdigit')
858
859        self.checkraises(TypeError, 'abc', 'isdigit', 42)
860
861    def test_title(self):
862        self.checkequal(' Hello ', ' hello ', 'title')
863        self.checkequal('Hello ', 'hello ', 'title')
864        self.checkequal('Hello ', 'Hello ', 'title')
865        self.checkequal('Format This As Title String', "fOrMaT thIs aS titLe String", 'title')
866        self.checkequal('Format,This-As*Title;String', "fOrMaT,thIs-aS*titLe;String", 'title', )
867        self.checkequal('Getint', "getInt", 'title')
868        self.checkraises(TypeError, 'hello', 'title', 42)
869
870    def test_splitlines(self):
871        self.checkequal(['abc', 'def', '', 'ghi'], "abc\ndef\n\rghi", 'splitlines')
872        self.checkequal(['abc', 'def', '', 'ghi'], "abc\ndef\n\r\nghi", 'splitlines')
873        self.checkequal(['abc', 'def', 'ghi'], "abc\ndef\r\nghi", 'splitlines')
874        self.checkequal(['abc', 'def', 'ghi'], "abc\ndef\r\nghi\n", 'splitlines')
875        self.checkequal(['abc', 'def', 'ghi', ''], "abc\ndef\r\nghi\n\r", 'splitlines')
876        self.checkequal(['', 'abc', 'def', 'ghi', ''], "\nabc\ndef\r\nghi\n\r", 'splitlines')
877        self.checkequal(['\n', 'abc\n', 'def\r\n', 'ghi\n', '\r'], "\nabc\ndef\r\nghi\n\r", 'splitlines', 1)
878
879        self.checkraises(TypeError, 'abc', 'splitlines', 42, 42)
880
881    def test_startswith(self):
882        self.checkequal(True, 'hello', 'startswith', 'he')
883        self.checkequal(True, 'hello', 'startswith', 'hello')
884        self.checkequal(False, 'hello', 'startswith', 'hello world')
885        self.checkequal(True, 'hello', 'startswith', '')
886        self.checkequal(False, 'hello', 'startswith', 'ello')
887        self.checkequal(True, 'hello', 'startswith', 'ello', 1)
888        self.checkequal(True, 'hello', 'startswith', 'o', 4)
889        self.checkequal(False, 'hello', 'startswith', 'o', 5)
890        self.checkequal(True, 'hello', 'startswith', '', 5)
891        self.checkequal(False, 'hello', 'startswith', 'lo', 6)
892        self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3)
893        self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3, 7)
894        self.checkequal(False, 'helloworld', 'startswith', 'lowo', 3, 6)
895
896        # test negative indices
897        self.checkequal(True, 'hello', 'startswith', 'he', 0, -1)
898        self.checkequal(True, 'hello', 'startswith', 'he', -53, -1)
899        self.checkequal(False, 'hello', 'startswith', 'hello', 0, -1)
900        self.checkequal(False, 'hello', 'startswith', 'hello world', -1, -10)
901        self.checkequal(False, 'hello', 'startswith', 'ello', -5)
902        self.checkequal(True, 'hello', 'startswith', 'ello', -4)
903        self.checkequal(False, 'hello', 'startswith', 'o', -2)
904        self.checkequal(True, 'hello', 'startswith', 'o', -1)
905        self.checkequal(True, 'hello', 'startswith', '', -3, -3)
906        self.checkequal(False, 'hello', 'startswith', 'lo', -9)
907
908        self.checkraises(TypeError, 'hello', 'startswith')
909        self.checkraises(TypeError, 'hello', 'startswith', 42)
910
911        # test tuple arguments
912        self.checkequal(True, 'hello', 'startswith', ('he', 'ha'))
913        self.checkequal(False, 'hello', 'startswith', ('lo', 'llo'))
914        self.checkequal(True, 'hello', 'startswith', ('hellox', 'hello'))
915        self.checkequal(False, 'hello', 'startswith', ())
916        self.checkequal(True, 'helloworld', 'startswith', ('hellowo',
917                                                           'rld', 'lowo'), 3)
918        self.checkequal(False, 'helloworld', 'startswith', ('hellowo', 'ello',
919                                                            'rld'), 3)
920        self.checkequal(True, 'hello', 'startswith', ('lo', 'he'), 0, -1)
921        self.checkequal(False, 'hello', 'startswith', ('he', 'hel'), 0, 1)
922        self.checkequal(True, 'hello', 'startswith', ('he', 'hel'), 0, 2)
923
924        self.checkraises(TypeError, 'hello', 'startswith', (42,))
925
926    def test_endswith(self):
927        self.checkequal(True, 'hello', 'endswith', 'lo')
928        self.checkequal(False, 'hello', 'endswith', 'he')
929        self.checkequal(True, 'hello', 'endswith', '')
930        self.checkequal(False, 'hello', 'endswith', 'hello world')
931        self.checkequal(False, 'helloworld', 'endswith', 'worl')
932        self.checkequal(True, 'helloworld', 'endswith', 'worl', 3, 9)
933        self.checkequal(True, 'helloworld', 'endswith', 'world', 3, 12)
934        self.checkequal(True, 'helloworld', 'endswith', 'lowo', 1, 7)
935        self.checkequal(True, 'helloworld', 'endswith', 'lowo', 2, 7)
936        self.checkequal(True, 'helloworld', 'endswith', 'lowo', 3, 7)
937        self.checkequal(False, 'helloworld', 'endswith', 'lowo', 4, 7)
938        self.checkequal(False, 'helloworld', 'endswith', 'lowo', 3, 8)
939        self.checkequal(False, 'ab', 'endswith', 'ab', 0, 1)
940        self.checkequal(False, 'ab', 'endswith', 'ab', 0, 0)
941
942        # test negative indices
943        self.checkequal(True, 'hello', 'endswith', 'lo', -2)
944        self.checkequal(False, 'hello', 'endswith', 'he', -2)
945        self.checkequal(True, 'hello', 'endswith', '', -3, -3)
946        self.checkequal(False, 'hello', 'endswith', 'hello world', -10, -2)
947        self.checkequal(False, 'helloworld', 'endswith', 'worl', -6)
948        self.checkequal(True, 'helloworld', 'endswith', 'worl', -5, -1)
949        self.checkequal(True, 'helloworld', 'endswith', 'worl', -5, 9)
950        self.checkequal(True, 'helloworld', 'endswith', 'world', -7, 12)
951        self.checkequal(True, 'helloworld', 'endswith', 'lowo', -99, -3)
952        self.checkequal(True, 'helloworld', 'endswith', 'lowo', -8, -3)
953        self.checkequal(True, 'helloworld', 'endswith', 'lowo', -7, -3)
954        self.checkequal(False, 'helloworld', 'endswith', 'lowo', 3, -4)
955        self.checkequal(False, 'helloworld', 'endswith', 'lowo', -8, -2)
956
957        self.checkraises(TypeError, 'hello', 'endswith')
958        self.checkraises(TypeError, 'hello', 'endswith', 42)
959
960        # test tuple arguments
961        self.checkequal(False, 'hello', 'endswith', ('he', 'ha'))
962        self.checkequal(True, 'hello', 'endswith', ('lo', 'llo'))
963        self.checkequal(True, 'hello', 'endswith', ('hellox', 'hello'))
964        self.checkequal(False, 'hello', 'endswith', ())
965        self.checkequal(True, 'helloworld', 'endswith', ('hellowo',
966                                                           'rld', 'lowo'), 3)
967        self.checkequal(False, 'helloworld', 'endswith', ('hellowo', 'ello',
968                                                            'rld'), 3, -1)
969        self.checkequal(True, 'hello', 'endswith', ('hell', 'ell'), 0, -1)
970        self.checkequal(False, 'hello', 'endswith', ('he', 'hel'), 0, 1)
971        self.checkequal(True, 'hello', 'endswith', ('he', 'hell'), 0, 4)
972
973        self.checkraises(TypeError, 'hello', 'endswith', (42,))
974
975    def test___contains__(self):
976        self.checkequal(True, '', '__contains__', '')
977        self.checkequal(True, 'abc', '__contains__', '')
978        self.checkequal(False, 'abc', '__contains__', '\0')
979        self.checkequal(True, '\0abc', '__contains__', '\0')
980        self.checkequal(True, 'abc\0', '__contains__', '\0')
981        self.checkequal(True, '\0abc', '__contains__', 'a')
982        self.checkequal(True, 'asdf', '__contains__', 'asdf')
983        self.checkequal(False, 'asd', '__contains__', 'asdf')
984        self.checkequal(False, '', '__contains__', 'asdf')
985
986    def test_subscript(self):
987        self.checkequal(u'a', 'abc', '__getitem__', 0)
988        self.checkequal(u'c', 'abc', '__getitem__', -1)
989        self.checkequal(u'a', 'abc', '__getitem__', 0L)
990        self.checkequal(u'abc', 'abc', '__getitem__', slice(0, 3))
991        self.checkequal(u'abc', 'abc', '__getitem__', slice(0, 1000))
992        self.checkequal(u'a', 'abc', '__getitem__', slice(0, 1))
993        self.checkequal(u'', 'abc', '__getitem__', slice(0, 0))
994
995        self.checkraises(TypeError, 'abc', '__getitem__', 'def')
996
997    def test_slice(self):
998        self.checkequal('abc', 'abc', '__getslice__', 0, 1000)
999        self.checkequal('abc', 'abc', '__getslice__', 0, 3)
1000        self.checkequal('ab', 'abc', '__getslice__', 0, 2)
1001        self.checkequal('bc', 'abc', '__getslice__', 1, 3)
1002        self.checkequal('b', 'abc', '__getslice__', 1, 2)
1003        self.checkequal('', 'abc', '__getslice__', 2, 2)
1004        self.checkequal('', 'abc', '__getslice__', 1000, 1000)
1005        self.checkequal('', 'abc', '__getslice__', 2000, 1000)
1006        self.checkequal('', 'abc', '__getslice__', 2, 1)
1007
1008        self.checkraises(TypeError, 'abc', '__getslice__', 'def')
1009
1010    def test_extended_getslice(self):
1011        # Test extended slicing by comparing with list slicing.
1012        s = string.ascii_letters + string.digits
1013        indices = (0, None, 1, 3, 41, -1, -2, -37)
1014        for start in indices:
1015            for stop in indices:
1016                # Skip step 0 (invalid)
1017                for step in indices[1:]:
1018                    L = list(s)[start:stop:step]
1019                    self.checkequal(u"".join(L), s, '__getitem__',
1020                                    slice(start, stop, step))
1021
1022    def test_mul(self):
1023        self.checkequal('', 'abc', '__mul__', -1)
1024        self.checkequal('', 'abc', '__mul__', 0)
1025        self.checkequal('abc', 'abc', '__mul__', 1)
1026        self.checkequal('abcabcabc', 'abc', '__mul__', 3)
1027        self.checkraises(TypeError, 'abc', '__mul__')
1028        self.checkraises(TypeError, 'abc', '__mul__', '')
1029        # XXX: on a 64-bit system, this doesn't raise an overflow error,
1030        # but either raises a MemoryError, or succeeds (if you have 54TiB)
1031        #self.checkraises(OverflowError, 10000*'abc', '__mul__', 2000000000)
1032
1033    def test_join(self):
1034        # join now works with any sequence type
1035        # moved here, because the argument order is
1036        # different in string.join (see the test in
1037        # test.test_string.StringTest.test_join)
1038        self.checkequal('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
1039        self.checkequal('abcd', '', 'join', ('a', 'b', 'c', 'd'))
1040        self.checkequal('bd', '', 'join', ('', 'b', '', 'd'))
1041        self.checkequal('ac', '', 'join', ('a', '', 'c', ''))
1042        self.checkequal('w x y z', ' ', 'join', Sequence())
1043        self.checkequal('abc', 'a', 'join', ('abc',))
1044        self.checkequal('z', 'a', 'join', UserList(['z']))
1045        if test_support.have_unicode:
1046            self.checkequal(unicode('a.b.c'), unicode('.'), 'join', ['a', 'b', 'c'])
1047            self.checkequal(unicode('a.b.c'), '.', 'join', [unicode('a'), 'b', 'c'])
1048            self.checkequal(unicode('a.b.c'), '.', 'join', ['a', unicode('b'), 'c'])
1049            self.checkequal(unicode('a.b.c'), '.', 'join', ['a', 'b', unicode('c')])
1050            self.checkraises(TypeError, '.', 'join', ['a', unicode('b'), 3])
1051        for i in [5, 25, 125]:
1052            self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
1053                 ['a' * i] * i)
1054            self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
1055                 ('a' * i,) * i)
1056
1057        self.checkraises(TypeError, ' ', 'join', BadSeq1())
1058        self.checkequal('a b c', ' ', 'join', BadSeq2())
1059
1060        self.checkraises(TypeError, ' ', 'join')
1061        self.checkraises(TypeError, ' ', 'join', 7)
1062        self.checkraises(TypeError, ' ', 'join', Sequence([7, 'hello', 123L]))
1063        try:
1064            def f():
1065                yield 4 + ""
1066            self.fixtype(' ').join(f())
1067        except TypeError, e:
1068            if '+' not in str(e):
1069                self.fail('join() ate exception message')
1070        else:
1071            self.fail('exception not raised')
1072
1073    def test_formatting(self):
1074        self.checkequal('+hello+', '+%s+', '__mod__', 'hello')
1075        self.checkequal('+10+', '+%d+', '__mod__', 10)
1076        self.checkequal('a', "%c", '__mod__', "a")
1077        self.checkequal('a', "%c", '__mod__', "a")
1078        self.checkequal('"', "%c", '__mod__', 34)
1079        self.checkequal('$', "%c", '__mod__', 36)
1080        self.checkequal('10', "%d", '__mod__', 10)
1081        self.checkequal('\x7f', "%c", '__mod__', 0x7f)
1082
1083        for ordinal in (-100, 0x200000):
1084            # unicode raises ValueError, str raises OverflowError
1085            self.checkraises((ValueError, OverflowError), '%c', '__mod__', ordinal)
1086
1087        longvalue = sys.maxint + 10L
1088        slongvalue = str(longvalue)
1089        if slongvalue[-1] in ("L","l"): slongvalue = slongvalue[:-1]
1090        self.checkequal(' 42', '%3ld', '__mod__', 42)
1091        self.checkequal('42', '%d', '__mod__', 42L)
1092        self.checkequal('42', '%d', '__mod__', 42.0)
1093        self.checkequal(slongvalue, '%d', '__mod__', longvalue)
1094        self.checkcall('%d', '__mod__', float(longvalue))
1095        self.checkequal('0042.00', '%07.2f', '__mod__', 42)
1096        self.checkequal('0042.00', '%07.2F', '__mod__', 42)
1097
1098        self.checkraises(TypeError, 'abc', '__mod__')
1099        self.checkraises(TypeError, '%(foo)s', '__mod__', 42)
1100        self.checkraises(TypeError, '%s%s', '__mod__', (42,))
1101        self.checkraises(TypeError, '%c', '__mod__', (None,))
1102        self.checkraises(ValueError, '%(foo', '__mod__', {})
1103        self.checkraises(TypeError, '%(foo)s %(bar)s', '__mod__', ('foo', 42))
1104        self.checkraises(TypeError, '%d', '__mod__', "42") # not numeric
1105        self.checkraises(TypeError, '%d', '__mod__', (42+0j)) # no int/long conversion provided
1106
1107        # argument names with properly nested brackets are supported
1108        self.checkequal('bar', '%((foo))s', '__mod__', {'(foo)': 'bar'})
1109
1110        # 100 is a magic number in PyUnicode_Format, this forces a resize
1111        self.checkequal(103*'a'+'x', '%sx', '__mod__', 103*'a')
1112
1113        self.checkraises(TypeError, '%*s', '__mod__', ('foo', 'bar'))
1114        self.checkraises(TypeError, '%10.*f', '__mod__', ('foo', 42.))
1115        self.checkraises(ValueError, '%10', '__mod__', (42,))
1116
1117        width = int(_testcapi.PY_SSIZE_T_MAX + 1)
1118        if width <= sys.maxint:
1119            self.checkraises(OverflowError, '%*s', '__mod__', (width, ''))
1120        prec = int(_testcapi.INT_MAX + 1)
1121        if prec <= sys.maxint:
1122            self.checkraises(OverflowError, '%.*f', '__mod__', (prec, 1. / 7))
1123        # Issue 15989
1124        width = int(1 << (_testcapi.PY_SSIZE_T_MAX.bit_length() + 1))
1125        if width <= sys.maxint:
1126            self.checkraises(OverflowError, '%*s', '__mod__', (width, ''))
1127        prec = int(_testcapi.UINT_MAX + 1)
1128        if prec <= sys.maxint:
1129            self.checkraises(OverflowError, '%.*f', '__mod__', (prec, 1. / 7))
1130
1131        class X(object): pass
1132        self.checkraises(TypeError, 'abc', '__mod__', X())
1133        class X(Exception):
1134            def __getitem__(self, k):
1135                return k
1136        self.checkequal('melon apple', '%(melon)s %(apple)s', '__mod__', X())
1137
1138    def test_floatformatting(self):
1139        # float formatting
1140        for prec in xrange(100):
1141            format = '%%.%if' % prec
1142            value = 0.01
1143            for x in xrange(60):
1144                value = value * 3.14159265359 / 3.0 * 10.0
1145                self.checkcall(format, "__mod__", value)
1146
1147    def test_inplace_rewrites(self):
1148        # Check that strings don't copy and modify cached single-character strings
1149        self.checkequal('a', 'A', 'lower')
1150        self.checkequal(True, 'A', 'isupper')
1151        self.checkequal('A', 'a', 'upper')
1152        self.checkequal(True, 'a', 'islower')
1153
1154        self.checkequal('a', 'A', 'replace', 'A', 'a')
1155        self.checkequal(True, 'A', 'isupper')
1156
1157        self.checkequal('A', 'a', 'capitalize')
1158        self.checkequal(True, 'a', 'islower')
1159
1160        self.checkequal('A', 'a', 'swapcase')
1161        self.checkequal(True, 'a', 'islower')
1162
1163        self.checkequal('A', 'a', 'title')
1164        self.checkequal(True, 'a', 'islower')
1165
1166    def test_partition(self):
1167
1168        self.checkequal(('this is the par', 'ti', 'tion method'),
1169            'this is the partition method', 'partition', 'ti')
1170
1171        # from raymond's original specification
1172        S = 'http://www.python.org'
1173        self.checkequal(('http', '://', 'www.python.org'), S, 'partition', '://')
1174        self.checkequal(('http://www.python.org', '', ''), S, 'partition', '?')
1175        self.checkequal(('', 'http://', 'www.python.org'), S, 'partition', 'http://')
1176        self.checkequal(('http://www.python.', 'org', ''), S, 'partition', 'org')
1177
1178        self.checkraises(ValueError, S, 'partition', '')
1179        self.checkraises(TypeError, S, 'partition', None)
1180
1181        # mixed use of str and unicode
1182        self.assertEqual('a/b/c'.partition(u'/'), ('a', '/', 'b/c'))
1183
1184    def test_rpartition(self):
1185
1186        self.checkequal(('this is the rparti', 'ti', 'on method'),
1187            'this is the rpartition method', 'rpartition', 'ti')
1188
1189        # from raymond's original specification
1190        S = 'http://www.python.org'
1191        self.checkequal(('http', '://', 'www.python.org'), S, 'rpartition', '://')
1192        self.checkequal(('', '', 'http://www.python.org'), S, 'rpartition', '?')
1193        self.checkequal(('', 'http://', 'www.python.org'), S, 'rpartition', 'http://')
1194        self.checkequal(('http://www.python.', 'org', ''), S, 'rpartition', 'org')
1195
1196        self.checkraises(ValueError, S, 'rpartition', '')
1197        self.checkraises(TypeError, S, 'rpartition', None)
1198
1199        # mixed use of str and unicode
1200        self.assertEqual('a/b/c'.rpartition(u'/'), ('a/b', '/', 'c'))
1201
1202    def test_none_arguments(self):
1203        # issue 11828
1204        s = 'hello'
1205        self.checkequal(2, s, 'find', 'l', None)
1206        self.checkequal(3, s, 'find', 'l', -2, None)
1207        self.checkequal(2, s, 'find', 'l', None, -2)
1208        self.checkequal(0, s, 'find', 'h', None, None)
1209
1210        self.checkequal(3, s, 'rfind', 'l', None)
1211        self.checkequal(3, s, 'rfind', 'l', -2, None)
1212        self.checkequal(2, s, 'rfind', 'l', None, -2)
1213        self.checkequal(0, s, 'rfind', 'h', None, None)
1214
1215        self.checkequal(2, s, 'index', 'l', None)
1216        self.checkequal(3, s, 'index', 'l', -2, None)
1217        self.checkequal(2, s, 'index', 'l', None, -2)
1218        self.checkequal(0, s, 'index', 'h', None, None)
1219
1220        self.checkequal(3, s, 'rindex', 'l', None)
1221        self.checkequal(3, s, 'rindex', 'l', -2, None)
1222        self.checkequal(2, s, 'rindex', 'l', None, -2)
1223        self.checkequal(0, s, 'rindex', 'h', None, None)
1224
1225        self.checkequal(2, s, 'count', 'l', None)
1226        self.checkequal(1, s, 'count', 'l', -2, None)
1227        self.checkequal(1, s, 'count', 'l', None, -2)
1228        self.checkequal(0, s, 'count', 'x', None, None)
1229
1230        self.checkequal(True, s, 'endswith', 'o', None)
1231        self.checkequal(True, s, 'endswith', 'lo', -2, None)
1232        self.checkequal(True, s, 'endswith', 'l', None, -2)
1233        self.checkequal(False, s, 'endswith', 'x', None, None)
1234
1235        self.checkequal(True, s, 'startswith', 'h', None)
1236        self.checkequal(True, s, 'startswith', 'l', -2, None)
1237        self.checkequal(True, s, 'startswith', 'h', None, -2)
1238        self.checkequal(False, s, 'startswith', 'x', None, None)
1239
1240    def test_find_etc_raise_correct_error_messages(self):
1241        # issue 11828
1242        s = 'hello'
1243        x = 'x'
1244        self.assertRaisesRegexp(TypeError, r'\bfind\b', s.find,
1245                                x, None, None, None)
1246        self.assertRaisesRegexp(TypeError, r'\brfind\b', s.rfind,
1247                                x, None, None, None)
1248        self.assertRaisesRegexp(TypeError, r'\bindex\b', s.index,
1249                                x, None, None, None)
1250        self.assertRaisesRegexp(TypeError, r'\brindex\b', s.rindex,
1251                                x, None, None, None)
1252        self.assertRaisesRegexp(TypeError, r'^count\(', s.count,
1253                                x, None, None, None)
1254        self.assertRaisesRegexp(TypeError, r'^startswith\(', s.startswith,
1255                                x, None, None, None)
1256        self.assertRaisesRegexp(TypeError, r'^endswith\(', s.endswith,
1257                                x, None, None, None)
1258
1259class MixinStrStringUserStringTest:
1260    # Additional tests for 8bit strings, i.e. str, UserString and
1261    # the string module
1262
1263    def test_maketrans(self):
1264        self.assertEqual(
1265           ''.join(map(chr, xrange(256))).replace('abc', 'xyz'),
1266           string.maketrans('abc', 'xyz')
1267        )
1268        self.assertRaises(ValueError, string.maketrans, 'abc', 'xyzw')
1269
1270    def test_translate(self):
1271        table = string.maketrans('abc', 'xyz')
1272        self.checkequal('xyzxyz', 'xyzabcdef', 'translate', table, 'def')
1273
1274        table = string.maketrans('a', 'A')
1275        self.checkequal('Abc', 'abc', 'translate', table)
1276        self.checkequal('xyz', 'xyz', 'translate', table)
1277        self.checkequal('yz', 'xyz', 'translate', table, 'x')
1278        self.checkequal('yx', 'zyzzx', 'translate', None, 'z')
1279        self.checkequal('zyzzx', 'zyzzx', 'translate', None, '')
1280        self.checkequal('zyzzx', 'zyzzx', 'translate', None)
1281        self.checkraises(ValueError, 'xyz', 'translate', 'too short', 'strip')
1282        self.checkraises(ValueError, 'xyz', 'translate', 'too short')
1283
1284
1285class MixinStrUserStringTest:
1286    # Additional tests that only work with
1287    # 8bit compatible object, i.e. str and UserString
1288
1289    if test_support.have_unicode:
1290        def test_encoding_decoding(self):
1291            codecs = [('rot13', 'uryyb jbeyq'),
1292                      ('base64', 'aGVsbG8gd29ybGQ=\n'),
1293                      ('hex', '68656c6c6f20776f726c64'),
1294                      ('uu', 'begin 666 <data>\n+:&5L;&\\@=V]R;&0 \n \nend\n')]
1295            for encoding, data in codecs:
1296                self.checkequal(data, 'hello world', 'encode', encoding)
1297                self.checkequal('hello world', data, 'decode', encoding)
1298            # zlib is optional, so we make the test optional too...
1299            try:
1300                import zlib
1301            except ImportError:
1302                pass
1303            else:
1304                data = 'x\x9c\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\x01\x00\x1a\x0b\x04]'
1305                self.checkequal(data, 'hello world', 'encode', 'zlib')
1306                self.checkequal('hello world', data, 'decode', 'zlib')
1307
1308            self.checkraises(TypeError, 'xyz', 'decode', 42)
1309            self.checkraises(TypeError, 'xyz', 'encode', 42)
1310
1311
1312class MixinStrUnicodeTest:
1313    # Additional tests that only work with str and unicode.
1314
1315    def test_bug1001011(self):
1316        # Make sure join returns a NEW object for single item sequences
1317        # involving a subclass.
1318        # Make sure that it is of the appropriate type.
1319        # Check the optimisation still occurs for standard objects.
1320        t = self.type2test
1321        class subclass(t):
1322            pass
1323        s1 = subclass("abcd")
1324        s2 = t().join([s1])
1325        self.assertTrue(s1 is not s2)
1326        self.assertTrue(type(s2) is t)
1327
1328        s1 = t("abcd")
1329        s2 = t().join([s1])
1330        self.assertTrue(s1 is s2)
1331
1332        # Should also test mixed-type join.
1333        if t is unicode:
1334            s1 = subclass("abcd")
1335            s2 = "".join([s1])
1336            self.assertTrue(s1 is not s2)
1337            self.assertTrue(type(s2) is t)
1338
1339            s1 = t("abcd")
1340            s2 = "".join([s1])
1341            self.assertTrue(s1 is s2)
1342
1343        elif t is str:
1344            s1 = subclass("abcd")
1345            s2 = u"".join([s1])
1346            self.assertTrue(s1 is not s2)
1347            self.assertTrue(type(s2) is unicode) # promotes!
1348
1349            s1 = t("abcd")
1350            s2 = u"".join([s1])
1351            self.assertTrue(s1 is not s2)
1352            self.assertTrue(type(s2) is unicode) # promotes!
1353
1354        else:
1355            self.fail("unexpected type for MixinStrUnicodeTest %r" % t)
1356