[TSI1] add tests for decompile method
This commit is contained in:
parent
b26eeb2eb2
commit
18bd3c6afe
162
Tests/ttLib/tables/T_S_I__1_test.py
Normal file
162
Tests/ttLib/tables/T_S_I__1_test.py
Normal file
@ -0,0 +1,162 @@
|
||||
from __future__ import print_function, division, absolute_import
|
||||
from fontTools.misc.py23 import unichr
|
||||
from fontTools.misc.loggingTools import CapturingLogHandler
|
||||
from fontTools.ttLib import TTFont, TTLibError
|
||||
from fontTools.ttLib.tables.T_S_I__0 import table_T_S_I__0
|
||||
from fontTools.ttLib.tables.T_S_I__1 import table_T_S_I__1
|
||||
import pytest
|
||||
|
||||
|
||||
TSI1_DATA = b"""abcdefghijklmnopqrstuvxywz0123456789"""
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def indextable():
|
||||
table = table_T_S_I__0()
|
||||
table.set(
|
||||
[(0, 1, 0), # gid 0, length=1, offset=0, text='a'
|
||||
(1, 5, 1), # gid 1, length=5, offset=1, text='bcdef'
|
||||
(2, 0, 1), # gid 2, length=0, offset=1, text=''
|
||||
(3, 0, 1), # gid 3, length=0, offset=1, text=''
|
||||
(4, 8, 6)], # gid 4, length=8, offset=6, text='ghijklmn'
|
||||
[(0xFFFA, 2, 14), # 'ppgm', length=2, offset=14, text='op'
|
||||
(0xFFFB, 4, 16), # 'cvt', length=4, offset=16, text='qrst'
|
||||
(0xFFFC, 6, 20), # 'reserved', length=6, offset=20, text='uvxywz'
|
||||
(0xFFFD, 10, 26)] # 'fpgm', length=10, offset=26, text='0123456789'
|
||||
)
|
||||
return table
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def font(indextable):
|
||||
font = TTFont()
|
||||
# ['a', 'b', 'c', ...]
|
||||
ch = 0x61
|
||||
n = len(indextable.indices)
|
||||
font.glyphOrder = [unichr(i) for i in range(ch, ch+n)]
|
||||
font['TSI0'] = indextable
|
||||
return font
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def empty_font():
|
||||
font = TTFont()
|
||||
font.glyphOrder = []
|
||||
indextable = table_T_S_I__0()
|
||||
indextable.set([], [(0xFFFA, 0, 0),
|
||||
(0xFFFB, 0, 0),
|
||||
(0xFFFC, 0, 0),
|
||||
(0xFFFD, 0, 0)])
|
||||
font['TSI0'] = indextable
|
||||
return font
|
||||
|
||||
|
||||
def test_decompile(font):
|
||||
table = table_T_S_I__1()
|
||||
table.decompile(TSI1_DATA, font)
|
||||
|
||||
assert table.glyphPrograms == {
|
||||
'a': b'a',
|
||||
'b': b'bcdef',
|
||||
# 'c': b'', # zero-length entries are skipped
|
||||
# 'd': b'',
|
||||
'e': b'ghijklmn'}
|
||||
assert table.extraPrograms == {
|
||||
'ppgm': b'op',
|
||||
'cvt': b'qrst',
|
||||
'reserved': b'uvxywz',
|
||||
'fpgm': b'0123456789'}
|
||||
|
||||
|
||||
def test_decompile_empty(empty_font):
|
||||
table = table_T_S_I__1()
|
||||
table.decompile(b"", empty_font)
|
||||
|
||||
assert table.glyphPrograms == {}
|
||||
assert table.extraPrograms == {}
|
||||
|
||||
|
||||
def test_decompile_invalid_length(empty_font):
|
||||
empty_font.glyphOrder = ['a']
|
||||
empty_font['TSI0'].indices = [(0, 0x8000+1, 0)]
|
||||
|
||||
table = table_T_S_I__1()
|
||||
with pytest.raises(TTLibError) as excinfo:
|
||||
table.decompile(b'', empty_font)
|
||||
assert excinfo.match("textLength .* must not be > 32768")
|
||||
|
||||
|
||||
def test_decompile_offset_past_end(empty_font):
|
||||
empty_font.glyphOrder = ['foo', 'bar']
|
||||
data = b'baz'
|
||||
empty_font['TSI0'].indices = [(0, len(data), 0), (1, 1, len(data)+1)]
|
||||
|
||||
table = table_T_S_I__1()
|
||||
with CapturingLogHandler(table.log, "WARNING") as captor:
|
||||
table.decompile(data, empty_font)
|
||||
|
||||
# the 'bar' program is skipped because its offset > len(data)
|
||||
assert table.glyphPrograms == {'foo': b'baz'}
|
||||
assert any("textOffset > totalLength" in r.msg for r in captor.records)
|
||||
|
||||
|
||||
def test_decompile_magic_length_last_extra(empty_font):
|
||||
indextable = empty_font['TSI0']
|
||||
indextable.extra_indices[-1] = (0xFFFD, 0x8000, 0)
|
||||
data = b"0" * (0x8000 + 1)
|
||||
|
||||
table = table_T_S_I__1()
|
||||
table.decompile(data, empty_font)
|
||||
|
||||
assert table.extraPrograms['fpgm'] == data
|
||||
|
||||
|
||||
def test_decompile_magic_length_last_glyph(empty_font):
|
||||
empty_font.glyphOrder = ['foo', 'bar']
|
||||
indextable = empty_font['TSI0']
|
||||
indextable.indices = [
|
||||
(0, 3, 0),
|
||||
(1, 0x8000, 3)] # the actual length of 'bar' program is
|
||||
indextable.extra_indices = [ # the difference between the first extra's
|
||||
(0xFFFA, 0, 0x8004), # offset and 'bar' offset: 0x8004 - 3
|
||||
(0xFFFB, 0, 0x8004),
|
||||
(0xFFFC, 0, 0x8004),
|
||||
(0xFFFD, 0, 0x8004)]
|
||||
foo_data = b"0" * 3
|
||||
bar_data = b"1" * (0x8000 + 1)
|
||||
data = foo_data + bar_data
|
||||
|
||||
table = table_T_S_I__1()
|
||||
table.decompile(data, empty_font)
|
||||
|
||||
assert table.glyphPrograms['foo'] == foo_data
|
||||
assert table.glyphPrograms['bar'] == bar_data
|
||||
|
||||
|
||||
def test_decompile_magic_length_non_last(empty_font):
|
||||
indextable = empty_font['TSI0']
|
||||
indextable.extra_indices = [
|
||||
(0xFFFA, 3, 0),
|
||||
(0xFFFB, 0x8000, 3), # the actual length of 'cvt' program is:
|
||||
(0xFFFC, 0, 0x8004), # nextTextOffset - textOffset: 0x8004 - 3
|
||||
(0xFFFD, 0, 0x8004)]
|
||||
ppgm_data = b"0" * 3
|
||||
cvt_data = b"1" * (0x8000 + 1)
|
||||
data = ppgm_data + cvt_data
|
||||
|
||||
table = table_T_S_I__1()
|
||||
table.decompile(data, empty_font)
|
||||
|
||||
assert table.extraPrograms['ppgm'] == ppgm_data
|
||||
assert table.extraPrograms['cvt'] == cvt_data
|
||||
|
||||
table = table_T_S_I__1()
|
||||
with CapturingLogHandler(table.log, "WARNING") as captor:
|
||||
table.decompile(data[:-1], empty_font) # last entry is truncated
|
||||
assert captor.match("nextTextOffset > totalLength")
|
||||
assert table.extraPrograms['cvt'] == cvt_data[:-1]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
sys.exit(pytest.main(sys.argv))
|
Loading…
x
Reference in New Issue
Block a user