+++ /dev/null
-"""Unit tests for the memoryview\r
-\r
-XXX We need more tests! Some tests are in test_bytes\r
-"""\r
-\r
-import unittest\r
-import sys\r
-import gc\r
-import weakref\r
-import array\r
-from test import test_support\r
-import io\r
-\r
-\r
-class AbstractMemoryTests:\r
- source_bytes = b"abcdef"\r
-\r
- @property\r
- def _source(self):\r
- return self.source_bytes\r
-\r
- @property\r
- def _types(self):\r
- return filter(None, [self.ro_type, self.rw_type])\r
-\r
- def check_getitem_with_type(self, tp):\r
- item = self.getitem_type\r
- b = tp(self._source)\r
- oldrefcount = sys.getrefcount(b)\r
- m = self._view(b)\r
- self.assertEqual(m[0], item(b"a"))\r
- self.assertIsInstance(m[0], bytes)\r
- self.assertEqual(m[5], item(b"f"))\r
- self.assertEqual(m[-1], item(b"f"))\r
- self.assertEqual(m[-6], item(b"a"))\r
- # Bounds checking\r
- self.assertRaises(IndexError, lambda: m[6])\r
- self.assertRaises(IndexError, lambda: m[-7])\r
- self.assertRaises(IndexError, lambda: m[sys.maxsize])\r
- self.assertRaises(IndexError, lambda: m[-sys.maxsize])\r
- # Type checking\r
- self.assertRaises(TypeError, lambda: m[None])\r
- self.assertRaises(TypeError, lambda: m[0.0])\r
- self.assertRaises(TypeError, lambda: m["a"])\r
- m = None\r
- self.assertEqual(sys.getrefcount(b), oldrefcount)\r
-\r
- def test_getitem(self):\r
- for tp in self._types:\r
- self.check_getitem_with_type(tp)\r
-\r
- def test_iter(self):\r
- for tp in self._types:\r
- b = tp(self._source)\r
- m = self._view(b)\r
- self.assertEqual(list(m), [m[i] for i in range(len(m))])\r
-\r
- def test_repr(self):\r
- for tp in self._types:\r
- b = tp(self._source)\r
- m = self._view(b)\r
- self.assertIsInstance(m.__repr__(), str)\r
-\r
- def test_setitem_readonly(self):\r
- if not self.ro_type:\r
- return\r
- b = self.ro_type(self._source)\r
- oldrefcount = sys.getrefcount(b)\r
- m = self._view(b)\r
- def setitem(value):\r
- m[0] = value\r
- self.assertRaises(TypeError, setitem, b"a")\r
- self.assertRaises(TypeError, setitem, 65)\r
- self.assertRaises(TypeError, setitem, memoryview(b"a"))\r
- m = None\r
- self.assertEqual(sys.getrefcount(b), oldrefcount)\r
-\r
- def test_setitem_writable(self):\r
- if not self.rw_type:\r
- return\r
- tp = self.rw_type\r
- b = self.rw_type(self._source)\r
- oldrefcount = sys.getrefcount(b)\r
- m = self._view(b)\r
- m[0] = tp(b"0")\r
- self._check_contents(tp, b, b"0bcdef")\r
- m[1:3] = tp(b"12")\r
- self._check_contents(tp, b, b"012def")\r
- m[1:1] = tp(b"")\r
- self._check_contents(tp, b, b"012def")\r
- m[:] = tp(b"abcdef")\r
- self._check_contents(tp, b, b"abcdef")\r
-\r
- # Overlapping copies of a view into itself\r
- m[0:3] = m[2:5]\r
- self._check_contents(tp, b, b"cdedef")\r
- m[:] = tp(b"abcdef")\r
- m[2:5] = m[0:3]\r
- self._check_contents(tp, b, b"ababcf")\r
-\r
- def setitem(key, value):\r
- m[key] = tp(value)\r
- # Bounds checking\r
- self.assertRaises(IndexError, setitem, 6, b"a")\r
- self.assertRaises(IndexError, setitem, -7, b"a")\r
- self.assertRaises(IndexError, setitem, sys.maxsize, b"a")\r
- self.assertRaises(IndexError, setitem, -sys.maxsize, b"a")\r
- # Wrong index/slice types\r
- self.assertRaises(TypeError, setitem, 0.0, b"a")\r
- self.assertRaises(TypeError, setitem, (0,), b"a")\r
- self.assertRaises(TypeError, setitem, "a", b"a")\r
- # Trying to resize the memory object\r
- self.assertRaises(ValueError, setitem, 0, b"")\r
- self.assertRaises(ValueError, setitem, 0, b"ab")\r
- self.assertRaises(ValueError, setitem, slice(1,1), b"a")\r
- self.assertRaises(ValueError, setitem, slice(0,2), b"a")\r
-\r
- m = None\r
- self.assertEqual(sys.getrefcount(b), oldrefcount)\r
-\r
- def test_delitem(self):\r
- for tp in self._types:\r
- b = tp(self._source)\r
- m = self._view(b)\r
- with self.assertRaises(TypeError):\r
- del m[1]\r
- with self.assertRaises(TypeError):\r
- del m[1:4]\r
-\r
- def test_tobytes(self):\r
- for tp in self._types:\r
- m = self._view(tp(self._source))\r
- b = m.tobytes()\r
- # This calls self.getitem_type() on each separate byte of b"abcdef"\r
- expected = b"".join(\r
- self.getitem_type(c) for c in b"abcdef")\r
- self.assertEqual(b, expected)\r
- self.assertIsInstance(b, bytes)\r
-\r
- def test_tolist(self):\r
- for tp in self._types:\r
- m = self._view(tp(self._source))\r
- l = m.tolist()\r
- self.assertEqual(l, map(ord, b"abcdef"))\r
-\r
- def test_compare(self):\r
- # memoryviews can compare for equality with other objects\r
- # having the buffer interface.\r
- for tp in self._types:\r
- m = self._view(tp(self._source))\r
- for tp_comp in self._types:\r
- self.assertTrue(m == tp_comp(b"abcdef"))\r
- self.assertFalse(m != tp_comp(b"abcdef"))\r
- self.assertFalse(m == tp_comp(b"abcde"))\r
- self.assertTrue(m != tp_comp(b"abcde"))\r
- self.assertFalse(m == tp_comp(b"abcde1"))\r
- self.assertTrue(m != tp_comp(b"abcde1"))\r
- self.assertTrue(m == m)\r
- self.assertTrue(m == m[:])\r
- self.assertTrue(m[0:6] == m[:])\r
- self.assertFalse(m[0:5] == m)\r
-\r
- # Comparison with objects which don't support the buffer API\r
- self.assertFalse(m == u"abcdef")\r
- self.assertTrue(m != u"abcdef")\r
- self.assertFalse(u"abcdef" == m)\r
- self.assertTrue(u"abcdef" != m)\r
-\r
- # Unordered comparisons are unimplemented, and therefore give\r
- # arbitrary results (they raise a TypeError in py3k)\r
-\r
- def check_attributes_with_type(self, tp):\r
- m = self._view(tp(self._source))\r
- self.assertEqual(m.format, self.format)\r
- self.assertIsInstance(m.format, str)\r
- self.assertEqual(m.itemsize, self.itemsize)\r
- self.assertEqual(m.ndim, 1)\r
- self.assertEqual(m.shape, (6,))\r
- self.assertEqual(len(m), 6)\r
- self.assertEqual(m.strides, (self.itemsize,))\r
- self.assertEqual(m.suboffsets, None)\r
- return m\r
-\r
- def test_attributes_readonly(self):\r
- if not self.ro_type:\r
- return\r
- m = self.check_attributes_with_type(self.ro_type)\r
- self.assertEqual(m.readonly, True)\r
-\r
- def test_attributes_writable(self):\r
- if not self.rw_type:\r
- return\r
- m = self.check_attributes_with_type(self.rw_type)\r
- self.assertEqual(m.readonly, False)\r
-\r
- # Disabled: unicode uses the old buffer API in 2.x\r
-\r
- #def test_getbuffer(self):\r
- ## Test PyObject_GetBuffer() on a memoryview object.\r
- #for tp in self._types:\r
- #b = tp(self._source)\r
- #oldrefcount = sys.getrefcount(b)\r
- #m = self._view(b)\r
- #oldviewrefcount = sys.getrefcount(m)\r
- #s = unicode(m, "utf-8")\r
- #self._check_contents(tp, b, s.encode("utf-8"))\r
- #self.assertEqual(sys.getrefcount(m), oldviewrefcount)\r
- #m = None\r
- #self.assertEqual(sys.getrefcount(b), oldrefcount)\r
-\r
- def test_gc(self):\r
- for tp in self._types:\r
- if not isinstance(tp, type):\r
- # If tp is a factory rather than a plain type, skip\r
- continue\r
-\r
- class MySource(tp):\r
- pass\r
- class MyObject:\r
- pass\r
-\r
- # Create a reference cycle through a memoryview object\r
- b = MySource(tp(b'abc'))\r
- m = self._view(b)\r
- o = MyObject()\r
- b.m = m\r
- b.o = o\r
- wr = weakref.ref(o)\r
- b = m = o = None\r
- # The cycle must be broken\r
- gc.collect()\r
- self.assertTrue(wr() is None, wr())\r
-\r
- def test_writable_readonly(self):\r
- # Issue #10451: memoryview incorrectly exposes a readonly\r
- # buffer as writable causing a segfault if using mmap\r
- tp = self.ro_type\r
- if tp is None:\r
- return\r
- b = tp(self._source)\r
- m = self._view(b)\r
- i = io.BytesIO(b'ZZZZ')\r
- self.assertRaises(TypeError, i.readinto, m)\r
-\r
-# Variations on source objects for the buffer: bytes-like objects, then arrays\r
-# with itemsize > 1.\r
-# NOTE: support for multi-dimensional objects is unimplemented.\r
-\r
-class BaseBytesMemoryTests(AbstractMemoryTests):\r
- ro_type = bytes\r
- rw_type = bytearray\r
- getitem_type = bytes\r
- itemsize = 1\r
- format = 'B'\r
-\r
-# Disabled: array.array() does not support the new buffer API in 2.x\r
-\r
-#class BaseArrayMemoryTests(AbstractMemoryTests):\r
- #ro_type = None\r
- #rw_type = lambda self, b: array.array('i', map(ord, b))\r
- #getitem_type = lambda self, b: array.array('i', map(ord, b)).tostring()\r
- #itemsize = array.array('i').itemsize\r
- #format = 'i'\r
-\r
- #def test_getbuffer(self):\r
- ## XXX Test should be adapted for non-byte buffers\r
- #pass\r
-\r
- #def test_tolist(self):\r
- ## XXX NotImplementedError: tolist() only supports byte views\r
- #pass\r
-\r
-\r
-# Variations on indirection levels: memoryview, slice of memoryview,\r
-# slice of slice of memoryview.\r
-# This is important to test allocation subtleties.\r
-\r
-class BaseMemoryviewTests:\r
- def _view(self, obj):\r
- return memoryview(obj)\r
-\r
- def _check_contents(self, tp, obj, contents):\r
- self.assertEqual(obj, tp(contents))\r
-\r
-class BaseMemorySliceTests:\r
- source_bytes = b"XabcdefY"\r
-\r
- def _view(self, obj):\r
- m = memoryview(obj)\r
- return m[1:7]\r
-\r
- def _check_contents(self, tp, obj, contents):\r
- self.assertEqual(obj[1:7], tp(contents))\r
-\r
- def test_refs(self):\r
- for tp in self._types:\r
- m = memoryview(tp(self._source))\r
- oldrefcount = sys.getrefcount(m)\r
- m[1:2]\r
- self.assertEqual(sys.getrefcount(m), oldrefcount)\r
-\r
-class BaseMemorySliceSliceTests:\r
- source_bytes = b"XabcdefY"\r
-\r
- def _view(self, obj):\r
- m = memoryview(obj)\r
- return m[:7][1:]\r
-\r
- def _check_contents(self, tp, obj, contents):\r
- self.assertEqual(obj[1:7], tp(contents))\r
-\r
-\r
-# Concrete test classes\r
-\r
-class BytesMemoryviewTest(unittest.TestCase,\r
- BaseMemoryviewTests, BaseBytesMemoryTests):\r
-\r
- def test_constructor(self):\r
- for tp in self._types:\r
- ob = tp(self._source)\r
- self.assertTrue(memoryview(ob))\r
- self.assertTrue(memoryview(object=ob))\r
- self.assertRaises(TypeError, memoryview)\r
- self.assertRaises(TypeError, memoryview, ob, ob)\r
- self.assertRaises(TypeError, memoryview, argument=ob)\r
- self.assertRaises(TypeError, memoryview, ob, argument=True)\r
-\r
-#class ArrayMemoryviewTest(unittest.TestCase,\r
- #BaseMemoryviewTests, BaseArrayMemoryTests):\r
-\r
- #def test_array_assign(self):\r
- ## Issue #4569: segfault when mutating a memoryview with itemsize != 1\r
- #a = array.array('i', range(10))\r
- #m = memoryview(a)\r
- #new_a = array.array('i', range(9, -1, -1))\r
- #m[:] = new_a\r
- #self.assertEqual(a, new_a)\r
-\r
-\r
-class BytesMemorySliceTest(unittest.TestCase,\r
- BaseMemorySliceTests, BaseBytesMemoryTests):\r
- pass\r
-\r
-#class ArrayMemorySliceTest(unittest.TestCase,\r
- #BaseMemorySliceTests, BaseArrayMemoryTests):\r
- #pass\r
-\r
-class BytesMemorySliceSliceTest(unittest.TestCase,\r
- BaseMemorySliceSliceTests, BaseBytesMemoryTests):\r
- pass\r
-\r
-#class ArrayMemorySliceSliceTest(unittest.TestCase,\r
- #BaseMemorySliceSliceTests, BaseArrayMemoryTests):\r
- #pass\r
-\r
-\r
-def test_main():\r
- test_support.run_unittest(__name__)\r
-\r
-if __name__ == "__main__":\r
- test_main()\r