Compare commits

...
Sign in to create a new pull request.

6 commits

Author SHA1 Message Date
jevans
18aaa983f7 Refactored warnings, no warnings/failures on mac. 2014-08-25 20:00:08 -04:00
jevans
d00f84b6eb moved test_exceeded_box_length into test_glymur_warnings 2014-08-21 19:48:26 -04:00
jevans
ddf17a9d18 Removed all tests from test_opj_suite_warn.
Now located in test_glymur_warnings and test_opj_suite_dump.
2014-08-21 19:29:08 -04:00
jevans
701aa3ba95 Starting to clearly separate warning testing from any other testing. 2014-08-21 08:44:20 -04:00
jevans
7e52996cc8 Using 3.x warning infrastructure exclusively. 2014-08-18 19:55:00 -04:00
John Evans
61126d6a8b Using 3.x warning infrastructure exclusively. 2014-08-17 19:03:29 -04:00
8 changed files with 516 additions and 504 deletions

View file

@ -202,7 +202,7 @@ class Codestream(object):
msg = 'Invalid marker id encountered at byte {0:d} ' msg = 'Invalid marker id encountered at byte {0:d} '
msg += 'in codestream: "0x{1:x}"' msg += 'in codestream: "0x{1:x}"'
msg = msg.format(self._offset, self._marker_id) msg = msg.format(self._offset, self._marker_id)
warnings.warn(msg) warnings.warn(msg, UserWarning)
break break
self.segment.append(segment) self.segment.append(segment)

View file

