xref: /aosp_15_r20/external/fonttools/Tests/ufoLib/UFOConversion_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughesimport os
2*e1fe3e4aSElliott Hughesimport shutil
3*e1fe3e4aSElliott Hughesimport unittest
4*e1fe3e4aSElliott Hughesimport tempfile
5*e1fe3e4aSElliott Hughesfrom io import open
6*e1fe3e4aSElliott Hughesfrom fontTools.ufoLib import UFOReader, UFOWriter
7*e1fe3e4aSElliott Hughesfrom fontTools.ufoLib import plistlib
8*e1fe3e4aSElliott Hughesfrom .testSupport import expectedFontInfo1To2Conversion, expectedFontInfo2To1Conversion
9*e1fe3e4aSElliott Hughes
10*e1fe3e4aSElliott Hughes
11*e1fe3e4aSElliott Hughes# the format version 1 lib.plist contains some data
12*e1fe3e4aSElliott Hughes# that these tests shouldn't be concerned about.
13*e1fe3e4aSElliott HughesremoveFromFormatVersion1Lib = [
14*e1fe3e4aSElliott Hughes    "org.robofab.opentype.classes",
15*e1fe3e4aSElliott Hughes    "org.robofab.opentype.features",
16*e1fe3e4aSElliott Hughes    "org.robofab.opentype.featureorder",
17*e1fe3e4aSElliott Hughes    "org.robofab.postScriptHintData",
18*e1fe3e4aSElliott Hughes]
19*e1fe3e4aSElliott Hughes
20*e1fe3e4aSElliott Hughes
21*e1fe3e4aSElliott Hughesclass ConversionFunctionsTestCase(unittest.TestCase):
22*e1fe3e4aSElliott Hughes    def tearDown(self):
23*e1fe3e4aSElliott Hughes        path = self.getFontPath("TestFont1 (UFO1) converted.ufo")
24*e1fe3e4aSElliott Hughes        if os.path.exists(path):
25*e1fe3e4aSElliott Hughes            shutil.rmtree(path)
26*e1fe3e4aSElliott Hughes        path = self.getFontPath("TestFont1 (UFO2) converted.ufo")
27*e1fe3e4aSElliott Hughes        if os.path.exists(path):
28*e1fe3e4aSElliott Hughes            shutil.rmtree(path)
29*e1fe3e4aSElliott Hughes
30*e1fe3e4aSElliott Hughes    def getFontPath(self, fileName):
31*e1fe3e4aSElliott Hughes        testdata = os.path.join(os.path.dirname(__file__), "testdata")
32*e1fe3e4aSElliott Hughes        return os.path.join(testdata, fileName)
33*e1fe3e4aSElliott Hughes
34*e1fe3e4aSElliott Hughes    def compareFileStructures(self, path1, path2, expectedInfoData, testFeatures):
35*e1fe3e4aSElliott Hughes        # result
36*e1fe3e4aSElliott Hughes        metainfoPath1 = os.path.join(path1, "metainfo.plist")
37*e1fe3e4aSElliott Hughes        fontinfoPath1 = os.path.join(path1, "fontinfo.plist")
38*e1fe3e4aSElliott Hughes        kerningPath1 = os.path.join(path1, "kerning.plist")
39*e1fe3e4aSElliott Hughes        groupsPath1 = os.path.join(path1, "groups.plist")
40*e1fe3e4aSElliott Hughes        libPath1 = os.path.join(path1, "lib.plist")
41*e1fe3e4aSElliott Hughes        featuresPath1 = os.path.join(path1, "features.plist")
42*e1fe3e4aSElliott Hughes        glyphsPath1 = os.path.join(path1, "glyphs")
43*e1fe3e4aSElliott Hughes        glyphsPath1_contents = os.path.join(glyphsPath1, "contents.plist")
44*e1fe3e4aSElliott Hughes        glyphsPath1_A = os.path.join(glyphsPath1, "A_.glif")
45*e1fe3e4aSElliott Hughes        glyphsPath1_B = os.path.join(glyphsPath1, "B_.glif")
46*e1fe3e4aSElliott Hughes        # expected result
47*e1fe3e4aSElliott Hughes        metainfoPath2 = os.path.join(path2, "metainfo.plist")
48*e1fe3e4aSElliott Hughes        fontinfoPath2 = os.path.join(path2, "fontinfo.plist")
49*e1fe3e4aSElliott Hughes        kerningPath2 = os.path.join(path2, "kerning.plist")
50*e1fe3e4aSElliott Hughes        groupsPath2 = os.path.join(path2, "groups.plist")
51*e1fe3e4aSElliott Hughes        libPath2 = os.path.join(path2, "lib.plist")
52*e1fe3e4aSElliott Hughes        featuresPath2 = os.path.join(path2, "features.plist")
53*e1fe3e4aSElliott Hughes        glyphsPath2 = os.path.join(path2, "glyphs")
54*e1fe3e4aSElliott Hughes        glyphsPath2_contents = os.path.join(glyphsPath2, "contents.plist")
55*e1fe3e4aSElliott Hughes        glyphsPath2_A = os.path.join(glyphsPath2, "A_.glif")
56*e1fe3e4aSElliott Hughes        glyphsPath2_B = os.path.join(glyphsPath2, "B_.glif")
57*e1fe3e4aSElliott Hughes        # look for existence
58*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(metainfoPath1), True)
59*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(fontinfoPath1), True)
60*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(kerningPath1), True)
61*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(groupsPath1), True)
62*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(libPath1), True)
63*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(glyphsPath1), True)
64*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(glyphsPath1_contents), True)
65*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(glyphsPath1_A), True)
66*e1fe3e4aSElliott Hughes        self.assertEqual(os.path.exists(glyphsPath1_B), True)
67*e1fe3e4aSElliott Hughes        if testFeatures:
68*e1fe3e4aSElliott Hughes            self.assertEqual(os.path.exists(featuresPath1), True)
69*e1fe3e4aSElliott Hughes        # look for aggrement
70*e1fe3e4aSElliott Hughes        with open(metainfoPath1, "rb") as f:
71*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
72*e1fe3e4aSElliott Hughes        with open(metainfoPath2, "rb") as f:
73*e1fe3e4aSElliott Hughes            data2 = plistlib.load(f)
74*e1fe3e4aSElliott Hughes        self.assertEqual(data1, data2)
75*e1fe3e4aSElliott Hughes        with open(fontinfoPath1, "rb") as f:
76*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
77*e1fe3e4aSElliott Hughes        self.assertEqual(sorted(data1.items()), sorted(expectedInfoData.items()))
78*e1fe3e4aSElliott Hughes        with open(kerningPath1, "rb") as f:
79*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
80*e1fe3e4aSElliott Hughes        with open(kerningPath2, "rb") as f:
81*e1fe3e4aSElliott Hughes            data2 = plistlib.load(f)
82*e1fe3e4aSElliott Hughes        self.assertEqual(data1, data2)
83*e1fe3e4aSElliott Hughes        with open(groupsPath1, "rb") as f:
84*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
85*e1fe3e4aSElliott Hughes        with open(groupsPath2, "rb") as f:
86*e1fe3e4aSElliott Hughes            data2 = plistlib.load(f)
87*e1fe3e4aSElliott Hughes        self.assertEqual(data1, data2)
88*e1fe3e4aSElliott Hughes        with open(libPath1, "rb") as f:
89*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
90*e1fe3e4aSElliott Hughes        with open(libPath2, "rb") as f:
91*e1fe3e4aSElliott Hughes            data2 = plistlib.load(f)
92*e1fe3e4aSElliott Hughes        if "UFO1" in libPath1:
93*e1fe3e4aSElliott Hughes            for key in removeFromFormatVersion1Lib:
94*e1fe3e4aSElliott Hughes                if key in data1:
95*e1fe3e4aSElliott Hughes                    del data1[key]
96*e1fe3e4aSElliott Hughes        if "UFO1" in libPath2:
97*e1fe3e4aSElliott Hughes            for key in removeFromFormatVersion1Lib:
98*e1fe3e4aSElliott Hughes                if key in data2:
99*e1fe3e4aSElliott Hughes                    del data2[key]
100*e1fe3e4aSElliott Hughes        self.assertEqual(data1, data2)
101*e1fe3e4aSElliott Hughes        with open(glyphsPath1_contents, "rb") as f:
102*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
103*e1fe3e4aSElliott Hughes        with open(glyphsPath2_contents, "rb") as f:
104*e1fe3e4aSElliott Hughes            data2 = plistlib.load(f)
105*e1fe3e4aSElliott Hughes        self.assertEqual(data1, data2)
106*e1fe3e4aSElliott Hughes        with open(glyphsPath1_A, "rb") as f:
107*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
108*e1fe3e4aSElliott Hughes        with open(glyphsPath2_A, "rb") as f:
109*e1fe3e4aSElliott Hughes            data2 = plistlib.load(f)
110*e1fe3e4aSElliott Hughes        self.assertEqual(data1, data2)
111*e1fe3e4aSElliott Hughes        with open(glyphsPath1_B, "rb") as f:
112*e1fe3e4aSElliott Hughes            data1 = plistlib.load(f)
113*e1fe3e4aSElliott Hughes        with open(glyphsPath2_B, "rb") as f:
114*e1fe3e4aSElliott Hughes            data2 = plistlib.load(f)
115*e1fe3e4aSElliott Hughes        self.assertEqual(data1, data2)
116*e1fe3e4aSElliott Hughes
117*e1fe3e4aSElliott Hughes
118*e1fe3e4aSElliott Hughes# ---------------------
119*e1fe3e4aSElliott Hughes# kerning up conversion
120*e1fe3e4aSElliott Hughes# ---------------------
121*e1fe3e4aSElliott Hughes
122*e1fe3e4aSElliott Hughes
123*e1fe3e4aSElliott Hughesclass TestInfoObject:
124*e1fe3e4aSElliott Hughes    pass
125*e1fe3e4aSElliott Hughes
126*e1fe3e4aSElliott Hughes
127*e1fe3e4aSElliott Hughesclass KerningUpConversionTestCase(unittest.TestCase):
128*e1fe3e4aSElliott Hughes    expectedKerning = {
129*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "public.kern2.CGroup"): 7,
130*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "public.kern2.DGroup"): 8,
131*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "A"): 5,
132*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "B"): 6,
133*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "public.kern2.CGroup"): 11,
134*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "public.kern2.DGroup"): 12,
135*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "A"): 9,
136*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "B"): 10,
137*e1fe3e4aSElliott Hughes        ("A", "public.kern2.CGroup"): 3,
138*e1fe3e4aSElliott Hughes        ("A", "public.kern2.DGroup"): 4,
139*e1fe3e4aSElliott Hughes        ("A", "A"): 1,
140*e1fe3e4aSElliott Hughes        ("A", "B"): 2,
141*e1fe3e4aSElliott Hughes        ("X", "A"): 13,
142*e1fe3e4aSElliott Hughes        ("X", "public.kern2.CGroup"): 14,
143*e1fe3e4aSElliott Hughes    }
144*e1fe3e4aSElliott Hughes
145*e1fe3e4aSElliott Hughes    expectedGroups = {
146*e1fe3e4aSElliott Hughes        "BGroup": ["B"],
147*e1fe3e4aSElliott Hughes        "CGroup": ["C", "Ccedilla"],
148*e1fe3e4aSElliott Hughes        "DGroup": ["D"],
149*e1fe3e4aSElliott Hughes        "public.kern1.BGroup": ["B"],
150*e1fe3e4aSElliott Hughes        "public.kern1.CGroup": ["C", "Ccedilla"],
151*e1fe3e4aSElliott Hughes        "public.kern2.CGroup": ["C", "Ccedilla"],
152*e1fe3e4aSElliott Hughes        "public.kern2.DGroup": ["D"],
153*e1fe3e4aSElliott Hughes        "Not A Kerning Group": ["A"],
154*e1fe3e4aSElliott Hughes        "X": ["X", "X.sc"],
155*e1fe3e4aSElliott Hughes    }
156*e1fe3e4aSElliott Hughes
157*e1fe3e4aSElliott Hughes    def setUp(self):
158*e1fe3e4aSElliott Hughes        self.tempDir = tempfile.mktemp()
159*e1fe3e4aSElliott Hughes        os.mkdir(self.tempDir)
160*e1fe3e4aSElliott Hughes        self.ufoPath = os.path.join(self.tempDir, "test.ufo")
161*e1fe3e4aSElliott Hughes
162*e1fe3e4aSElliott Hughes    def tearDown(self):
163*e1fe3e4aSElliott Hughes        shutil.rmtree(self.tempDir)
164*e1fe3e4aSElliott Hughes
165*e1fe3e4aSElliott Hughes    def makeUFO(self, formatVersion):
166*e1fe3e4aSElliott Hughes        self.clearUFO()
167*e1fe3e4aSElliott Hughes        if not os.path.exists(self.ufoPath):
168*e1fe3e4aSElliott Hughes            os.mkdir(self.ufoPath)
169*e1fe3e4aSElliott Hughes
170*e1fe3e4aSElliott Hughes        # glyphs
171*e1fe3e4aSElliott Hughes        glyphsPath = os.path.join(self.ufoPath, "glyphs")
172*e1fe3e4aSElliott Hughes        if not os.path.exists(glyphsPath):
173*e1fe3e4aSElliott Hughes            os.mkdir(glyphsPath)
174*e1fe3e4aSElliott Hughes        glyphFile = "X_.glif"
175*e1fe3e4aSElliott Hughes        glyphsContents = dict(X=glyphFile)
176*e1fe3e4aSElliott Hughes        path = os.path.join(glyphsPath, "contents.plist")
177*e1fe3e4aSElliott Hughes        with open(path, "wb") as f:
178*e1fe3e4aSElliott Hughes            plistlib.dump(glyphsContents, f)
179*e1fe3e4aSElliott Hughes        path = os.path.join(glyphsPath, glyphFile)
180*e1fe3e4aSElliott Hughes        with open(path, "w") as f:
181*e1fe3e4aSElliott Hughes            f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
182*e1fe3e4aSElliott Hughes
183*e1fe3e4aSElliott Hughes        # metainfo.plist
184*e1fe3e4aSElliott Hughes        metaInfo = dict(creator="test", formatVersion=formatVersion)
185*e1fe3e4aSElliott Hughes        path = os.path.join(self.ufoPath, "metainfo.plist")
186*e1fe3e4aSElliott Hughes        with open(path, "wb") as f:
187*e1fe3e4aSElliott Hughes            plistlib.dump(metaInfo, f)
188*e1fe3e4aSElliott Hughes        # kerning
189*e1fe3e4aSElliott Hughes        kerning = {
190*e1fe3e4aSElliott Hughes            "A": {"A": 1, "B": 2, "CGroup": 3, "DGroup": 4},
191*e1fe3e4aSElliott Hughes            "BGroup": {"A": 5, "B": 6, "CGroup": 7, "DGroup": 8},
192*e1fe3e4aSElliott Hughes            "CGroup": {"A": 9, "B": 10, "CGroup": 11, "DGroup": 12},
193*e1fe3e4aSElliott Hughes            "X": {"A": 13, "CGroup": 14},
194*e1fe3e4aSElliott Hughes        }
195*e1fe3e4aSElliott Hughes        path = os.path.join(self.ufoPath, "kerning.plist")
196*e1fe3e4aSElliott Hughes        with open(path, "wb") as f:
197*e1fe3e4aSElliott Hughes            plistlib.dump(kerning, f)
198*e1fe3e4aSElliott Hughes        # groups
199*e1fe3e4aSElliott Hughes        groups = {
200*e1fe3e4aSElliott Hughes            "BGroup": ["B"],
201*e1fe3e4aSElliott Hughes            "CGroup": ["C", "Ccedilla"],
202*e1fe3e4aSElliott Hughes            "DGroup": ["D"],
203*e1fe3e4aSElliott Hughes            "Not A Kerning Group": ["A"],
204*e1fe3e4aSElliott Hughes            "X": ["X", "X.sc"],  # a group with a name that is also a glyph name
205*e1fe3e4aSElliott Hughes        }
206*e1fe3e4aSElliott Hughes        path = os.path.join(self.ufoPath, "groups.plist")
207*e1fe3e4aSElliott Hughes        with open(path, "wb") as f:
208*e1fe3e4aSElliott Hughes            plistlib.dump(groups, f)
209*e1fe3e4aSElliott Hughes        # font info
210*e1fe3e4aSElliott Hughes        fontInfo = {"familyName": "Test"}
211*e1fe3e4aSElliott Hughes        path = os.path.join(self.ufoPath, "fontinfo.plist")
212*e1fe3e4aSElliott Hughes        with open(path, "wb") as f:
213*e1fe3e4aSElliott Hughes            plistlib.dump(fontInfo, f)
214*e1fe3e4aSElliott Hughes
215*e1fe3e4aSElliott Hughes    def clearUFO(self):
216*e1fe3e4aSElliott Hughes        if os.path.exists(self.ufoPath):
217*e1fe3e4aSElliott Hughes            shutil.rmtree(self.ufoPath)
218*e1fe3e4aSElliott Hughes
219*e1fe3e4aSElliott Hughes    def testUFO1(self):
220*e1fe3e4aSElliott Hughes        self.makeUFO(formatVersion=2)
221*e1fe3e4aSElliott Hughes        reader = UFOReader(self.ufoPath, validate=True)
222*e1fe3e4aSElliott Hughes        kerning = reader.readKerning()
223*e1fe3e4aSElliott Hughes        self.assertEqual(self.expectedKerning, kerning)
224*e1fe3e4aSElliott Hughes        groups = reader.readGroups()
225*e1fe3e4aSElliott Hughes        self.assertEqual(self.expectedGroups, groups)
226*e1fe3e4aSElliott Hughes        info = TestInfoObject()
227*e1fe3e4aSElliott Hughes        reader.readInfo(info)
228*e1fe3e4aSElliott Hughes
229*e1fe3e4aSElliott Hughes    def testUFO2(self):
230*e1fe3e4aSElliott Hughes        self.makeUFO(formatVersion=2)
231*e1fe3e4aSElliott Hughes        reader = UFOReader(self.ufoPath, validate=True)
232*e1fe3e4aSElliott Hughes        kerning = reader.readKerning()
233*e1fe3e4aSElliott Hughes        self.assertEqual(self.expectedKerning, kerning)
234*e1fe3e4aSElliott Hughes        groups = reader.readGroups()
235*e1fe3e4aSElliott Hughes        self.assertEqual(self.expectedGroups, groups)
236*e1fe3e4aSElliott Hughes        info = TestInfoObject()
237*e1fe3e4aSElliott Hughes        reader.readInfo(info)
238*e1fe3e4aSElliott Hughes
239*e1fe3e4aSElliott Hughes
240*e1fe3e4aSElliott Hughesclass KerningDownConversionTestCase(unittest.TestCase):
241*e1fe3e4aSElliott Hughes    expectedKerning = {
242*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "public.kern2.CGroup"): 7,
243*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "public.kern2.DGroup"): 8,
244*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "A"): 5,
245*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "B"): 6,
246*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "public.kern2.CGroup"): 11,
247*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "public.kern2.DGroup"): 12,
248*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "A"): 9,
249*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "B"): 10,
250*e1fe3e4aSElliott Hughes        ("A", "public.kern2.CGroup"): 3,
251*e1fe3e4aSElliott Hughes        ("A", "public.kern2.DGroup"): 4,
252*e1fe3e4aSElliott Hughes        ("A", "A"): 1,
253*e1fe3e4aSElliott Hughes        ("A", "B"): 2,
254*e1fe3e4aSElliott Hughes    }
255*e1fe3e4aSElliott Hughes
256*e1fe3e4aSElliott Hughes    groups = {
257*e1fe3e4aSElliott Hughes        "BGroup": ["B"],
258*e1fe3e4aSElliott Hughes        "CGroup": ["C"],
259*e1fe3e4aSElliott Hughes        "DGroup": ["D"],
260*e1fe3e4aSElliott Hughes        "public.kern1.BGroup": ["B"],
261*e1fe3e4aSElliott Hughes        "public.kern1.CGroup": ["C", "Ccedilla"],
262*e1fe3e4aSElliott Hughes        "public.kern2.CGroup": ["C", "Ccedilla"],
263*e1fe3e4aSElliott Hughes        "public.kern2.DGroup": ["D"],
264*e1fe3e4aSElliott Hughes        "Not A Kerning Group": ["A"],
265*e1fe3e4aSElliott Hughes    }
266*e1fe3e4aSElliott Hughes    expectedWrittenGroups = {
267*e1fe3e4aSElliott Hughes        "BGroup": ["B"],
268*e1fe3e4aSElliott Hughes        "CGroup": ["C", "Ccedilla"],
269*e1fe3e4aSElliott Hughes        "DGroup": ["D"],
270*e1fe3e4aSElliott Hughes        "Not A Kerning Group": ["A"],
271*e1fe3e4aSElliott Hughes    }
272*e1fe3e4aSElliott Hughes
273*e1fe3e4aSElliott Hughes    kerning = {
274*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "public.kern2.CGroup"): 7,
275*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "public.kern2.DGroup"): 8,
276*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "A"): 5,
277*e1fe3e4aSElliott Hughes        ("public.kern1.BGroup", "B"): 6,
278*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "public.kern2.CGroup"): 11,
279*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "public.kern2.DGroup"): 12,
280*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "A"): 9,
281*e1fe3e4aSElliott Hughes        ("public.kern1.CGroup", "B"): 10,
282*e1fe3e4aSElliott Hughes        ("A", "public.kern2.CGroup"): 3,
283*e1fe3e4aSElliott Hughes        ("A", "public.kern2.DGroup"): 4,
284*e1fe3e4aSElliott Hughes        ("A", "A"): 1,
285*e1fe3e4aSElliott Hughes        ("A", "B"): 2,
286*e1fe3e4aSElliott Hughes    }
287*e1fe3e4aSElliott Hughes    expectedWrittenKerning = {
288*e1fe3e4aSElliott Hughes        "BGroup": {"CGroup": 7, "DGroup": 8, "A": 5, "B": 6},
289*e1fe3e4aSElliott Hughes        "CGroup": {"CGroup": 11, "DGroup": 12, "A": 9, "B": 10},
290*e1fe3e4aSElliott Hughes        "A": {"CGroup": 3, "DGroup": 4, "A": 1, "B": 2},
291*e1fe3e4aSElliott Hughes    }
292*e1fe3e4aSElliott Hughes
293*e1fe3e4aSElliott Hughes    downConversionMapping = {
294*e1fe3e4aSElliott Hughes        "side1": {"BGroup": "public.kern1.BGroup", "CGroup": "public.kern1.CGroup"},
295*e1fe3e4aSElliott Hughes        "side2": {"CGroup": "public.kern2.CGroup", "DGroup": "public.kern2.DGroup"},
296*e1fe3e4aSElliott Hughes    }
297*e1fe3e4aSElliott Hughes
298*e1fe3e4aSElliott Hughes    def setUp(self):
299*e1fe3e4aSElliott Hughes        self.tempDir = tempfile.mktemp()
300*e1fe3e4aSElliott Hughes        os.mkdir(self.tempDir)
301*e1fe3e4aSElliott Hughes        self.dstDir = os.path.join(self.tempDir, "test.ufo")
302*e1fe3e4aSElliott Hughes
303*e1fe3e4aSElliott Hughes    def tearDown(self):
304*e1fe3e4aSElliott Hughes        shutil.rmtree(self.tempDir)
305*e1fe3e4aSElliott Hughes
306*e1fe3e4aSElliott Hughes    def tearDownUFO(self):
307*e1fe3e4aSElliott Hughes        shutil.rmtree(self.dstDir)
308*e1fe3e4aSElliott Hughes
309*e1fe3e4aSElliott Hughes    def testWrite(self):
310*e1fe3e4aSElliott Hughes        writer = UFOWriter(self.dstDir, formatVersion=2)
311*e1fe3e4aSElliott Hughes        writer.setKerningGroupConversionRenameMaps(self.downConversionMapping)
312*e1fe3e4aSElliott Hughes        writer.writeKerning(self.kerning)
313*e1fe3e4aSElliott Hughes        writer.writeGroups(self.groups)
314*e1fe3e4aSElliott Hughes        # test groups
315*e1fe3e4aSElliott Hughes        path = os.path.join(self.dstDir, "groups.plist")
316*e1fe3e4aSElliott Hughes        with open(path, "rb") as f:
317*e1fe3e4aSElliott Hughes            writtenGroups = plistlib.load(f)
318*e1fe3e4aSElliott Hughes        self.assertEqual(writtenGroups, self.expectedWrittenGroups)
319*e1fe3e4aSElliott Hughes        # test kerning
320*e1fe3e4aSElliott Hughes        path = os.path.join(self.dstDir, "kerning.plist")
321*e1fe3e4aSElliott Hughes        with open(path, "rb") as f:
322*e1fe3e4aSElliott Hughes            writtenKerning = plistlib.load(f)
323*e1fe3e4aSElliott Hughes        self.assertEqual(writtenKerning, self.expectedWrittenKerning)
324*e1fe3e4aSElliott Hughes        self.tearDownUFO()
325