summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_bytes.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_bytes.py')
-rw-r--r--Lib/test/test_bytes.py137
1 files changed, 116 insertions, 21 deletions
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 3c09141..0a73fcb 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -13,9 +13,11 @@ import functools
import pickle
import tempfile
import unittest
+
import test.support
import test.string_tests
import test.buffer_tests
+from test.support import bigaddrspacetest, MAX_Py_ssize_t
if sys.flags.bytes_warning:
@@ -98,6 +100,14 @@ class BaseBytesTest:
self.assertRaises(TypeError, self.type2test, [0.0])
self.assertRaises(TypeError, self.type2test, [None])
self.assertRaises(TypeError, self.type2test, [C()])
+ self.assertRaises(TypeError, self.type2test, 0, 'ascii')
+ self.assertRaises(TypeError, self.type2test, b'', 'ascii')
+ self.assertRaises(TypeError, self.type2test, 0, errors='ignore')
+ self.assertRaises(TypeError, self.type2test, b'', errors='ignore')
+ self.assertRaises(TypeError, self.type2test, '')
+ self.assertRaises(TypeError, self.type2test, '', errors='ignore')
+ self.assertRaises(TypeError, self.type2test, '', b'ascii')
+ self.assertRaises(TypeError, self.type2test, '', 'ascii', b'ignore')
def test_constructor_value_errors(self):
self.assertRaises(ValueError, self.type2test, [-1])
@@ -111,6 +121,17 @@ class BaseBytesTest:
self.assertRaises(ValueError, self.type2test, [sys.maxsize+1])
self.assertRaises(ValueError, self.type2test, [10**100])
+ @bigaddrspacetest
+ def test_constructor_overflow(self):
+ size = MAX_Py_ssize_t
+ self.assertRaises((OverflowError, MemoryError), self.type2test, size)
+ try:
+ # Should either pass or raise an error (e.g. on debug builds with
+ # additional malloc() overhead), but shouldn't crash.
+ bytearray(size - 4)
+ except (OverflowError, MemoryError):
+ pass
+
def test_compare(self):
b1 = self.type2test([1, 2, 3])
b2 = self.type2test([1, 2, 3])
@@ -288,8 +309,23 @@ class BaseBytesTest:
self.assertEqual(self.type2test(b"").join(lst), b"abc")
self.assertEqual(self.type2test(b"").join(tuple(lst)), b"abc")
self.assertEqual(self.type2test(b"").join(iter(lst)), b"abc")
- self.assertEqual(self.type2test(b".").join([b"ab", b"cd"]), b"ab.cd")
- # XXX more...
+ dot_join = self.type2test(b".:").join
+ self.assertEqual(dot_join([b"ab", b"cd"]), b"ab.:cd")
+ self.assertEqual(dot_join([memoryview(b"ab"), b"cd"]), b"ab.:cd")
+ self.assertEqual(dot_join([b"ab", memoryview(b"cd")]), b"ab.:cd")
+ self.assertEqual(dot_join([bytearray(b"ab"), b"cd"]), b"ab.:cd")
+ self.assertEqual(dot_join([b"ab", bytearray(b"cd")]), b"ab.:cd")
+ # Stress it with many items
+ seq = [b"abc"] * 1000
+ expected = b"abc" + b".:abc" * 999
+ self.assertEqual(dot_join(seq), expected)
+ self.assertRaises(TypeError, self.type2test(b" ").join, None)
+ # Error handling and cleanup when some item in the middle of the
+ # sequence has the wrong type.
+ with self.assertRaises(TypeError):
+ dot_join([bytearray(b"ab"), "cd", b"ef"])
+ with self.assertRaises(TypeError):
+ dot_join([memoryview(b"ab"), "cd", b"ef"])
def test_count(self):
b = self.type2test(b'mississippi')
@@ -519,22 +555,23 @@ class BaseBytesTest:
self.assertEqual(b, q)
def test_iterator_pickling(self):
- for b in b"", b"a", b"abc", b"\xffab\x80", b"\0\0\377\0\0":
- it = itorg = iter(self.type2test(b))
- data = list(self.type2test(b))
- d = pickle.dumps(it)
- it = pickle.loads(d)
- self.assertEqual(type(itorg), type(it))
- self.assertEqual(list(it), data)
-
- it = pickle.loads(d)
- try:
- next(it)
- except StopIteration:
- continue
- d = pickle.dumps(it)
- it = pickle.loads(d)
- self.assertEqual(list(it), data[1:])
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ for b in b"", b"a", b"abc", b"\xffab\x80", b"\0\0\377\0\0":
+ it = itorg = iter(self.type2test(b))
+ data = list(self.type2test(b))
+ d = pickle.dumps(it, proto)
+ it = pickle.loads(d)
+ self.assertEqual(type(itorg), type(it))
+ self.assertEqual(list(it), data)
+
+ it = pickle.loads(d)
+ try:
+ next(it)
+ except StopIteration:
+ continue
+ d = pickle.dumps(it, proto)
+ it = pickle.loads(d)
+ self.assertEqual(list(it), data[1:])
def test_strip(self):
b = self.type2test(b'mississippi')
@@ -686,7 +723,7 @@ class BytesTest(BaseBytesTest, unittest.TestCase):
type2test = bytes
def test_buffer_is_readonly(self):
- fd = os.dup(sys.stdin.fileno())
+ fd = os.open(__file__, os.O_RDONLY)
with open(fd, "rb", buffering=0) as f:
self.assertRaises(TypeError, f.readinto, b"")
@@ -707,6 +744,14 @@ class BytesTest(BaseBytesTest, unittest.TestCase):
def __index__(self):
return 42
self.assertEqual(bytes(A()), b'a')
+ # Issue #24731
+ class A:
+ def __bytes__(self):
+ return OtherBytesSubclass(b'abc')
+ self.assertEqual(bytes(A()), b'abc')
+ self.assertIs(type(bytes(A())), OtherBytesSubclass)
+ self.assertEqual(BytesSubclass(A()), b'abc')
+ self.assertIs(type(BytesSubclass(A())), BytesSubclass)
# Test PyBytes_FromFormat()
def test_from_format(self):
@@ -765,7 +810,7 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
finally:
try:
os.remove(tfn)
- except os.error:
+ except OSError:
pass
def test_reverse(self):
@@ -901,6 +946,31 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
with self.assertRaises(ValueError):
b[3:4] = elem
+ def test_setslice_extend(self):
+ # Exercise the resizing logic (see issue #19087)
+ b = bytearray(range(100))
+ self.assertEqual(list(b), list(range(100)))
+ del b[:10]
+ self.assertEqual(list(b), list(range(10, 100)))
+ b.extend(range(100, 110))
+ self.assertEqual(list(b), list(range(10, 110)))
+
+ def test_fifo_overrun(self):
+ # Test for issue #23985, a buffer overrun when implementing a FIFO
+ # Build Python in pydebug mode for best results.
+ b = bytearray(10)
+ b.pop() # Defeat expanding buffer off-by-one quirk
+ del b[:1] # Advance start pointer without reallocating
+ b += bytes(2) # Append exactly the number of deleted bytes
+ del b # Free memory buffer, allowing pydebug verification
+
+ def test_del_expand(self):
+ # Reducing the size should not expand the buffer (issue #23985)
+ b = bytearray(10)
+ size = sys.getsizeof(b)
+ del b[:1]
+ self.assertLessEqual(sys.getsizeof(b), size)
+
def test_extended_set_del_slice(self):
indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300)
for start in indices:
@@ -968,10 +1038,27 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
for i in range(100):
b += b"x"
alloc = b.__alloc__()
- self.assertTrue(alloc >= len(b))
+ self.assertGreater(alloc, len(b)) # including trailing null byte
if alloc not in seq:
seq.append(alloc)
+ def test_init_alloc(self):
+ b = bytearray()
+ def g():
+ for i in range(1, 100):
+ yield i
+ a = list(b)
+ self.assertEqual(a, list(range(1, len(a)+1)))
+ self.assertEqual(len(b), len(a))
+ self.assertLessEqual(len(b), i)
+ alloc = b.__alloc__()
+ self.assertGreater(alloc, len(b)) # including trailing null byte
+ b.__init__(g())
+ self.assertEqual(list(b), list(range(1, 100)))
+ self.assertEqual(len(b), 99)
+ alloc = b.__alloc__()
+ self.assertGreater(alloc, len(b))
+
def test_extend(self):
orig = b'hello'
a = bytearray(orig)
@@ -1280,6 +1367,11 @@ class BytearrayPEP3137Test(unittest.TestCase,
self.assertEqual(val, newval)
self.assertTrue(val is not newval,
expr+' returned val on a mutable object')
+ sep = self.marshal(b'')
+ newval = sep.join([val])
+ self.assertEqual(val, newval)
+ self.assertIsNot(val, newval)
+
class FixedStringTest(test.string_tests.BaseTest):
@@ -1381,6 +1473,9 @@ class ByteArraySubclass(bytearray):
class BytesSubclass(bytes):
pass
+class OtherBytesSubclass(bytes):
+ pass
+
class ByteArraySubclassTest(SubclassTest, unittest.TestCase):
type2test = bytearray
subclass2test = ByteArraySubclass