@ -1,100 +0,0 @@
"""
Test suite for codestream parsing.
"""
# unittest doesn't work well with R0904.
# pylint: disable=R0904
# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2
# pylint: disable=E1101
import os
import struct
import sys
import tempfile
import unittest
import warnings
from glymur import Jp2k
import glymur
from .fixtures import opj_data_file, OPJ_DATA_ROOT
@unittest.skipIf(sys.platform.startswith('linux'), 'warnings failing on linux')
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestCodestreamOpjDataWarnings(unittest.TestCase):
"""Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT"""
def test_bad_rsiz(self):
"""Should warn if RSIZ is bad. Issue196"""
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
j = Jp2k(filename)
self.assertEqual(len(w), 3)
self.assertTrue(issubclass(w[0].category, UserWarning))
self.assertTrue('Invalid profile' in str(w[0].message))
def test_bad_wavelet_transform(self):
"""Should warn if wavelet transform is bad. Issue195"""
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
j = Jp2k(filename)
self.assertTrue(issubclass(w[0].category, UserWarning))
self.assertTrue('Invalid wavelet transform' in str(w[0].message))
def test_invalid_progression_order(self):
"""Should still be able to parse even if prog order is invalid."""
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
Jp2k(jfile)
self.assertTrue(issubclass(w[0].category, UserWarning))
self.assertTrue('Invalid progression order' in str(w[0].message))
def test_tile_height_is_zero(self):
"""Zero tile height should not cause an exception."""
filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
Jp2k(filename)
self.assertTrue(issubclass(w[0].category, UserWarning))
self.assertTrue('Invalid tile dimensions' in str(w[0].message))
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_unknown_marker_segment(self):
"""Should warn for an unknown marker."""
# Let's inject a marker segment whose marker does not appear to
# be valid. We still parse the file, but warn about the offending
# marker.
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
with open(filename, 'rb') as ifile:
# Everything up until the first QCD marker.
read_buffer = ifile.read(45)
tfile.write(read_buffer)
# Write the new marker segment, 0xff79 = 65401
read_buffer = struct.pack('>HHB', int(65401), int(3), int(0))
tfile.write(read_buffer)
# Get the rest of the input file.
read_buffer = ifile.read()
tfile.write(read_buffer)
tfile.flush()
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
codestream = Jp2k(tfile.name).get_codestream()
self.assertTrue(issubclass(w[0].category, UserWarning))
self.assertTrue('Unrecognized marker' in str(w[0].message))
self.assertEqual(codestream.segment[2].marker_id, '0xff79')
self.assertEqual(codestream.segment[2].length, 3)
self.assertEqual(codestream.segment[2].data, b'\x00')
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1,210 @@
"""
Test suite for warnings issued by glymur.
"""
# unittest doesn't work well with R0904.
# pylint: disable=R0904
# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2
# pylint: disable=E1101
import os
import re
import struct
import sys
import tempfile
import unittest
import warnings
from glymur import Jp2k
import glymur
from .fixtures import opj_data_file, OPJ_DATA_ROOT
@unittest.skipIf(sys.hexversion < 0x03030000,
"assertWarn methods introduced in 3.x")
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestWarnings(unittest.TestCase):
"""Test suite for warnings issued by glymur."""
def test_exceeded_box_length(self):
"""
should warn if reading past end of a box
Verify that a warning is issued if we read past the end of a box
This file has a palette (pclr) box whose length is impossibly
short.
"""
infile = os.path.join(OPJ_DATA_ROOT,
'input/nonregression/mem-b2ace68c-1381.jp2')
regex = re.compile(r'''Encountered\san\sunrecoverable\sValueError\s
while\sparsing\sa\spclr\sbox\sat\sbyte\soffset\s
\d+\.\s+The\soriginal\serror\smessage\swas\s
"total\ssize\sof\snew\sarray\smust\sbe\s
unchanged"''',
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(infile)
def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self):
"""
Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it
really does deserve a warning.
"""
relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2'
jfile = opj_data_file(relpath)
regex = re.compile(r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""",
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(jfile)
def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self):
"""
Has an invalid number of resolutions.
"""
lst = ['input', 'nonregression',
'gdal_fuzzer_unchecked_numresolutions.jp2']
jfile = opj_data_file('/'.join(lst))
regex = re.compile(r"""Invalid\snumber\sof\sresolutions\s
\(\d+\)\.""",
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(jfile)
@unittest.skipIf(re.match("1.5|2.0.0", glymur.version.openjpeg_version),
"Test not passing on 1.5.x, not introduced until 2.x")
def test_NR_gdal_fuzzer_check_number_of_tiles(self):
"""
Has an impossible tiling setup.
"""
lst = ['input', 'nonregression',
'gdal_fuzzer_check_number_of_tiles.jp2']
jfile = opj_data_file('/'.join(lst))
regex = re.compile(r"""Invalid\snumber\sof\stiles\s
\(\d+\)\.""",
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(jfile)
def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self):
"""
Invalid subsampling value.
"""
lst = ['input', 'nonregression', 'gdal_fuzzer_check_comp_dx_dy.jp2']
jfile = opj_data_file('/'.join(lst))
regex = re.compile(r"""Invalid\ssubsampling\svalue\sfor\scomponent\s
\d+:\s+
dx=\d+,\s*dy=\d+""",
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(jfile)
def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self):
lst = ['input', 'nonregression',
'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2']
jfile = opj_data_file('/'.join(lst))
regex = re.compile(r"""Invalid\scomponent\snumber\s\(\d+\),\s
number\sof\scomponents\sis\sonly\s\d+""",
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(jfile)
def test_NR_broken_jp2_dump(self):
"""
The colr box has a ridiculously incorrect box length.
"""
jfile = opj_data_file('input/nonregression/broken.jp2')
regex = re.compile(r'''b'colr'\sbox\shas\sincorrect\sbox\slength\s
\(\d+\)''',
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
jp2 = Jp2k(jfile)
def test_NR_broken2_jp2_dump(self):
"""
Invalid marker ID on codestream.
"""
jfile = opj_data_file('input/nonregression/broken2.jp2')
regex = re.compile(r'''Invalid\smarker\sid\sencountered\sat\sbyte\s
\d+\sin\scodestream:\s*"0x[a-fA-F0-9]{4}"''',
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(jfile)
def test_NR_broken4_jp2_dump(self):
"""
Has an invalid marker in the main header
"""
jfile = opj_data_file('input/nonregression/broken4.jp2')
regex = r'Invalid marker id encountered at byte \d+ in codestream'
with self.assertWarnsRegex(UserWarning, regex):
jp2 = Jp2k(jfile)
@unittest.skipIf(sys.maxsize < 2**32, 'Do not run on 32-bit platforms')
def test_NR_broken3_jp2_dump(self):
"""
Has an impossibly large box length.
The file in question here has a colr box with an erroneous box
length of over 1GB. Don't run it on 32-bit platforms.
"""
jfile = opj_data_file('input/nonregression/broken3.jp2')
regex = re.compile(r'''b'colr'\sbox\shas\sincorrect\sbox\slength\s
\(\d+\)''', re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):
Jp2k(jfile)
def test_bad_rsiz(self):
"""Should warn if RSIZ is bad. Issue196"""
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
Jp2k(filename)
def test_bad_wavelet_transform(self):
"""Should warn if wavelet transform is bad. Issue195"""
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
with self.assertWarnsRegex(UserWarning, 'Invalid wavelet transform'):
Jp2k(filename)
def test_invalid_progression_order(self):
"""Should still be able to parse even if prog order is invalid."""
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
with self.assertWarnsRegex(UserWarning, 'Invalid progression order'):
Jp2k(jfile)
def test_tile_height_is_zero(self):
"""Zero tile height should not cause an exception."""
filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2')
with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'):
Jp2k(filename)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_unknown_marker_segment(self):
"""Should warn for an unknown marker."""
# Let's inject a marker segment whose marker does not appear to
# be valid. We still parse the file, but warn about the offending
# marker.
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
with open(filename, 'rb') as ifile:
# Everything up until the first QCD marker.
read_buffer = ifile.read(45)
tfile.write(read_buffer)
# Write the new marker segment, 0xff79 = 65401
read_buffer = struct.pack('>HHB', int(65401), int(3), int(0))
tfile.write(read_buffer)
# Get the rest of the input file.
read_buffer = ifile.read()
tfile.write(read_buffer)
tfile.flush()
with self.assertWarnsRegex(UserWarning, 'Unrecognized marker'):
codestream = Jp2k(tfile.name).get_codestream()
if __name__ == "__main__":
unittest.main()

View file

@ -287,6 +287,132 @@ class TestSuite(unittest.TestCase):
jpdata = jp2k.read() jpdata = jp2k.read()
self.assertEqual(jpdata.shape, (512, 768, 3)) self.assertEqual(jpdata.shape, (512, 768, 3))
def test_NR_broken_jp2_dump(self):
jfile = opj_data_file('input/nonregression/broken.jp2')
with warnings.catch_warnings():
# colr box has bad length.
warnings.simplefilter("ignore")
jp2 = Jp2k(jfile)
ids = [box.box_id for box in jp2.box]
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
ids = [box.box_id for box in jp2.box[2].box]
self.assertEqual(ids, ['ihdr', 'colr'])
# Signature box. Check for corruption.
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
# File type box.
self.assertEqual(jp2.box[1].brand, 'jp2 ')
self.assertEqual(jp2.box[1].minor_version, 0)
self.assertEqual(jp2.box[1].compatibility_list[0], 'jp2 ')
# Jp2 Header
# Image header
self.assertEqual(jp2.box[2].box[0].height, 152)
self.assertEqual(jp2.box[2].box[0].width, 203)
self.assertEqual(jp2.box[2].box[0].num_components, 3)
self.assertEqual(jp2.box[2].box[0].bits_per_component, 8)
self.assertEqual(jp2.box[2].box[0].signed, False)
self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
# Jp2 Header
# Colour specification
self.assertEqual(jp2.box[2].box[1].method,
glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(jp2.box[2].box[1].precedence, 0)
self.assertEqual(jp2.box[2].box[1].approximation, 0) # not allowed?
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
c = jp2.box[3].main_header
ids = [x.marker_id for x in c.segment]
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
self.assertEqual(ids, expected)
# SIZ: Image and tile size
# Profile:
self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size
self.assertEqual(c.segment[1].xsiz, 203)
self.assertEqual(c.segment[1].ysiz, 152)
# Reference grid offset
self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size
self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), (203, 152))
# Tile offset
self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0))
# bitdepth
self.assertEqual(c.segment[1].bitdepth, (8, 8, 8))
# signed
self.assertEqual(c.segment[1].signed, (False, False, False))
# subsampling
self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3)
# COM: comment
# Registration
self.assertEqual(c.segment[2].rcme, glymur.core.RCME_ISO_8859_1)
# Comment value
self.assertEqual(c.segment[2].ccme.decode('latin-1'),
"Creator: JasPer Version 1.701.0")
# COD: Coding style default
self.assertFalse(c.segment[3].scod & 2) # no sop
self.assertFalse(c.segment[3].scod & 4) # no eph
self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[3].layers, 1) # layers = 1
self.assertEqual(c.segment[3].spcod[3], 1) # mct
self.assertEqual(c.segment[3].spcod[4], 5) # level
self.assertEqual(tuple(c.segment[3].code_block_size),
(64, 64)) # cblk
# Selective arithmetic coding bypass
self.assertFalse(c.segment[3].spcod[7] & 0x01)
# Reset context probabilities
self.assertFalse(c.segment[3].spcod[7] & 0x02)
# Termination on each coding pass
self.assertFalse(c.segment[3].spcod[7] & 0x04)
# Vertically causal context
self.assertFalse(c.segment[3].spcod[7] & 0x08)
# Predictable termination
self.assertFalse(c.segment[3].spcod[7] & 0x0010)
# Segmentation symbols
self.assertFalse(c.segment[3].spcod[7] & 0x0020)
self.assertEqual(c.segment[3].spcod[8],
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[3].spcod), 9)
# QCD: Quantization default
self.assertEqual(c.segment[4].sqcd & 0x1f, 0)
self.assertEqual(c.segment[4].guard_bits, 2)
self.assertEqual(c.segment[4].mantissa, [0] * 16)
self.assertEqual(c.segment[4].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[5].cqcc, 1)
self.assertEqual(c.segment[5].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[5].mantissa, [0] * 16)
self.assertEqual(c.segment[5].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[6].cqcc, 2)
self.assertEqual(c.segment[6].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[6].mantissa, [0] * 16)
self.assertEqual(c.segment[6].exponent,
[8] + [9, 9, 10] * 5)
def test_NR_DEC_Bretagne2_j2k_1_decode(self): def test_NR_DEC_Bretagne2_j2k_1_decode(self):
jfile = opj_data_file('input/nonregression/Bretagne2.j2k') jfile = opj_data_file('input/nonregression/Bretagne2.j2k')
jp2 = Jp2k(jfile) jp2 = Jp2k(jfile)

View file

@ -52,6 +52,171 @@ class TestSuiteDump(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self):
"""
Has an 'XML ' box instead of 'xml '. Just verify we can read it.
"""
relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2'
jfile = opj_data_file(relpath)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
j = Jp2k(jfile)
d = j.read()
self.assertTrue(True)
def test_NR_broken4_jp2_dump(self):
jfile = opj_data_file('input/nonregression/broken4.jp2')
with warnings.catch_warnings():
warnings.simplefilter("ignore")
jp2 = Jp2k(jfile)
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
@unittest.skipIf(sys.maxsize < 2**32, 'Do not run on 32-bit platforms')
def test_NR_broken3_jp2_dump(self):
"""
NR_broken3_jp2_dump
The file in question here has a colr box with an erroneous box
length of over 1GB. Don't run it on 32-bit platforms.
"""
jfile = opj_data_file('input/nonregression/broken3.jp2')
with warnings.catch_warnings():
# Bad box length.
warnings.simplefilter("ignore")
jp2 = Jp2k(jfile)
ids = [box.box_id for box in jp2.box]
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
ids = [box.box_id for box in jp2.box[2].box]
self.assertEqual(ids, ['ihdr', 'colr'])
# Signature box. Check for corruption.
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
# File type box.
self.assertEqual(jp2.box[1].brand, 'jp2 ')
self.assertEqual(jp2.box[1].minor_version, 0)
self.assertEqual(jp2.box[1].compatibility_list[0], 'jp2 ')
# Jp2 Header
# Image header
self.assertEqual(jp2.box[2].box[0].height, 152)
self.assertEqual(jp2.box[2].box[0].width, 203)
self.assertEqual(jp2.box[2].box[0].num_components, 3)
self.assertEqual(jp2.box[2].box[0].bits_per_component, 8)
self.assertEqual(jp2.box[2].box[0].signed, False)
self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
# Jp2 Header
# Colour specification
self.assertEqual(jp2.box[2].box[1].method,
glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(jp2.box[2].box[1].precedence, 0)
self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
c = jp2.box[3].main_header
ids = [x.marker_id for x in c.segment]
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
self.assertEqual(ids, expected)
# SIZ: Image and tile size
# Profile:
self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size
self.assertEqual(c.segment[1].xsiz, 203)
self.assertEqual(c.segment[1].ysiz, 152)
# Reference grid offset
self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size
self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), (203, 152))
# Tile offset
self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0))
# bitdepth
self.assertEqual(c.segment[1].bitdepth, (8, 8, 8))
# signed
self.assertEqual(c.segment[1].signed, (False, False, False))
# subsampling
self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3)
# COM: comment
# Registration
self.assertEqual(c.segment[2].rcme, glymur.core.RCME_ISO_8859_1)
# Comment value
self.assertEqual(c.segment[2].ccme.decode('latin-1'),
"Creator: JasPer Vers)on 1.701.0")
# COD: Coding style default
self.assertFalse(c.segment[3].scod & 2) # no sop
self.assertFalse(c.segment[3].scod & 4) # no eph
self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[3].layers, 1) # layers = 1
self.assertEqual(c.segment[3].spcod[3], 1) # mct
self.assertEqual(c.segment[3].spcod[4], 5) # level
self.assertEqual(tuple(c.segment[3].code_block_size),
(64, 64)) # cblk
# Selective arithmetic coding bypass
self.assertFalse(c.segment[3].spcod[7] & 0x01)
# Reset context probabilities
self.assertFalse(c.segment[3].spcod[7] & 0x02)
# Termination on each coding pass
self.assertFalse(c.segment[3].spcod[7] & 0x04)
# Vertically causal context
self.assertFalse(c.segment[3].spcod[7] & 0x08)
# Predictable termination
self.assertFalse(c.segment[3].spcod[7] & 0x0010)
# Segmentation symbols
self.assertFalse(c.segment[3].spcod[7] & 0x0020)
self.assertEqual(c.segment[3].spcod[8],
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[3].spcod), 9)
# QCD: Quantization default
self.assertEqual(c.segment[4].sqcd & 0x1f, 0)
self.assertEqual(c.segment[4].guard_bits, 2)
self.assertEqual(c.segment[4].mantissa, [0] * 16)
self.assertEqual(c.segment[4].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[5].cqcc, 1)
self.assertEqual(c.segment[5].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[5].mantissa, [0] * 16)
self.assertEqual(c.segment[5].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[6].cqcc, 2)
self.assertEqual(c.segment[6].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[6].mantissa, [0] * 16)
self.assertEqual(c.segment[6].exponent,
[8] + [9, 9, 10] * 5)
def test_NR_broken2_jp2_dump(self):
"""
Invalid marker ID in the codestream.
"""
jfile = opj_data_file('input/nonregression/broken2.jp2')
with warnings.catch_warnings():
# Invalid marker ID on codestream.
warnings.simplefilter("ignore")
jp2 = Jp2k(jfile)
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
def test_NR_file409752(self): def test_NR_file409752(self):
jfile = opj_data_file('input/nonregression/file409752.jp2') jfile = opj_data_file('input/nonregression/file409752.jp2')
jp2 = Jp2k(jfile) jp2 = Jp2k(jfile)
@ -4594,8 +4759,7 @@ class TestSuiteDump(unittest.TestCase):
lst = ['input', 'nonregression', 'issue188_beach_64bitsbox.jp2'] lst = ['input', 'nonregression', 'issue188_beach_64bitsbox.jp2']
jfile = opj_data_file('/'.join(lst)) jfile = opj_data_file('/'.join(lst))
with warnings.catch_warnings(): with warnings.catch_warnings():
# There's a warning for an unknown box. We explicitly test for # There's a warning for an unknown box.
# that down below.
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
jp2 = Jp2k(jfile) jp2 = Jp2k(jfile)

View file

@ -83,7 +83,7 @@ class TestSuiteNegative(unittest.TestCase):
relpath = 'input/nonregression/illegalcolortransform.j2k' relpath = 'input/nonregression/illegalcolortransform.j2k'
jfile = opj_data_file(relpath) jfile = opj_data_file(relpath)
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings():
warnings.simplefilter('ignore') warnings.simplefilter('ignore')
codestream = jp2k.get_codestream(header_only=False) codestream = jp2k.get_codestream(header_only=False)
@ -119,17 +119,6 @@ class TestSuiteNegative(unittest.TestCase):
with self.assertRaises(IOError): with self.assertRaises(IOError):
j.write(data, cbsize=(2, 2048)) j.write(data, cbsize=(2, 2048))
def test_exceeded_box(self):
"""should warn if reading past end of a box"""
# Verify that a warning is issued if we read past the end of a box
# This file has a palette (pclr) box whose length is impossibly
# short.
infile = os.path.join(OPJ_DATA_ROOT,
'input/nonregression/mem-b2ace68c-1381.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
Jp2k(infile)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_precinct_size_not_p2(self): def test_precinct_size_not_p2(self):
"""precinct sizes should be powers of two.""" """precinct sizes should be powers of two."""

View file

@ -1,376 +0,0 @@
"""
The tests defined here roughly correspond to what is in the OpenJPEG test
suite.
"""
# Some test names correspond with openjpeg tests. Long names are ok in this
# case.
# pylint: disable=C0103
# All of these tests correspond to tests in openjpeg, so no docstring is really
# needed.
# pylint: disable=C0111
# This module is very long, cannot be helped.
# pylint: disable=C0302
# unittest fools pylint with "too many public methods"
# pylint: disable=R0904
# Some tests use numpy test infrastructure, which means the tests never
# reference "self", so pylint claims it should be a function. No, no, no.
# pylint: disable=R0201
# Many tests are pretty long and that can't be helped.
# pylint: disable=R0915
# asserWarns introduced in python 3.2 (python2.7/pylint issue)
# pylint: disable=E1101
import re
import sys
import unittest
import warnings
import numpy as np
from glymur import Jp2k
import glymur
from .fixtures import OPJ_DATA_ROOT
from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestSuiteDumpWarnings(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_NR_broken_jp2_dump(self):
jfile = opj_data_file('input/nonregression/broken.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
# colr box has bad length.
jp2 = Jp2k(jfile)
ids = [box.box_id for box in jp2.box]
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
ids = [box.box_id for box in jp2.box[2].box]
self.assertEqual(ids, ['ihdr', 'colr'])
# Signature box. Check for corruption.
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
# File type box.
self.assertEqual(jp2.box[1].brand, 'jp2 ')
self.assertEqual(jp2.box[1].minor_version, 0)
self.assertEqual(jp2.box[1].compatibility_list[0], 'jp2 ')
# Jp2 Header
# Image header
self.assertEqual(jp2.box[2].box[0].height, 152)
self.assertEqual(jp2.box[2].box[0].width, 203)
self.assertEqual(jp2.box[2].box[0].num_components, 3)
self.assertEqual(jp2.box[2].box[0].bits_per_component, 8)
self.assertEqual(jp2.box[2].box[0].signed, False)
self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
# Jp2 Header
# Colour specification
self.assertEqual(jp2.box[2].box[1].method,
glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(jp2.box[2].box[1].precedence, 0)
self.assertEqual(jp2.box[2].box[1].approximation, 0) # not allowed?
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
c = jp2.box[3].main_header
ids = [x.marker_id for x in c.segment]
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
self.assertEqual(ids, expected)
# SIZ: Image and tile size
# Profile:
self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size
self.assertEqual(c.segment[1].xsiz, 203)
self.assertEqual(c.segment[1].ysiz, 152)
# Reference grid offset
self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size
self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), (203, 152))
# Tile offset
self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0))
# bitdepth
self.assertEqual(c.segment[1].bitdepth, (8, 8, 8))
# signed
self.assertEqual(c.segment[1].signed, (False, False, False))
# subsampling
self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3)
# COM: comment
# Registration
self.assertEqual(c.segment[2].rcme, glymur.core.RCME_ISO_8859_1)
# Comment value
self.assertEqual(c.segment[2].ccme.decode('latin-1'),
"Creator: JasPer Version 1.701.0")
# COD: Coding style default
self.assertFalse(c.segment[3].scod & 2) # no sop
self.assertFalse(c.segment[3].scod & 4) # no eph
self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[3].layers, 1) # layers = 1
self.assertEqual(c.segment[3].spcod[3], 1) # mct
self.assertEqual(c.segment[3].spcod[4], 5) # level
self.assertEqual(tuple(c.segment[3].code_block_size),
(64, 64)) # cblk
# Selective arithmetic coding bypass
self.assertFalse(c.segment[3].spcod[7] & 0x01)
# Reset context probabilities
self.assertFalse(c.segment[3].spcod[7] & 0x02)
# Termination on each coding pass
self.assertFalse(c.segment[3].spcod[7] & 0x04)
# Vertically causal context
self.assertFalse(c.segment[3].spcod[7] & 0x08)
# Predictable termination
self.assertFalse(c.segment[3].spcod[7] & 0x0010)
# Segmentation symbols
self.assertFalse(c.segment[3].spcod[7] & 0x0020)
self.assertEqual(c.segment[3].spcod[8],
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[3].spcod), 9)
# QCD: Quantization default
self.assertEqual(c.segment[4].sqcd & 0x1f, 0)
self.assertEqual(c.segment[4].guard_bits, 2)
self.assertEqual(c.segment[4].mantissa, [0] * 16)
self.assertEqual(c.segment[4].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[5].cqcc, 1)
self.assertEqual(c.segment[5].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[5].mantissa, [0] * 16)
self.assertEqual(c.segment[5].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[6].cqcc, 2)
self.assertEqual(c.segment[6].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[6].mantissa, [0] * 16)
self.assertEqual(c.segment[6].exponent,
[8] + [9, 9, 10] * 5)
def test_NR_broken2_jp2_dump(self):
# Invalid marker ID on codestream.
jfile = opj_data_file('input/nonregression/broken2.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
jp2 = Jp2k(jfile)
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
@unittest.skipIf(sys.maxsize < 2**32, 'Do not run on 32-bit platforms')
def test_NR_broken3_jp2_dump(self):
"""
NR_broken3_jp2_dump
The file in question here has a colr box with an erroneous box
length of over 1GB. Don't run it on 32-bit platforms.
"""
jfile = opj_data_file('input/nonregression/broken3.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
jp2 = Jp2k(jfile)
ids = [box.box_id for box in jp2.box]
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
ids = [box.box_id for box in jp2.box[2].box]
self.assertEqual(ids, ['ihdr', 'colr'])
# Signature box. Check for corruption.
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
# File type box.
self.assertEqual(jp2.box[1].brand, 'jp2 ')
self.assertEqual(jp2.box[1].minor_version, 0)
self.assertEqual(jp2.box[1].compatibility_list[0], 'jp2 ')
# Jp2 Header
# Image header
self.assertEqual(jp2.box[2].box[0].height, 152)
self.assertEqual(jp2.box[2].box[0].width, 203)
self.assertEqual(jp2.box[2].box[0].num_components, 3)
self.assertEqual(jp2.box[2].box[0].bits_per_component, 8)
self.assertEqual(jp2.box[2].box[0].signed, False)
self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
# Jp2 Header
# Colour specification
self.assertEqual(jp2.box[2].box[1].method,
glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(jp2.box[2].box[1].precedence, 0)
self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
c = jp2.box[3].main_header
ids = [x.marker_id for x in c.segment]
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
self.assertEqual(ids, expected)
# SIZ: Image and tile size
# Profile:
self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size
self.assertEqual(c.segment[1].xsiz, 203)
self.assertEqual(c.segment[1].ysiz, 152)
# Reference grid offset
self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size
self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), (203, 152))
# Tile offset
self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0))
# bitdepth
self.assertEqual(c.segment[1].bitdepth, (8, 8, 8))
# signed
self.assertEqual(c.segment[1].signed, (False, False, False))
# subsampling
self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3)
# COM: comment
# Registration
self.assertEqual(c.segment[2].rcme, glymur.core.RCME_ISO_8859_1)
# Comment value
self.assertEqual(c.segment[2].ccme.decode('latin-1'),
"Creator: JasPer Vers)on 1.701.0")
# COD: Coding style default
self.assertFalse(c.segment[3].scod & 2) # no sop
self.assertFalse(c.segment[3].scod & 4) # no eph
self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[3].layers, 1) # layers = 1
self.assertEqual(c.segment[3].spcod[3], 1) # mct
self.assertEqual(c.segment[3].spcod[4], 5) # level
self.assertEqual(tuple(c.segment[3].code_block_size),
(64, 64)) # cblk
# Selective arithmetic coding bypass
self.assertFalse(c.segment[3].spcod[7] & 0x01)
# Reset context probabilities
self.assertFalse(c.segment[3].spcod[7] & 0x02)
# Termination on each coding pass
self.assertFalse(c.segment[3].spcod[7] & 0x04)
# Vertically causal context
self.assertFalse(c.segment[3].spcod[7] & 0x08)
# Predictable termination
self.assertFalse(c.segment[3].spcod[7] & 0x0010)
# Segmentation symbols
self.assertFalse(c.segment[3].spcod[7] & 0x0020)
self.assertEqual(c.segment[3].spcod[8],
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[3].spcod), 9)
# QCD: Quantization default
self.assertEqual(c.segment[4].sqcd & 0x1f, 0)
self.assertEqual(c.segment[4].guard_bits, 2)
self.assertEqual(c.segment[4].mantissa, [0] * 16)
self.assertEqual(c.segment[4].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[5].cqcc, 1)
self.assertEqual(c.segment[5].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[5].mantissa, [0] * 16)
self.assertEqual(c.segment[5].exponent,
[8] + [9, 9, 10] * 5)
# QCC: Quantization component
# associated component
self.assertEqual(c.segment[6].cqcc, 2)
self.assertEqual(c.segment[6].guard_bits, 2)
# quantization type
self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none
self.assertEqual(c.segment[6].mantissa, [0] * 16)
self.assertEqual(c.segment[6].exponent,
[8] + [9, 9, 10] * 5)
def test_NR_broken4_jp2_dump(self):
# Has an invalid marker in the main header
jfile = opj_data_file('input/nonregression/broken4.jp2')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
jp2 = Jp2k(jfile)
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self):
lst = ['input', 'nonregression',
'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2']
jfile = opj_data_file('/'.join(lst))
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
Jp2k(jfile)
def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self):
lst = ['input', 'nonregression', 'gdal_fuzzer_check_comp_dx_dy.jp2']
jfile = opj_data_file('/'.join(lst))
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
Jp2k(jfile)
def test_NR_gdal_fuzzer_check_number_of_tiles(self):
# Has an impossible tiling setup.
lst = ['input', 'nonregression',
'gdal_fuzzer_check_number_of_tiles.jp2']
jfile = opj_data_file('/'.join(lst))
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
Jp2k(jfile)
def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self):
# Has an invalid number of resolutions.
lst = ['input', 'nonregression',
'gdal_fuzzer_unchecked_numresolutions.jp2']
jfile = opj_data_file('/'.join(lst))
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
Jp2k(jfile)
@unittest.skipIf(re.match("1.5|2.0.0", glymur.version.openjpeg_version),
"Test not passing on 1.5.x, not introduced until 2.x")
def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self):
# Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it
# really does deserve a warning.
relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2'
jfile = opj_data_file(relpath)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('ignore')
j = Jp2k(jfile)
d = j.read()
if __name__ == "__main__":
unittest.main()

View file

@ -11,6 +11,7 @@
# pylint: disable=R0904 # pylint: disable=R0904
import os import os
import re
import struct import struct
import sys import sys
import tempfile import tempfile
@ -76,7 +77,7 @@ class TestPrinting(unittest.TestCase):
with open(self.jpxfile, 'rb') as ifile: with open(self.jpxfile, 'rb') as ifile:
tfile.write(ifile.read()) tfile.write(ifile.read())
# Add the header for an unknwon superbox. # Add the header for an unknown superbox.
write_buffer = struct.pack('>I4s', 20, 'grp '.encode()) write_buffer = struct.pack('>I4s', 20, 'grp '.encode())
tfile.write(write_buffer) tfile.write(write_buffer)
@ -86,10 +87,10 @@ class TestPrinting(unittest.TestCase):
tfile.write(write_buffer) tfile.write(write_buffer)
tfile.flush() tfile.flush()
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings():
warnings.simplefilter('always') # Suppress the warning about the unrecognized box.
warnings.simplefilter("ignore")
jpx = Jp2k(tfile.name) jpx = Jp2k(tfile.name)
self.assertTrue(len(w), 1)
glymur.set_printoptions(short=True) glymur.set_printoptions(short=True)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -725,8 +726,6 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
# Reset printoptions for every test. # Reset printoptions for every test.
glymur.set_printoptions(short=False, xml=True, codestream=True) glymur.set_printoptions(short=False, xml=True, codestream=True)
warnings.resetwarnings()
def tearDown(self): def tearDown(self):
pass pass
@ -744,6 +743,8 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
"""An invalid colorspace shouldn't cause an error.""" """An invalid colorspace shouldn't cause an error."""
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2') filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
with warnings.catch_warnings(): with warnings.catch_warnings():
# Bad compatibility list item and bad colorspace warnings. Just
# suppress the warnings.
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
jp2 = Jp2k(filename) jp2 = Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -763,14 +764,15 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2') filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
j = Jp2k(filename) jp2 = Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j) print(jp2)
def test_invalid_progression_order(self): def test_invalid_progression_order(self):
"""Should still be able to print even if prog order is invalid.""" """Should still be able to print even if prog order is invalid."""
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2') jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
with warnings.catch_warnings(): with warnings.catch_warnings():
# Multiple warnings, actually.
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
jp2 = Jp2k(jfile) jp2 = Jp2k(jfile)
codestream = jp2.get_codestream() codestream = jp2.get_codestream()
@ -1058,10 +1060,7 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
def test_uuid(self): def test_uuid(self):
"""verify printing of UUID box""" """verify printing of UUID box"""
filename = opj_data_file('input/nonregression/text_GBR.jp2') filename = opj_data_file('input/nonregression/text_GBR.jp2')
with warnings.catch_warnings(): jp2 = Jp2k(filename)
# brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore")
jp2 = Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(jp2.box[4]) print(jp2.box[4])