xref: /aosp_15_r20/external/fonttools/Tests/ttLib/tables/tables_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughesfrom fontTools.ttLib import TTFont, tagToXML
2*e1fe3e4aSElliott Hughesfrom io import StringIO
3*e1fe3e4aSElliott Hughesimport os
4*e1fe3e4aSElliott Hughesimport sys
5*e1fe3e4aSElliott Hughesimport re
6*e1fe3e4aSElliott Hughesimport contextlib
7*e1fe3e4aSElliott Hughesimport pytest
8*e1fe3e4aSElliott Hughes
9*e1fe3e4aSElliott Hughestry:
10*e1fe3e4aSElliott Hughes    import unicodedata2
11*e1fe3e4aSElliott Hughesexcept ImportError:
12*e1fe3e4aSElliott Hughes    if sys.version_info[:2] < (3, 6):
13*e1fe3e4aSElliott Hughes        unicodedata2 = None
14*e1fe3e4aSElliott Hughes    else:
15*e1fe3e4aSElliott Hughes        # on 3.6 the built-in unicodedata is the same as unicodedata2 backport
16*e1fe3e4aSElliott Hughes        import unicodedata
17*e1fe3e4aSElliott Hughes
18*e1fe3e4aSElliott Hughes        unicodedata2 = unicodedata
19*e1fe3e4aSElliott Hughes
20*e1fe3e4aSElliott Hughes
21*e1fe3e4aSElliott Hughes# Font files in data/*.{o,t}tf; output gets compared to data/*.ttx.*
22*e1fe3e4aSElliott HughesTESTS = {
23*e1fe3e4aSElliott Hughes    "aots/base.otf": (
24*e1fe3e4aSElliott Hughes        "CFF ",
25*e1fe3e4aSElliott Hughes        "cmap",
26*e1fe3e4aSElliott Hughes        "head",
27*e1fe3e4aSElliott Hughes        "hhea",
28*e1fe3e4aSElliott Hughes        "hmtx",
29*e1fe3e4aSElliott Hughes        "maxp",
30*e1fe3e4aSElliott Hughes        "name",
31*e1fe3e4aSElliott Hughes        "OS/2",
32*e1fe3e4aSElliott Hughes        "post",
33*e1fe3e4aSElliott Hughes    ),
34*e1fe3e4aSElliott Hughes    "aots/classdef1_font1.otf": ("GSUB",),
35*e1fe3e4aSElliott Hughes    "aots/classdef1_font2.otf": ("GSUB",),
36*e1fe3e4aSElliott Hughes    "aots/classdef1_font3.otf": ("GSUB",),
37*e1fe3e4aSElliott Hughes    "aots/classdef1_font4.otf": ("GSUB",),
38*e1fe3e4aSElliott Hughes    "aots/classdef2_font1.otf": ("GSUB",),
39*e1fe3e4aSElliott Hughes    "aots/classdef2_font2.otf": ("GSUB",),
40*e1fe3e4aSElliott Hughes    "aots/classdef2_font3.otf": ("GSUB",),
41*e1fe3e4aSElliott Hughes    "aots/classdef2_font4.otf": ("GSUB",),
42*e1fe3e4aSElliott Hughes    "aots/cmap0_font1.otf": ("cmap",),
43*e1fe3e4aSElliott Hughes    "aots/cmap10_font1.otf": ("cmap",),
44*e1fe3e4aSElliott Hughes    "aots/cmap10_font2.otf": ("cmap",),
45*e1fe3e4aSElliott Hughes    "aots/cmap12_font1.otf": ("cmap",),
46*e1fe3e4aSElliott Hughes    "aots/cmap14_font1.otf": ("cmap",),
47*e1fe3e4aSElliott Hughes    "aots/cmap2_font1.otf": ("cmap",),
48*e1fe3e4aSElliott Hughes    "aots/cmap4_font1.otf": ("cmap",),
49*e1fe3e4aSElliott Hughes    "aots/cmap4_font2.otf": ("cmap",),
50*e1fe3e4aSElliott Hughes    "aots/cmap4_font3.otf": ("cmap",),
51*e1fe3e4aSElliott Hughes    "aots/cmap4_font4.otf": ("cmap",),
52*e1fe3e4aSElliott Hughes    "aots/cmap6_font1.otf": ("cmap",),
53*e1fe3e4aSElliott Hughes    "aots/cmap6_font2.otf": ("cmap",),
54*e1fe3e4aSElliott Hughes    "aots/cmap8_font1.otf": ("cmap",),
55*e1fe3e4aSElliott Hughes    "aots/cmap_composition_font1.otf": ("cmap",),
56*e1fe3e4aSElliott Hughes    "aots/cmap_subtableselection_font1.otf": ("cmap",),
57*e1fe3e4aSElliott Hughes    "aots/cmap_subtableselection_font2.otf": ("cmap",),
58*e1fe3e4aSElliott Hughes    "aots/cmap_subtableselection_font3.otf": ("cmap",),
59*e1fe3e4aSElliott Hughes    "aots/cmap_subtableselection_font4.otf": ("cmap",),
60*e1fe3e4aSElliott Hughes    "aots/cmap_subtableselection_font5.otf": ("cmap",),
61*e1fe3e4aSElliott Hughes    "aots/gpos1_1_lookupflag_f1.otf": ("GDEF", "GPOS"),
62*e1fe3e4aSElliott Hughes    "aots/gpos1_1_simple_f1.otf": ("GPOS",),
63*e1fe3e4aSElliott Hughes    "aots/gpos1_1_simple_f2.otf": ("GPOS",),
64*e1fe3e4aSElliott Hughes    "aots/gpos1_1_simple_f3.otf": ("GPOS",),
65*e1fe3e4aSElliott Hughes    "aots/gpos1_1_simple_f4.otf": ("GPOS",),
66*e1fe3e4aSElliott Hughes    "aots/gpos1_2_font1.otf": ("GPOS",),
67*e1fe3e4aSElliott Hughes    "aots/gpos1_2_font2.otf": ("GDEF", "GPOS"),
68*e1fe3e4aSElliott Hughes    "aots/gpos2_1_font6.otf": ("GPOS",),
69*e1fe3e4aSElliott Hughes    "aots/gpos2_1_font7.otf": ("GPOS",),
70*e1fe3e4aSElliott Hughes    "aots/gpos2_1_lookupflag_f1.otf": ("GDEF", "GPOS"),
71*e1fe3e4aSElliott Hughes    "aots/gpos2_1_lookupflag_f2.otf": ("GDEF", "GPOS"),
72*e1fe3e4aSElliott Hughes    "aots/gpos2_1_next_glyph_f1.otf": ("GPOS",),
73*e1fe3e4aSElliott Hughes    "aots/gpos2_1_next_glyph_f2.otf": ("GPOS",),
74*e1fe3e4aSElliott Hughes    "aots/gpos2_1_simple_f1.otf": ("GPOS",),
75*e1fe3e4aSElliott Hughes    "aots/gpos2_2_font1.otf": ("GPOS",),
76*e1fe3e4aSElliott Hughes    "aots/gpos2_2_font2.otf": ("GDEF", "GPOS"),
77*e1fe3e4aSElliott Hughes    "aots/gpos2_2_font3.otf": ("GDEF", "GPOS"),
78*e1fe3e4aSElliott Hughes    "aots/gpos2_2_font4.otf": ("GPOS",),
79*e1fe3e4aSElliott Hughes    "aots/gpos2_2_font5.otf": ("GPOS",),
80*e1fe3e4aSElliott Hughes    "aots/gpos3_font1.otf": ("GPOS",),
81*e1fe3e4aSElliott Hughes    "aots/gpos3_font2.otf": ("GDEF", "GPOS"),
82*e1fe3e4aSElliott Hughes    "aots/gpos3_font3.otf": ("GDEF", "GPOS"),
83*e1fe3e4aSElliott Hughes    "aots/gpos4_lookupflag_f1.otf": ("GDEF", "GPOS"),
84*e1fe3e4aSElliott Hughes    "aots/gpos4_lookupflag_f2.otf": ("GDEF", "GPOS"),
85*e1fe3e4aSElliott Hughes    "aots/gpos4_multiple_anchors_1.otf": ("GDEF", "GPOS"),
86*e1fe3e4aSElliott Hughes    "aots/gpos4_simple_1.otf": ("GDEF", "GPOS"),
87*e1fe3e4aSElliott Hughes    "aots/gpos5_font1.otf": ("GDEF", "GPOS", "GSUB"),
88*e1fe3e4aSElliott Hughes    "aots/gpos6_font1.otf": ("GDEF", "GPOS"),
89*e1fe3e4aSElliott Hughes    "aots/gpos7_1_font1.otf": ("GPOS",),
90*e1fe3e4aSElliott Hughes    "aots/gpos9_font1.otf": ("GPOS",),
91*e1fe3e4aSElliott Hughes    "aots/gpos9_font2.otf": ("GPOS",),
92*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_boundary_f1.otf": ("GDEF", "GPOS"),
93*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_boundary_f2.otf": ("GDEF", "GPOS"),
94*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_boundary_f3.otf": ("GDEF", "GPOS"),
95*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_boundary_f4.otf": ("GDEF", "GPOS"),
96*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_lookupflag_f1.otf": ("GDEF", "GPOS"),
97*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_multiple_subrules_f1.otf": ("GDEF", "GPOS"),
98*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_multiple_subrules_f2.otf": ("GDEF", "GPOS"),
99*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_next_glyph_f1.otf": ("GDEF", "GPOS"),
100*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_simple_f1.otf": ("GDEF", "GPOS"),
101*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_simple_f2.otf": ("GDEF", "GPOS"),
102*e1fe3e4aSElliott Hughes    "aots/gpos_chaining1_successive_f1.otf": ("GDEF", "GPOS"),
103*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_boundary_f1.otf": ("GDEF", "GPOS"),
104*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_boundary_f2.otf": ("GDEF", "GPOS"),
105*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_boundary_f3.otf": ("GDEF", "GPOS"),
106*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_boundary_f4.otf": ("GDEF", "GPOS"),
107*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_lookupflag_f1.otf": ("GDEF", "GPOS"),
108*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_multiple_subrules_f1.otf": ("GDEF", "GPOS"),
109*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_multiple_subrules_f2.otf": ("GDEF", "GPOS"),
110*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_next_glyph_f1.otf": ("GDEF", "GPOS"),
111*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_simple_f1.otf": ("GDEF", "GPOS"),
112*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_simple_f2.otf": ("GDEF", "GPOS"),
113*e1fe3e4aSElliott Hughes    "aots/gpos_chaining2_successive_f1.otf": ("GDEF", "GPOS"),
114*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_boundary_f1.otf": ("GDEF", "GPOS"),
115*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_boundary_f2.otf": ("GDEF", "GPOS"),
116*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_boundary_f3.otf": ("GDEF", "GPOS"),
117*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_boundary_f4.otf": ("GDEF", "GPOS"),
118*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_lookupflag_f1.otf": ("GDEF", "GPOS"),
119*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_next_glyph_f1.otf": ("GDEF", "GPOS"),
120*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_simple_f1.otf": ("GDEF", "GPOS"),
121*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_simple_f2.otf": ("GDEF", "GPOS"),
122*e1fe3e4aSElliott Hughes    "aots/gpos_chaining3_successive_f1.otf": ("GDEF", "GPOS"),
123*e1fe3e4aSElliott Hughes    "aots/gpos_context1_boundary_f1.otf": ("GDEF", "GPOS"),
124*e1fe3e4aSElliott Hughes    "aots/gpos_context1_boundary_f2.otf": ("GDEF", "GPOS"),
125*e1fe3e4aSElliott Hughes    "aots/gpos_context1_expansion_f1.otf": ("GDEF", "GPOS"),
126*e1fe3e4aSElliott Hughes    "aots/gpos_context1_lookupflag_f1.otf": ("GDEF", "GPOS"),
127*e1fe3e4aSElliott Hughes    "aots/gpos_context1_lookupflag_f2.otf": ("GDEF", "GPOS"),
128*e1fe3e4aSElliott Hughes    "aots/gpos_context1_multiple_subrules_f1.otf": ("GDEF", "GPOS"),
129*e1fe3e4aSElliott Hughes    "aots/gpos_context1_multiple_subrules_f2.otf": ("GDEF", "GPOS"),
130*e1fe3e4aSElliott Hughes    "aots/gpos_context1_next_glyph_f1.otf": ("GDEF", "GPOS"),
131*e1fe3e4aSElliott Hughes    "aots/gpos_context1_simple_f1.otf": ("GDEF", "GPOS"),
132*e1fe3e4aSElliott Hughes    "aots/gpos_context1_simple_f2.otf": ("GDEF", "GPOS"),
133*e1fe3e4aSElliott Hughes    "aots/gpos_context1_successive_f1.otf": ("GDEF", "GPOS"),
134*e1fe3e4aSElliott Hughes    "aots/gpos_context2_boundary_f1.otf": ("GDEF", "GPOS"),
135*e1fe3e4aSElliott Hughes    "aots/gpos_context2_boundary_f2.otf": ("GDEF", "GPOS"),
136*e1fe3e4aSElliott Hughes    "aots/gpos_context2_classes_f1.otf": ("GDEF", "GPOS"),
137*e1fe3e4aSElliott Hughes    "aots/gpos_context2_classes_f2.otf": ("GDEF", "GPOS"),
138*e1fe3e4aSElliott Hughes    "aots/gpos_context2_expansion_f1.otf": ("GDEF", "GPOS"),
139*e1fe3e4aSElliott Hughes    "aots/gpos_context2_lookupflag_f1.otf": ("GDEF", "GPOS"),
140*e1fe3e4aSElliott Hughes    "aots/gpos_context2_lookupflag_f2.otf": ("GDEF", "GPOS"),
141*e1fe3e4aSElliott Hughes    "aots/gpos_context2_multiple_subrules_f1.otf": ("GDEF", "GPOS"),
142*e1fe3e4aSElliott Hughes    "aots/gpos_context2_multiple_subrules_f2.otf": ("GDEF", "GPOS"),
143*e1fe3e4aSElliott Hughes    "aots/gpos_context2_next_glyph_f1.otf": ("GDEF", "GPOS"),
144*e1fe3e4aSElliott Hughes    "aots/gpos_context2_simple_f1.otf": ("GDEF", "GPOS"),
145*e1fe3e4aSElliott Hughes    "aots/gpos_context2_simple_f2.otf": ("GDEF", "GPOS"),
146*e1fe3e4aSElliott Hughes    "aots/gpos_context2_successive_f1.otf": ("GDEF", "GPOS"),
147*e1fe3e4aSElliott Hughes    "aots/gpos_context3_boundary_f1.otf": ("GDEF", "GPOS"),
148*e1fe3e4aSElliott Hughes    "aots/gpos_context3_boundary_f2.otf": ("GDEF", "GPOS"),
149*e1fe3e4aSElliott Hughes    "aots/gpos_context3_lookupflag_f1.otf": ("GDEF", "GPOS"),
150*e1fe3e4aSElliott Hughes    "aots/gpos_context3_lookupflag_f2.otf": ("GDEF", "GPOS"),
151*e1fe3e4aSElliott Hughes    "aots/gpos_context3_next_glyph_f1.otf": ("GDEF", "GPOS"),
152*e1fe3e4aSElliott Hughes    "aots/gpos_context3_simple_f1.otf": ("GDEF", "GPOS"),
153*e1fe3e4aSElliott Hughes    "aots/gpos_context3_successive_f1.otf": ("GDEF", "GPOS"),
154*e1fe3e4aSElliott Hughes    "aots/gsub1_1_lookupflag_f1.otf": ("GDEF", "GSUB"),
155*e1fe3e4aSElliott Hughes    "aots/gsub1_1_modulo_f1.otf": ("GSUB",),
156*e1fe3e4aSElliott Hughes    "aots/gsub1_1_simple_f1.otf": ("GSUB",),
157*e1fe3e4aSElliott Hughes    "aots/gsub1_2_lookupflag_f1.otf": ("GDEF", "GSUB"),
158*e1fe3e4aSElliott Hughes    "aots/gsub1_2_simple_f1.otf": ("GSUB",),
159*e1fe3e4aSElliott Hughes    "aots/gsub2_1_lookupflag_f1.otf": ("GDEF", "GSUB"),
160*e1fe3e4aSElliott Hughes    "aots/gsub2_1_multiple_sequences_f1.otf": ("GSUB",),
161*e1fe3e4aSElliott Hughes    "aots/gsub2_1_simple_f1.otf": ("GSUB",),
162*e1fe3e4aSElliott Hughes    "aots/gsub3_1_lookupflag_f1.otf": ("GDEF", "GSUB"),
163*e1fe3e4aSElliott Hughes    "aots/gsub3_1_multiple_f1.otf": ("GSUB",),
164*e1fe3e4aSElliott Hughes    "aots/gsub3_1_simple_f1.otf": ("GSUB",),
165*e1fe3e4aSElliott Hughes    "aots/gsub4_1_lookupflag_f1.otf": ("GDEF", "GSUB"),
166*e1fe3e4aSElliott Hughes    "aots/gsub4_1_multiple_ligatures_f1.otf": ("GSUB",),
167*e1fe3e4aSElliott Hughes    "aots/gsub4_1_multiple_ligatures_f2.otf": ("GSUB",),
168*e1fe3e4aSElliott Hughes    "aots/gsub4_1_multiple_ligsets_f1.otf": ("GSUB",),
169*e1fe3e4aSElliott Hughes    "aots/gsub4_1_simple_f1.otf": ("GSUB",),
170*e1fe3e4aSElliott Hughes    "aots/gsub7_font1.otf": ("GSUB",),
171*e1fe3e4aSElliott Hughes    "aots/gsub7_font2.otf": ("GSUB",),
172*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_boundary_f1.otf": ("GDEF", "GSUB"),
173*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_boundary_f2.otf": ("GDEF", "GSUB"),
174*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_boundary_f3.otf": ("GDEF", "GSUB"),
175*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_boundary_f4.otf": ("GDEF", "GSUB"),
176*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_lookupflag_f1.otf": ("GDEF", "GSUB"),
177*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_multiple_subrules_f1.otf": ("GDEF", "GSUB"),
178*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_multiple_subrules_f2.otf": ("GDEF", "GSUB"),
179*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_next_glyph_f1.otf": ("GDEF", "GSUB"),
180*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_simple_f1.otf": ("GDEF", "GSUB"),
181*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_simple_f2.otf": ("GDEF", "GSUB"),
182*e1fe3e4aSElliott Hughes    "aots/gsub_chaining1_successive_f1.otf": ("GDEF", "GSUB"),
183*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_boundary_f1.otf": ("GDEF", "GSUB"),
184*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_boundary_f2.otf": ("GDEF", "GSUB"),
185*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_boundary_f3.otf": ("GDEF", "GSUB"),
186*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_boundary_f4.otf": ("GDEF", "GSUB"),
187*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_lookupflag_f1.otf": ("GDEF", "GSUB"),
188*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_multiple_subrules_f1.otf": ("GDEF", "GSUB"),
189*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_multiple_subrules_f2.otf": ("GDEF", "GSUB"),
190*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_next_glyph_f1.otf": ("GDEF", "GSUB"),
191*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_simple_f1.otf": ("GDEF", "GSUB"),
192*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_simple_f2.otf": ("GDEF", "GSUB"),
193*e1fe3e4aSElliott Hughes    "aots/gsub_chaining2_successive_f1.otf": ("GDEF", "GSUB"),
194*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_boundary_f1.otf": ("GDEF", "GSUB"),
195*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_boundary_f2.otf": ("GDEF", "GSUB"),
196*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_boundary_f3.otf": ("GDEF", "GSUB"),
197*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_boundary_f4.otf": ("GDEF", "GSUB"),
198*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_lookupflag_f1.otf": ("GDEF", "GSUB"),
199*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_next_glyph_f1.otf": ("GDEF", "GSUB"),
200*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_simple_f1.otf": ("GDEF", "GSUB"),
201*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_simple_f2.otf": ("GDEF", "GSUB"),
202*e1fe3e4aSElliott Hughes    "aots/gsub_chaining3_successive_f1.otf": ("GDEF", "GSUB"),
203*e1fe3e4aSElliott Hughes    "aots/gsub_context1_boundary_f1.otf": ("GDEF", "GSUB"),
204*e1fe3e4aSElliott Hughes    "aots/gsub_context1_boundary_f2.otf": ("GDEF", "GSUB"),
205*e1fe3e4aSElliott Hughes    "aots/gsub_context1_expansion_f1.otf": ("GDEF", "GSUB"),
206*e1fe3e4aSElliott Hughes    "aots/gsub_context1_lookupflag_f1.otf": ("GDEF", "GSUB"),
207*e1fe3e4aSElliott Hughes    "aots/gsub_context1_lookupflag_f2.otf": ("GDEF", "GSUB"),
208*e1fe3e4aSElliott Hughes    "aots/gsub_context1_multiple_subrules_f1.otf": ("GDEF", "GSUB"),
209*e1fe3e4aSElliott Hughes    "aots/gsub_context1_multiple_subrules_f2.otf": ("GDEF", "GSUB"),
210*e1fe3e4aSElliott Hughes    "aots/gsub_context1_next_glyph_f1.otf": ("GDEF", "GSUB"),
211*e1fe3e4aSElliott Hughes    "aots/gsub_context1_simple_f1.otf": ("GDEF", "GSUB"),
212*e1fe3e4aSElliott Hughes    "aots/gsub_context1_simple_f2.otf": ("GDEF", "GSUB"),
213*e1fe3e4aSElliott Hughes    "aots/gsub_context1_successive_f1.otf": ("GDEF", "GSUB"),
214*e1fe3e4aSElliott Hughes    "aots/gsub_context2_boundary_f1.otf": ("GDEF", "GSUB"),
215*e1fe3e4aSElliott Hughes    "aots/gsub_context2_boundary_f2.otf": ("GDEF", "GSUB"),
216*e1fe3e4aSElliott Hughes    "aots/gsub_context2_classes_f1.otf": ("GDEF", "GSUB"),
217*e1fe3e4aSElliott Hughes    "aots/gsub_context2_classes_f2.otf": ("GDEF", "GSUB"),
218*e1fe3e4aSElliott Hughes    "aots/gsub_context2_expansion_f1.otf": ("GDEF", "GSUB"),
219*e1fe3e4aSElliott Hughes    "aots/gsub_context2_lookupflag_f1.otf": ("GDEF", "GSUB"),
220*e1fe3e4aSElliott Hughes    "aots/gsub_context2_lookupflag_f2.otf": ("GDEF", "GSUB"),
221*e1fe3e4aSElliott Hughes    "aots/gsub_context2_multiple_subrules_f1.otf": ("GDEF", "GSUB"),
222*e1fe3e4aSElliott Hughes    "aots/gsub_context2_multiple_subrules_f2.otf": ("GDEF", "GSUB"),
223*e1fe3e4aSElliott Hughes    "aots/gsub_context2_next_glyph_f1.otf": ("GDEF", "GSUB"),
224*e1fe3e4aSElliott Hughes    "aots/gsub_context2_simple_f1.otf": ("GDEF", "GSUB"),
225*e1fe3e4aSElliott Hughes    "aots/gsub_context2_simple_f2.otf": ("GDEF", "GSUB"),
226*e1fe3e4aSElliott Hughes    "aots/gsub_context2_successive_f1.otf": ("GDEF", "GSUB"),
227*e1fe3e4aSElliott Hughes    "aots/gsub_context3_boundary_f1.otf": ("GDEF", "GSUB"),
228*e1fe3e4aSElliott Hughes    "aots/gsub_context3_boundary_f2.otf": ("GDEF", "GSUB"),
229*e1fe3e4aSElliott Hughes    "aots/gsub_context3_lookupflag_f1.otf": ("GDEF", "GSUB"),
230*e1fe3e4aSElliott Hughes    "aots/gsub_context3_lookupflag_f2.otf": ("GDEF", "GSUB"),
231*e1fe3e4aSElliott Hughes    "aots/gsub_context3_next_glyph_f1.otf": ("GDEF", "GSUB"),
232*e1fe3e4aSElliott Hughes    "aots/gsub_context3_simple_f1.otf": ("GDEF", "GSUB"),
233*e1fe3e4aSElliott Hughes    "aots/gsub_context3_successive_f1.otf": ("GDEF", "GSUB"),
234*e1fe3e4aSElliott Hughes    "aots/lookupflag_ignore_attach_f1.otf": ("GDEF", "GSUB"),
235*e1fe3e4aSElliott Hughes    "aots/lookupflag_ignore_base_f1.otf": ("GDEF", "GSUB"),
236*e1fe3e4aSElliott Hughes    "aots/lookupflag_ignore_combination_f1.otf": ("GDEF", "GSUB"),
237*e1fe3e4aSElliott Hughes    "aots/lookupflag_ignore_ligatures_f1.otf": ("GDEF", "GSUB"),
238*e1fe3e4aSElliott Hughes    "aots/lookupflag_ignore_marks_f1.otf": ("GDEF", "GSUB"),
239*e1fe3e4aSElliott Hughes    "graphite/graphite_tests.ttf": ("Silf", "Glat", "Feat", "Sill"),
240*e1fe3e4aSElliott Hughes}
241*e1fe3e4aSElliott Hughes
242*e1fe3e4aSElliott Hughes
243*e1fe3e4aSElliott HughesTEST_REQUIREMENTS = {
244*e1fe3e4aSElliott Hughes    "aots/cmap4_font4.otf": ("unicodedata2",),
245*e1fe3e4aSElliott Hughes}
246*e1fe3e4aSElliott Hughes
247*e1fe3e4aSElliott Hughes
248*e1fe3e4aSElliott HughesttLibVersion_RE = re.compile(r' ttLibVersion=".*"')
249*e1fe3e4aSElliott Hughes
250*e1fe3e4aSElliott Hughes
251*e1fe3e4aSElliott Hughesdef getpath(testfile):
252*e1fe3e4aSElliott Hughes    path = os.path.dirname(__file__)
253*e1fe3e4aSElliott Hughes    return os.path.join(path, "data", testfile)
254*e1fe3e4aSElliott Hughes
255*e1fe3e4aSElliott Hughes
256*e1fe3e4aSElliott Hughesdef read_expected_ttx(testfile, tableTag):
257*e1fe3e4aSElliott Hughes    name = os.path.splitext(testfile)[0]
258*e1fe3e4aSElliott Hughes    xml_expected_path = getpath("%s.ttx.%s" % (name, tagToXML(tableTag)))
259*e1fe3e4aSElliott Hughes    with open(xml_expected_path, "r", encoding="utf-8") as xml_file:
260*e1fe3e4aSElliott Hughes        xml_expected = ttLibVersion_RE.sub("", xml_file.read())
261*e1fe3e4aSElliott Hughes    return xml_expected
262*e1fe3e4aSElliott Hughes
263*e1fe3e4aSElliott Hughes
264*e1fe3e4aSElliott Hughesdef dump_ttx(font, tableTag):
265*e1fe3e4aSElliott Hughes    f = StringIO()
266*e1fe3e4aSElliott Hughes    font.saveXML(f, tables=[tableTag])
267*e1fe3e4aSElliott Hughes    return ttLibVersion_RE.sub("", f.getvalue())
268*e1fe3e4aSElliott Hughes
269*e1fe3e4aSElliott Hughes
270*e1fe3e4aSElliott Hughesdef load_ttx(ttx):
271*e1fe3e4aSElliott Hughes    f = StringIO()
272*e1fe3e4aSElliott Hughes    f.write(ttx)
273*e1fe3e4aSElliott Hughes    f.seek(0)
274*e1fe3e4aSElliott Hughes    font = TTFont()
275*e1fe3e4aSElliott Hughes    font.importXML(f)
276*e1fe3e4aSElliott Hughes    return font
277*e1fe3e4aSElliott Hughes
278*e1fe3e4aSElliott Hughes
279*e1fe3e4aSElliott Hughes@contextlib.contextmanager
280*e1fe3e4aSElliott Hughesdef open_font(testfile):
281*e1fe3e4aSElliott Hughes    font = TTFont(getpath(testfile))
282*e1fe3e4aSElliott Hughes    try:
283*e1fe3e4aSElliott Hughes        yield font
284*e1fe3e4aSElliott Hughes    finally:
285*e1fe3e4aSElliott Hughes        font.close()
286*e1fe3e4aSElliott Hughes
287*e1fe3e4aSElliott Hughes
288*e1fe3e4aSElliott Hughesdef _skip_if_requirement_missing(testfile):
289*e1fe3e4aSElliott Hughes    if testfile in TEST_REQUIREMENTS:
290*e1fe3e4aSElliott Hughes        for req in TEST_REQUIREMENTS[testfile]:
291*e1fe3e4aSElliott Hughes            if globals()[req] is None:
292*e1fe3e4aSElliott Hughes                pytest.skip("%s not installed" % req)
293*e1fe3e4aSElliott Hughes
294*e1fe3e4aSElliott Hughes
295*e1fe3e4aSElliott Hughesdef test_xml_from_binary(testfile, tableTag):
296*e1fe3e4aSElliott Hughes    """Check XML from decompiled object."""
297*e1fe3e4aSElliott Hughes    _skip_if_requirement_missing(testfile)
298*e1fe3e4aSElliott Hughes
299*e1fe3e4aSElliott Hughes    xml_expected = read_expected_ttx(testfile, tableTag)
300*e1fe3e4aSElliott Hughes
301*e1fe3e4aSElliott Hughes    with open_font(testfile) as font:
302*e1fe3e4aSElliott Hughes        xml_from_binary = dump_ttx(font, tableTag)
303*e1fe3e4aSElliott Hughes
304*e1fe3e4aSElliott Hughes    assert xml_expected == xml_from_binary
305*e1fe3e4aSElliott Hughes
306*e1fe3e4aSElliott Hughes
307*e1fe3e4aSElliott Hughesdef test_xml_from_xml(testfile, tableTag):
308*e1fe3e4aSElliott Hughes    """Check XML from object read from XML."""
309*e1fe3e4aSElliott Hughes    _skip_if_requirement_missing(testfile)
310*e1fe3e4aSElliott Hughes
311*e1fe3e4aSElliott Hughes    xml_expected = read_expected_ttx(testfile, tableTag)
312*e1fe3e4aSElliott Hughes
313*e1fe3e4aSElliott Hughes    font = load_ttx(xml_expected)
314*e1fe3e4aSElliott Hughes    name = os.path.splitext(testfile)[0]
315*e1fe3e4aSElliott Hughes    setupfile = getpath("%s.ttx.%s.setup" % (name, tagToXML(tableTag)))
316*e1fe3e4aSElliott Hughes    if os.path.exists(setupfile):
317*e1fe3e4aSElliott Hughes        #        import pdb; pdb.set_trace()
318*e1fe3e4aSElliott Hughes        font.importXML(setupfile)
319*e1fe3e4aSElliott Hughes    xml_from_xml = dump_ttx(font, tableTag)
320*e1fe3e4aSElliott Hughes
321*e1fe3e4aSElliott Hughes    assert xml_expected == xml_from_xml
322*e1fe3e4aSElliott Hughes
323*e1fe3e4aSElliott Hughes
324*e1fe3e4aSElliott Hughesdef pytest_generate_tests(metafunc):
325*e1fe3e4aSElliott Hughes    # http://doc.pytest.org/en/latest/parametrize.html#basic-pytest-generate-tests-example
326*e1fe3e4aSElliott Hughes    fixturenames = metafunc.fixturenames
327*e1fe3e4aSElliott Hughes    argnames = ("testfile", "tableTag")
328*e1fe3e4aSElliott Hughes    if all(fn in fixturenames for fn in argnames):
329*e1fe3e4aSElliott Hughes        argvalues = [
330*e1fe3e4aSElliott Hughes            (testfile, tableTag)
331*e1fe3e4aSElliott Hughes            for testfile, tableTags in sorted(TESTS.items())
332*e1fe3e4aSElliott Hughes            for tableTag in tableTags
333*e1fe3e4aSElliott Hughes        ]
334*e1fe3e4aSElliott Hughes        metafunc.parametrize(argnames, argvalues)
335*e1fe3e4aSElliott Hughes
336*e1fe3e4aSElliott Hughes
337*e1fe3e4aSElliott Hughesif __name__ == "__main__":
338*e1fe3e4aSElliott Hughes    sys.exit(pytest.main(sys.argv))
339