import sys import array import ctypes import struct import unittest from ..ext import array as sdlextarray singlebyteseq = [x for x in range(0x100)] doublebyteseq = [x for x in range(0x10000)] quadbyteseq = [0x00000000, 0x000000FF, 0x0000FF00, 0x0000FFFF, 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00FFFFFF, 0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFFFF0000, 0xFFFF00FF, 0xFFFFFF00, 0xFFFFFFFF ] singlebytebuf = array.array("B", singlebyteseq) doublebytebuf = array.array("H", doublebyteseq) quadbytebuf = array.array("I", quadbyteseq) USHORT_SIZE = struct.calcsize("H") UINT_SIZE = struct.calcsize("I") UBYTE_SIZE = struct.calcsize("B") def create_16b(seq, offset): if sys.byteorder == 'little': return (seq[offset] | seq[offset + 1] << 8) else: return (seq[offset] << 8 | seq[offset + 1]) def create_32b(seq, size, offset): if sys.byteorder == 'little': if size == 1: return (seq[offset] | seq[offset + 1] << 8 | seq[offset + 2] << 16 | seq[offset + 3] << 24) elif size == 2: return (seq[offset] | seq[offset + 1] << 16) else: if size == 1: return (seq[offset] << 24 | seq[offset + 1] << 16 | seq[offset + 2] << 8 | seq[offset + 3]) elif size == 2: return (seq[offset] << 16 | seq[offset + 1]) def create_64b(seq, size, offset): if sys.byteorder == 'little': if size == 1: return (seq[offset] | seq[offset + 1] << 8 | seq[offset + 2] << 16 | seq[offset + 3] << 24 | seq[offset + 4] << 32 | seq[offset + 5] << 40 | seq[offset + 6] << 48 | seq[offset + 7] << 56) elif size == 2: return (seq[offset] | seq[offset + 1] << 16 | seq[offset + 2] << 32 | seq[offset + 3] << 48) elif size == 4: return (seq[offset] | seq[offset + 1] << 32) else: if size == 1: return (seq[offset] << 56 | seq[offset + 1] << 48 | seq[offset + 2] << 40 | seq[offset + 3] << 32 | seq[offset + 4] << 24 | seq[offset + 5] << 16 | seq[offset + 6] << 8 | seq[offset + 7]) elif size == 2: return (seq[offset] << 48 | seq[offset + 1] << 32 | seq[offset + 2] << 16 | seq[offset + 3]) elif size == 4: return (seq[offset] << 32 | seq[offset]) def lobyte16(val): return val & 0x00FF def hibyte16(val): return val >> 8 & 0x00FF def lobytes32(val): return val & 0x0000FFFF def hibytes32(val): return val >> 16 & 0x0000FFFF def ltrbyte32(val, pos): if sys.byteorder == 'little': if pos == 0: return val & 0x000000FF elif pos == 1: return (val & 0x0000FF00) >> 8 elif pos == 2: return (val & 0x00FF0000) >> 16 elif pos == 3: return (val & 0xFF000000) >> 24 else: raise IndexError("invalid position") else: if pos == 3: return (val & 0x000000FF) elif pos == 2: return (val & 0x0000FF00) >> 8 elif pos == 1: return (val & 0x00FF0000) >> 16 elif pos == 0: return (val & 0xFF000000) >> 24 else: raise IndexError("invalid position") class SDL2ExtArrayTest(unittest.TestCase): __tags__ = ["sdl2ext"] def test_to_ctypes(self): for seq, dtype in ((singlebyteseq, ctypes.c_ubyte), (singlebytebuf, ctypes.c_ubyte), (doublebyteseq, ctypes.c_ushort), (doublebytebuf, ctypes.c_ushort), (quadbyteseq, ctypes.c_uint), (quadbytebuf, ctypes.c_uint)): bytebuf, size = sdlextarray.to_ctypes(seq, dtype) self.assertEqual(size, len(seq)) for index, x in enumerate(bytebuf): self.assertEqual(x, seq[index]) def test_CTypesView__singlebytes(self): buf1 = sdlextarray.CTypesView(singlebyteseq, docopy=True) buf2 = sdlextarray.CTypesView(singlebytebuf, docopy=False) for singlebytes, shared in ((buf1, False), (buf2, True)): self.assertIsInstance(singlebytes, sdlextarray.CTypesView) self.assertEqual(singlebytes.is_shared, shared) self.assertEqual(singlebytes.bytesize, len(singlebyteseq)) for index, val in enumerate(singlebytes.to_bytes()): self.assertEqual(val, singlebyteseq[index]) offset = 0 for val in singlebytes.to_uint16(): seqval = create_16b(singlebyteseq, offset) self.assertEqual(val, seqval) offset += 2 offset = 0 for val in singlebytes.to_uint32(): seqval = create_32b(singlebyteseq, 1, offset) self.assertEqual(val, seqval) offset += 4 offset = 0 for val in singlebytes.to_uint64(): seqval = create_64b(singlebyteseq, 1, offset) self.assertEqual(val, seqval) offset += 8 def test_CTypesView__doublebytes(self): buf1 = sdlextarray.CTypesView(doublebyteseq, USHORT_SIZE, docopy=True) buf2 = sdlextarray.CTypesView(doublebytebuf, USHORT_SIZE, docopy=False) for singlebytes, shared in ((buf1, False), (buf2, True)): self.assertIsInstance(singlebytes, sdlextarray.CTypesView) self.assertEqual(singlebytes.is_shared, shared) self.assertEqual(singlebytes.bytesize, len(doublebyteseq) * 2) offset = 0 cnt = 0 for val in singlebytes.to_bytes(): if cnt > 0: self.assertEqual(val, hibyte16(doublebyteseq[offset])) cnt = 0 offset += 1 else: self.assertEqual(val, lobyte16(doublebyteseq[offset])) cnt += 1 offset = 0 for val in singlebytes.to_uint16(): self.assertEqual(val, doublebyteseq[offset]) offset += 1 offset = 0 for val in singlebytes.to_uint32(): seqval = create_32b(doublebyteseq, 2, offset) self.assertEqual(val, seqval) offset += 2 offset = 0 for val in singlebytes.to_uint64(): seqval = create_64b(doublebyteseq, 2, offset) self.assertEqual(val, seqval) offset += 4 def test_CTypesView__quadbytes(self): buf1 = sdlextarray.CTypesView(quadbyteseq, UINT_SIZE, docopy=True) buf2 = sdlextarray.CTypesView(quadbytebuf, UINT_SIZE, docopy=False) for singlebytes, shared in ((buf1, False), (buf2, True)): self.assertIsInstance(singlebytes, sdlextarray.CTypesView) self.assertEqual(singlebytes.is_shared, shared) self.assertEqual(singlebytes.bytesize, len(quadbyteseq) * 4) offset = 0 cnt = 0 for val in singlebytes.to_bytes(): self.assertEqual(val, ltrbyte32(quadbyteseq[offset], cnt)) if cnt == 3: offset += 1 cnt = 0 else: cnt += 1 cnt = 0 offset = 0 for val in singlebytes.to_uint16(): if cnt > 0: self.assertEqual(val, hibytes32(quadbyteseq[offset])) cnt = 0 offset += 1 else: self.assertEqual(val, lobytes32(quadbyteseq[offset])) cnt += 1 offset = 0 for val in singlebytes.to_uint32(): self.assertEqual(val, quadbyteseq[offset]) offset += 1 offset = 0 for val in singlebytes.to_uint64(): seqval = create_64b(quadbyteseq, 4, offset) self.assertEqual(val, seqval) offset += 2 def test_CTypesView__repr__(self): seqs = ((singlebyteseq, UBYTE_SIZE, 1, False), (doublebyteseq, USHORT_SIZE, 2, False), (quadbyteseq, UINT_SIZE, 4, False), (singlebytebuf, UBYTE_SIZE, 1, True), (doublebytebuf, USHORT_SIZE, 2, True), (quadbytebuf, UINT_SIZE, 4, True), ) for seq, size, factor, shared in seqs: buf = sdlextarray.CTypesView(seq, size, not shared) otype = type(seq).__name__ if not shared: otype = 'array' text = "CTypesView(type=%s, bytesize=%d, shared=%s)" % \ (otype, len(seq) * factor, shared) self.assertEqual(text, repr(buf)) def test_MemoryView(self): self.assertRaises(TypeError, sdlextarray.MemoryView, 5, 1, (1,)) self.assertRaises(TypeError, sdlextarray.MemoryView, None, 1, (1,)) source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) for index, val in enumerate(view): self.assertEqual(val, source[index]) view = sdlextarray.MemoryView(source, 1, (2, 7)) word1 = view[0] # "Example" word2 = view[1] # " buffer" self.assertEqual(len(view), 2) self.assertEqual(len(word1), 7) self.assertEqual(len(word2), 7) for index, val in enumerate(word1): self.assertEqual(val, source[index]) for index, val in enumerate(word2): self.assertEqual(val, source[index + 7]) # TODO: more tests def test_MemoryView_ndim_strides(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) self.assertEqual(view.ndim, 1) self.assertEqual(view.strides, (len(source),)) view = sdlextarray.MemoryView(source, 1, (2, 7)) self.assertEqual(view.ndim, 2) self.assertEqual(view.strides, (2, 7)) view = sdlextarray.MemoryView(source, 1, (7, 2)) self.assertEqual(view.ndim, 2) self.assertEqual(view.strides, (7, 2)) view = sdlextarray.MemoryView(source, 1, (2, 2, 2)) self.assertEqual(view.ndim, 3) self.assertEqual(view.strides, (2, 2, 2)) def test_MemoryView_itemsize(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) self.assertEqual(view.itemsize, 1) view = sdlextarray.MemoryView(source, 7, (1, 7)) self.assertEqual(view.itemsize, 7) def test_MemoryView_size(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) self.assertEqual(view.size, len(source)) view = sdlextarray.MemoryView(source, 7, (1, 7)) self.assertEqual(view.size, len(source)) def test_MemoryView_source(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) self.assertEqual(view.source, source) def test_to_tuple(self): ar = (ctypes.c_int * 20)() for i in range(20): ar[i] = i vtuple = sdlextarray.to_tuple(ar) self.assertIsInstance(vtuple, tuple) for index, value in enumerate(vtuple): self.assertEqual(value, ar[index]) def test_to_list(self): ar = (ctypes.c_int * 20)() for i in range(20): ar[i] = i vlist = sdlextarray.to_list(ar) self.assertIsInstance(vlist, list) for index, value in enumerate(vlist): self.assertEqual(value, ar[index]) def test_create_array(self): barr = bytes(bytearray(singlebyteseq)) for i in (1, 2, 4, 8): parr = sdlextarray.create_array(barr, i) self.assertIsInstance(parr, array.array) if i == 1: self.assertEqual(parr[0], 0x0) elif i == 2: self.assertEqual(parr[0], 0x0100) elif i == 4: self.assertEqual(parr[0], 0x03020100) for i in (0, 3, 5, 6, 7, 9, 10, 12, "test", self): self.assertRaises(TypeError, sdlextarray.create_array, barr, i) if __name__ == '__main__': sys.exit(unittest.main())