123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- """ Testing mio5_utils Cython module
- """
- import sys
- from io import BytesIO
- cStringIO = BytesIO
- import numpy as np
- from numpy.testing import assert_array_equal, assert_equal, assert_
- from pytest import raises as assert_raises
- import scipy.io.matlab._byteordercodes as boc
- import scipy.io.matlab._streams as streams
- import scipy.io.matlab._mio5_params as mio5p
- import scipy.io.matlab._mio5_utils as m5u
- def test_byteswap():
- for val in (
- 1,
- 0x100,
- 0x10000):
- a = np.array(val, dtype=np.uint32)
- b = a.byteswap()
- c = m5u.byteswap_u4(a)
- assert_equal(b.item(), c)
- d = m5u.byteswap_u4(c)
- assert_equal(a.item(), d)
- def _make_tag(base_dt, val, mdtype, sde=False):
- ''' Makes a simple matlab tag, full or sde '''
- base_dt = np.dtype(base_dt)
- bo = boc.to_numpy_code(base_dt.byteorder)
- byte_count = base_dt.itemsize
- if not sde:
- udt = bo + 'u4'
- padding = 8 - (byte_count % 8)
- all_dt = [('mdtype', udt),
- ('byte_count', udt),
- ('val', base_dt)]
- if padding:
- all_dt.append(('padding', 'u1', padding))
- else: # is sde
- udt = bo + 'u2'
- padding = 4-byte_count
- if bo == '<': # little endian
- all_dt = [('mdtype', udt),
- ('byte_count', udt),
- ('val', base_dt)]
- else: # big endian
- all_dt = [('byte_count', udt),
- ('mdtype', udt),
- ('val', base_dt)]
- if padding:
- all_dt.append(('padding', 'u1', padding))
- tag = np.zeros((1,), dtype=all_dt)
- tag['mdtype'] = mdtype
- tag['byte_count'] = byte_count
- tag['val'] = val
- return tag
- def _write_stream(stream, *strings):
- stream.truncate(0)
- stream.seek(0)
- for s in strings:
- stream.write(s)
- stream.seek(0)
- def _make_readerlike(stream, byte_order=boc.native_code):
- class R:
- pass
- r = R()
- r.mat_stream = stream
- r.byte_order = byte_order
- r.struct_as_record = True
- r.uint16_codec = sys.getdefaultencoding()
- r.chars_as_strings = False
- r.mat_dtype = False
- r.squeeze_me = False
- return r
- def test_read_tag():
- # mainly to test errors
- # make reader-like thing
- str_io = BytesIO()
- r = _make_readerlike(str_io)
- c_reader = m5u.VarReader5(r)
- # This works for StringIO but _not_ cStringIO
- assert_raises(OSError, c_reader.read_tag)
- # bad SDE
- tag = _make_tag('i4', 1, mio5p.miINT32, sde=True)
- tag['byte_count'] = 5
- _write_stream(str_io, tag.tobytes())
- assert_raises(ValueError, c_reader.read_tag)
- def test_read_stream():
- tag = _make_tag('i4', 1, mio5p.miINT32, sde=True)
- tag_str = tag.tobytes()
- str_io = cStringIO(tag_str)
- st = streams.make_stream(str_io)
- s = streams._read_into(st, tag.itemsize)
- assert_equal(s, tag.tobytes())
- def test_read_numeric():
- # make reader-like thing
- str_io = cStringIO()
- r = _make_readerlike(str_io)
- # check simplest of tags
- for base_dt, val, mdtype in (('u2', 30, mio5p.miUINT16),
- ('i4', 1, mio5p.miINT32),
- ('i2', -1, mio5p.miINT16)):
- for byte_code in ('<', '>'):
- r.byte_order = byte_code
- c_reader = m5u.VarReader5(r)
- assert_equal(c_reader.little_endian, byte_code == '<')
- assert_equal(c_reader.is_swapped, byte_code != boc.native_code)
- for sde_f in (False, True):
- dt = np.dtype(base_dt).newbyteorder(byte_code)
- a = _make_tag(dt, val, mdtype, sde_f)
- a_str = a.tobytes()
- _write_stream(str_io, a_str)
- el = c_reader.read_numeric()
- assert_equal(el, val)
- # two sequential reads
- _write_stream(str_io, a_str, a_str)
- el = c_reader.read_numeric()
- assert_equal(el, val)
- el = c_reader.read_numeric()
- assert_equal(el, val)
- def test_read_numeric_writeable():
- # make reader-like thing
- str_io = cStringIO()
- r = _make_readerlike(str_io, '<')
- c_reader = m5u.VarReader5(r)
- dt = np.dtype('<u2')
- a = _make_tag(dt, 30, mio5p.miUINT16, 0)
- a_str = a.tobytes()
- _write_stream(str_io, a_str)
- el = c_reader.read_numeric()
- assert_(el.flags.writeable is True)
- def test_zero_byte_string():
- # Tests hack to allow chars of non-zero length, but 0 bytes
- # make reader-like thing
- str_io = cStringIO()
- r = _make_readerlike(str_io, boc.native_code)
- c_reader = m5u.VarReader5(r)
- tag_dt = np.dtype([('mdtype', 'u4'), ('byte_count', 'u4')])
- tag = np.zeros((1,), dtype=tag_dt)
- tag['mdtype'] = mio5p.miINT8
- tag['byte_count'] = 1
- hdr = m5u.VarHeader5()
- # Try when string is 1 length
- hdr.set_dims([1,])
- _write_stream(str_io, tag.tobytes() + b' ')
- str_io.seek(0)
- val = c_reader.read_char(hdr)
- assert_equal(val, ' ')
- # Now when string has 0 bytes 1 length
- tag['byte_count'] = 0
- _write_stream(str_io, tag.tobytes())
- str_io.seek(0)
- val = c_reader.read_char(hdr)
- assert_equal(val, ' ')
- # Now when string has 0 bytes 4 length
- str_io.seek(0)
- hdr.set_dims([4,])
- val = c_reader.read_char(hdr)
- assert_array_equal(val, [' '] * 4)
|