1# -*- coding: utf-8 -*-
2from __future__ import absolute_import, unicode_literals
3import os
4import shutil
5import unittest
6import tempfile
7from io import open
8from fontTools.misc.py23 import unicode
9from fontTools.ufoLib import UFOReader, UFOWriter, UFOLibError
10from fontTools.ufoLib.glifLib import GlifLibError
11from fontTools.misc import plistlib
12from .testSupport import fontInfoVersion3
13
14
15class TestInfoObject(object): pass
16
17
18# --------------
19# fontinfo.plist
20# --------------
21
22class ReadFontInfoVersion3TestCase(unittest.TestCase):
23
24	def setUp(self):
25		self.dstDir = tempfile.mktemp()
26		os.mkdir(self.dstDir)
27		metaInfo = {
28			"creator": "test",
29			"formatVersion": 3
30		}
31		path = os.path.join(self.dstDir, "metainfo.plist")
32		with open(path, "wb") as f:
33			plistlib.dump(metaInfo, f)
34
35	def tearDown(self):
36		shutil.rmtree(self.dstDir)
37
38	def _writeInfoToPlist(self, info):
39		path = os.path.join(self.dstDir, "fontinfo.plist")
40		with open(path, "wb") as f:
41			plistlib.dump(info, f)
42
43	def testRead(self):
44		originalData = dict(fontInfoVersion3)
45		self._writeInfoToPlist(originalData)
46		infoObject = TestInfoObject()
47		reader = UFOReader(self.dstDir, validate=True)
48		reader.readInfo(infoObject)
49		readData = {}
50		for attr in list(fontInfoVersion3.keys()):
51			readData[attr] = getattr(infoObject, attr)
52		self.assertEqual(originalData, readData)
53
54	def testGenericRead(self):
55		# familyName
56		info = dict(fontInfoVersion3)
57		info["familyName"] = 123
58		self._writeInfoToPlist(info)
59		reader = UFOReader(self.dstDir, validate=True)
60		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
61		# styleName
62		info = dict(fontInfoVersion3)
63		info["styleName"] = 123
64		self._writeInfoToPlist(info)
65		reader = UFOReader(self.dstDir, validate=True)
66		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
67		# styleMapFamilyName
68		info = dict(fontInfoVersion3)
69		info["styleMapFamilyName"] = 123
70		self._writeInfoToPlist(info)
71		reader = UFOReader(self.dstDir, validate=True)
72		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
73		# styleMapStyleName
74		## not a string
75		info = dict(fontInfoVersion3)
76		info["styleMapStyleName"] = 123
77		self._writeInfoToPlist(info)
78		reader = UFOReader(self.dstDir, validate=True)
79		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
80		## out of range
81		info = dict(fontInfoVersion3)
82		info["styleMapStyleName"] = "REGULAR"
83		self._writeInfoToPlist(info)
84		reader = UFOReader(self.dstDir, validate=True)
85		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
86		# versionMajor
87		info = dict(fontInfoVersion3)
88		info["versionMajor"] = "1"
89		self._writeInfoToPlist(info)
90		reader = UFOReader(self.dstDir, validate=True)
91		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
92		# versionMinor
93		info = dict(fontInfoVersion3)
94		info["versionMinor"] = "0"
95		self._writeInfoToPlist(info)
96		reader = UFOReader(self.dstDir, validate=True)
97		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
98		info = dict(fontInfoVersion3)
99		info["versionMinor"] = -1
100		self._writeInfoToPlist(info)
101		reader = UFOReader(self.dstDir, validate=True)
102		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
103		# copyright
104		info = dict(fontInfoVersion3)
105		info["copyright"] = 123
106		self._writeInfoToPlist(info)
107		reader = UFOReader(self.dstDir, validate=True)
108		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
109		# trademark
110		info = dict(fontInfoVersion3)
111		info["trademark"] = 123
112		self._writeInfoToPlist(info)
113		reader = UFOReader(self.dstDir, validate=True)
114		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
115		# unitsPerEm
116		info = dict(fontInfoVersion3)
117		info["unitsPerEm"] = "abc"
118		self._writeInfoToPlist(info)
119		reader = UFOReader(self.dstDir, validate=True)
120		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
121		info = dict(fontInfoVersion3)
122		info["unitsPerEm"] = -1
123		self._writeInfoToPlist(info)
124		reader = UFOReader(self.dstDir, validate=True)
125		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
126		info = dict(fontInfoVersion3)
127		info["unitsPerEm"] = -1.0
128		self._writeInfoToPlist(info)
129		reader = UFOReader(self.dstDir, validate=True)
130		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
131		# descender
132		info = dict(fontInfoVersion3)
133		info["descender"] = "abc"
134		self._writeInfoToPlist(info)
135		reader = UFOReader(self.dstDir, validate=True)
136		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
137		# xHeight
138		info = dict(fontInfoVersion3)
139		info["xHeight"] = "abc"
140		self._writeInfoToPlist(info)
141		reader = UFOReader(self.dstDir, validate=True)
142		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
143		# capHeight
144		info = dict(fontInfoVersion3)
145		info["capHeight"] = "abc"
146		self._writeInfoToPlist(info)
147		reader = UFOReader(self.dstDir, validate=True)
148		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
149		# ascender
150		info = dict(fontInfoVersion3)
151		info["ascender"] = "abc"
152		self._writeInfoToPlist(info)
153		reader = UFOReader(self.dstDir, validate=True)
154		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
155		# italicAngle
156		info = dict(fontInfoVersion3)
157		info["italicAngle"] = "abc"
158		self._writeInfoToPlist(info)
159		reader = UFOReader(self.dstDir, validate=True)
160		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
161
162	def testGaspRead(self):
163		# not a list
164		info = dict(fontInfoVersion3)
165		info["openTypeGaspRangeRecords"] = "abc"
166		self._writeInfoToPlist(info)
167		reader = UFOReader(self.dstDir, validate=True)
168		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
169		# empty list
170		info = dict(fontInfoVersion3)
171		info["openTypeGaspRangeRecords"] = []
172		self._writeInfoToPlist(info)
173		reader = UFOReader(self.dstDir, validate=True)
174		reader.readInfo(TestInfoObject())
175		# not a dict
176		info = dict(fontInfoVersion3)
177		info["openTypeGaspRangeRecords"] = ["abc"]
178		self._writeInfoToPlist(info)
179		reader = UFOReader(self.dstDir, validate=True)
180		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
181		# dict not properly formatted
182		info = dict(fontInfoVersion3)
183		info["openTypeGaspRangeRecords"] = [dict(rangeMaxPPEM=0xFFFF, notTheRightKey=1)]
184		self._writeInfoToPlist(info)
185		reader = UFOReader(self.dstDir, validate=True)
186		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
187		info = dict(fontInfoVersion3)
188		info["openTypeGaspRangeRecords"] = [dict(notTheRightKey=1, rangeGaspBehavior=[0])]
189		self._writeInfoToPlist(info)
190		reader = UFOReader(self.dstDir, validate=True)
191		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
192		# not an int for ppem
193		info = dict(fontInfoVersion3)
194		info["openTypeGaspRangeRecords"] = [dict(rangeMaxPPEM="abc", rangeGaspBehavior=[0]), dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0])]
195		self._writeInfoToPlist(info)
196		reader = UFOReader(self.dstDir, validate=True)
197		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
198		# not a list for behavior
199		info = dict(fontInfoVersion3)
200		info["openTypeGaspRangeRecords"] = [dict(rangeMaxPPEM=10, rangeGaspBehavior="abc"), dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0])]
201		self._writeInfoToPlist(info)
202		reader = UFOReader(self.dstDir, validate=True)
203		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
204		# invalid behavior value
205		info = dict(fontInfoVersion3)
206		info["openTypeGaspRangeRecords"] = [dict(rangeMaxPPEM=10, rangeGaspBehavior=[-1]), dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0])]
207		self._writeInfoToPlist(info)
208		reader = UFOReader(self.dstDir, validate=True)
209		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
210		# not sorted
211		info = dict(fontInfoVersion3)
212		info["openTypeGaspRangeRecords"] = [dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0]), dict(rangeMaxPPEM=10, rangeGaspBehavior=[0])]
213		self._writeInfoToPlist(info)
214		reader = UFOReader(self.dstDir, validate=True)
215		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
216		# no 0xFFFF
217		info = dict(fontInfoVersion3)
218		info["openTypeGaspRangeRecords"] = [dict(rangeMaxPPEM=10, rangeGaspBehavior=[0]), dict(rangeMaxPPEM=20, rangeGaspBehavior=[0])]
219		self._writeInfoToPlist(info)
220		reader = UFOReader(self.dstDir, validate=True)
221		reader.readInfo(TestInfoObject())
222
223	def testHeadRead(self):
224		# openTypeHeadCreated
225		## not a string
226		info = dict(fontInfoVersion3)
227		info["openTypeHeadCreated"] = 123
228		self._writeInfoToPlist(info)
229		reader = UFOReader(self.dstDir, validate=True)
230		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
231		## invalid format
232		info = dict(fontInfoVersion3)
233		info["openTypeHeadCreated"] = "2000-Jan-01 00:00:00"
234		self._writeInfoToPlist(info)
235		reader = UFOReader(self.dstDir, validate=True)
236		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
237		# openTypeHeadLowestRecPPEM
238		info = dict(fontInfoVersion3)
239		info["openTypeHeadLowestRecPPEM"] = "abc"
240		self._writeInfoToPlist(info)
241		reader = UFOReader(self.dstDir, validate=True)
242		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
243		info = dict(fontInfoVersion3)
244		info["openTypeHeadLowestRecPPEM"] = -1
245		self._writeInfoToPlist(info)
246		reader = UFOReader(self.dstDir, validate=True)
247		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
248		# openTypeHeadFlags
249		info = dict(fontInfoVersion3)
250		info["openTypeHeadFlags"] = [-1]
251		self._writeInfoToPlist(info)
252		reader = UFOReader(self.dstDir, validate=True)
253		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
254
255	def testHheaRead(self):
256		# openTypeHheaAscender
257		info = dict(fontInfoVersion3)
258		info["openTypeHheaAscender"] = "abc"
259		self._writeInfoToPlist(info)
260		reader = UFOReader(self.dstDir, validate=True)
261		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
262		# openTypeHheaDescender
263		info = dict(fontInfoVersion3)
264		info["openTypeHheaDescender"] = "abc"
265		self._writeInfoToPlist(info)
266		reader = UFOReader(self.dstDir, validate=True)
267		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
268		# openTypeHheaLineGap
269		info = dict(fontInfoVersion3)
270		info["openTypeHheaLineGap"] = "abc"
271		self._writeInfoToPlist(info)
272		reader = UFOReader(self.dstDir, validate=True)
273		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
274		# openTypeHheaCaretSlopeRise
275		info = dict(fontInfoVersion3)
276		info["openTypeHheaCaretSlopeRise"] = "abc"
277		self._writeInfoToPlist(info)
278		reader = UFOReader(self.dstDir, validate=True)
279		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
280		# openTypeHheaCaretSlopeRun
281		info = dict(fontInfoVersion3)
282		info["openTypeHheaCaretSlopeRun"] = "abc"
283		self._writeInfoToPlist(info)
284		reader = UFOReader(self.dstDir, validate=True)
285		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
286		# openTypeHheaCaretOffset
287		info = dict(fontInfoVersion3)
288		info["openTypeHheaCaretOffset"] = "abc"
289		self._writeInfoToPlist(info)
290		reader = UFOReader(self.dstDir, validate=True)
291		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
292
293	def testNameRead(self):
294		# openTypeNameDesigner
295		info = dict(fontInfoVersion3)
296		info["openTypeNameDesigner"] = 123
297		self._writeInfoToPlist(info)
298		reader = UFOReader(self.dstDir, validate=True)
299		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
300		# openTypeNameDesignerURL
301		info = dict(fontInfoVersion3)
302		info["openTypeNameDesignerURL"] = 123
303		self._writeInfoToPlist(info)
304		reader = UFOReader(self.dstDir, validate=True)
305		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
306		# openTypeNameManufacturer
307		info = dict(fontInfoVersion3)
308		info["openTypeNameManufacturer"] = 123
309		self._writeInfoToPlist(info)
310		reader = UFOReader(self.dstDir, validate=True)
311		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
312		# openTypeNameManufacturerURL
313		info = dict(fontInfoVersion3)
314		info["openTypeNameManufacturerURL"] = 123
315		self._writeInfoToPlist(info)
316		reader = UFOReader(self.dstDir, validate=True)
317		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
318		# openTypeNameLicense
319		info = dict(fontInfoVersion3)
320		info["openTypeNameLicense"] = 123
321		self._writeInfoToPlist(info)
322		reader = UFOReader(self.dstDir, validate=True)
323		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
324		# openTypeNameLicenseURL
325		info = dict(fontInfoVersion3)
326		info["openTypeNameLicenseURL"] = 123
327		self._writeInfoToPlist(info)
328		reader = UFOReader(self.dstDir, validate=True)
329		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
330		# openTypeNameVersion
331		info = dict(fontInfoVersion3)
332		info["openTypeNameVersion"] = 123
333		self._writeInfoToPlist(info)
334		reader = UFOReader(self.dstDir, validate=True)
335		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
336		# openTypeNameUniqueID
337		info = dict(fontInfoVersion3)
338		info["openTypeNameUniqueID"] = 123
339		self._writeInfoToPlist(info)
340		reader = UFOReader(self.dstDir, validate=True)
341		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
342		# openTypeNameDescription
343		info = dict(fontInfoVersion3)
344		info["openTypeNameDescription"] = 123
345		self._writeInfoToPlist(info)
346		reader = UFOReader(self.dstDir, validate=True)
347		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
348		# openTypeNamePreferredFamilyName
349		info = dict(fontInfoVersion3)
350		info["openTypeNamePreferredFamilyName"] = 123
351		self._writeInfoToPlist(info)
352		reader = UFOReader(self.dstDir, validate=True)
353		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
354		# openTypeNamePreferredSubfamilyName
355		info = dict(fontInfoVersion3)
356		info["openTypeNamePreferredSubfamilyName"] = 123
357		self._writeInfoToPlist(info)
358		reader = UFOReader(self.dstDir, validate=True)
359		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
360		# openTypeNameCompatibleFullName
361		info = dict(fontInfoVersion3)
362		info["openTypeNameCompatibleFullName"] = 123
363		self._writeInfoToPlist(info)
364		reader = UFOReader(self.dstDir, validate=True)
365		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
366		# openTypeNameSampleText
367		info = dict(fontInfoVersion3)
368		info["openTypeNameSampleText"] = 123
369		self._writeInfoToPlist(info)
370		reader = UFOReader(self.dstDir, validate=True)
371		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
372		# openTypeNameWWSFamilyName
373		info = dict(fontInfoVersion3)
374		info["openTypeNameWWSFamilyName"] = 123
375		self._writeInfoToPlist(info)
376		reader = UFOReader(self.dstDir, validate=True)
377		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
378		# openTypeNameWWSSubfamilyName
379		info = dict(fontInfoVersion3)
380		info["openTypeNameWWSSubfamilyName"] = 123
381		self._writeInfoToPlist(info)
382		reader = UFOReader(self.dstDir, validate=True)
383		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
384		# openTypeNameRecords
385		## not a list
386		info = dict(fontInfoVersion3)
387		info["openTypeNameRecords"] = "abc"
388		self._writeInfoToPlist(info)
389		reader = UFOReader(self.dstDir, validate=True)
390		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
391		## not a dict
392		info = dict(fontInfoVersion3)
393		info["openTypeNameRecords"] = ["abc"]
394		self._writeInfoToPlist(info)
395		reader = UFOReader(self.dstDir, validate=True)
396		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
397		## invalid dict structure
398		info = dict(fontInfoVersion3)
399		info["openTypeNameRecords"] = [dict(foo="bar")]
400		self._writeInfoToPlist(info)
401		reader = UFOReader(self.dstDir, validate=True)
402		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
403		## incorrect keys
404		info = dict(fontInfoVersion3)
405		info["openTypeNameRecords"] = [
406			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string="Name Record.", foo="bar")
407		]
408		self._writeInfoToPlist(info)
409		reader = UFOReader(self.dstDir, validate=True)
410		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
411		info = dict(fontInfoVersion3)
412		info["openTypeNameRecords"] = [
413			dict(platformID=1, encodingID=1, languageID=1, string="Name Record.")
414		]
415		self._writeInfoToPlist(info)
416		reader = UFOReader(self.dstDir, validate=True)
417		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
418		info = dict(fontInfoVersion3)
419		info["openTypeNameRecords"] = [
420			dict(nameID=1, encodingID=1, languageID=1, string="Name Record.")
421		]
422		self._writeInfoToPlist(info)
423		reader = UFOReader(self.dstDir, validate=True)
424		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
425		info = dict(fontInfoVersion3)
426		info["openTypeNameRecords"] = [
427			dict(nameID=1, platformID=1, languageID=1, string="Name Record.")
428		]
429		self._writeInfoToPlist(info)
430		reader = UFOReader(self.dstDir, validate=True)
431		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
432		info = dict(fontInfoVersion3)
433		info["openTypeNameRecords"] = [
434			dict(nameID=1, platformID=1, encodingID=1, string="Name Record.")
435		]
436		self._writeInfoToPlist(info)
437		reader = UFOReader(self.dstDir, validate=True)
438		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
439		info = dict(fontInfoVersion3)
440		info["openTypeNameRecords"] = [
441			dict(nameID=1, platformID=1, encodingID=1, languageID=1)
442		]
443		self._writeInfoToPlist(info)
444		reader = UFOReader(self.dstDir, validate=True)
445		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
446		## invalid values
447		info = dict(fontInfoVersion3)
448		info["openTypeNameRecords"] = [
449			dict(nameID="1", platformID=1, encodingID=1, languageID=1, string="Name Record.")
450		]
451		self._writeInfoToPlist(info)
452		reader = UFOReader(self.dstDir, validate=True)
453		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
454		info = dict(fontInfoVersion3)
455		info["openTypeNameRecords"] = [
456			dict(nameID=1, platformID="1", encodingID=1, languageID=1, string="Name Record.")
457		]
458		self._writeInfoToPlist(info)
459		reader = UFOReader(self.dstDir, validate=True)
460		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
461		info = dict(fontInfoVersion3)
462		info["openTypeNameRecords"] = [
463			dict(nameID=1, platformID=1, encodingID="1", languageID=1, string="Name Record.")
464		]
465		self._writeInfoToPlist(info)
466		reader = UFOReader(self.dstDir, validate=True)
467		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
468		info = dict(fontInfoVersion3)
469		info["openTypeNameRecords"] = [
470			dict(nameID=1, platformID=1, encodingID=1, languageID="1", string="Name Record.")
471		]
472		self._writeInfoToPlist(info)
473		reader = UFOReader(self.dstDir, validate=True)
474		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
475		info = dict(fontInfoVersion3)
476		info["openTypeNameRecords"] = [
477			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string=1)
478		]
479		self._writeInfoToPlist(info)
480		reader = UFOReader(self.dstDir, validate=True)
481		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
482		## duplicate
483		info = dict(fontInfoVersion3)
484		info["openTypeNameRecords"] = [
485			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string="Name Record."),
486			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string="Name Record.")
487		]
488		self._writeInfoToPlist(info)
489		reader = UFOReader(self.dstDir, validate=True)
490		reader.readInfo(TestInfoObject())
491
492	def testOS2Read(self):
493		# openTypeOS2WidthClass
494		## not an int
495		info = dict(fontInfoVersion3)
496		info["openTypeOS2WidthClass"] = "abc"
497		self._writeInfoToPlist(info)
498		reader = UFOReader(self.dstDir, validate=True)
499		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
500		## out or range
501		info = dict(fontInfoVersion3)
502		info["openTypeOS2WidthClass"] = 15
503		self._writeInfoToPlist(info)
504		reader = UFOReader(self.dstDir, validate=True)
505		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
506		# openTypeOS2WeightClass
507		info = dict(fontInfoVersion3)
508		## not an int
509		info["openTypeOS2WeightClass"] = "abc"
510		self._writeInfoToPlist(info)
511		reader = UFOReader(self.dstDir, validate=True)
512		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
513		## out of range
514		info["openTypeOS2WeightClass"] = -50
515		self._writeInfoToPlist(info)
516		reader = UFOReader(self.dstDir, validate=True)
517		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
518		# openTypeOS2Selection
519		info = dict(fontInfoVersion3)
520		info["openTypeOS2Selection"] = [-1]
521		self._writeInfoToPlist(info)
522		reader = UFOReader(self.dstDir, validate=True)
523		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
524		# openTypeOS2VendorID
525		info = dict(fontInfoVersion3)
526		info["openTypeOS2VendorID"] = 1234
527		self._writeInfoToPlist(info)
528		reader = UFOReader(self.dstDir, validate=True)
529		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
530		# openTypeOS2Panose
531		## not an int
532		info = dict(fontInfoVersion3)
533		info["openTypeOS2Panose"] = [0, 1, 2, 3, 4, 5, 6, 7, 8, str(9)]
534		self._writeInfoToPlist(info)
535		reader = UFOReader(self.dstDir, validate=True)
536		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
537		## negative
538		info = dict(fontInfoVersion3)
539		info["openTypeOS2Panose"] = [0, 1, 2, 3, 4, 5, 6, 7, 8, -9]
540		self._writeInfoToPlist(info)
541		reader = UFOReader(self.dstDir, validate=True)
542		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
543		## too few values
544		info = dict(fontInfoVersion3)
545		info["openTypeOS2Panose"] = [0, 1, 2, 3]
546		self._writeInfoToPlist(info)
547		reader = UFOReader(self.dstDir, validate=True)
548		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
549		## too many values
550		info = dict(fontInfoVersion3)
551		info["openTypeOS2Panose"] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
552		self._writeInfoToPlist(info)
553		reader = UFOReader(self.dstDir, validate=True)
554		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
555		# openTypeOS2FamilyClass
556		## not an int
557		info = dict(fontInfoVersion3)
558		info["openTypeOS2FamilyClass"] = [1, str(1)]
559		self._writeInfoToPlist(info)
560		reader = UFOReader(self.dstDir, validate=True)
561		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
562		## too few values
563		info = dict(fontInfoVersion3)
564		info["openTypeOS2FamilyClass"] = [1]
565		self._writeInfoToPlist(info)
566		reader = UFOReader(self.dstDir, validate=True)
567		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
568		## too many values
569		info = dict(fontInfoVersion3)
570		info["openTypeOS2FamilyClass"] = [1, 1, 1]
571		self._writeInfoToPlist(info)
572		reader = UFOReader(self.dstDir, validate=True)
573		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
574		## out of range
575		info = dict(fontInfoVersion3)
576		info["openTypeOS2FamilyClass"] = [1, 201]
577		self._writeInfoToPlist(info)
578		reader = UFOReader(self.dstDir, validate=True)
579		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
580		# openTypeOS2UnicodeRanges
581		## not an int
582		info = dict(fontInfoVersion3)
583		info["openTypeOS2UnicodeRanges"] = ["0"]
584		self._writeInfoToPlist(info)
585		reader = UFOReader(self.dstDir, validate=True)
586		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
587		## out of range
588		info = dict(fontInfoVersion3)
589		info["openTypeOS2UnicodeRanges"] = [-1]
590		self._writeInfoToPlist(info)
591		reader = UFOReader(self.dstDir, validate=True)
592		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
593		# openTypeOS2CodePageRanges
594		## not an int
595		info = dict(fontInfoVersion3)
596		info["openTypeOS2CodePageRanges"] = ["0"]
597		self._writeInfoToPlist(info)
598		reader = UFOReader(self.dstDir, validate=True)
599		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
600		## out of range
601		info = dict(fontInfoVersion3)
602		info["openTypeOS2CodePageRanges"] = [-1]
603		self._writeInfoToPlist(info)
604		reader = UFOReader(self.dstDir, validate=True)
605		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
606		# openTypeOS2TypoAscender
607		info = dict(fontInfoVersion3)
608		info["openTypeOS2TypoAscender"] = "abc"
609		self._writeInfoToPlist(info)
610		reader = UFOReader(self.dstDir, validate=True)
611		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
612		# openTypeOS2TypoDescender
613		info = dict(fontInfoVersion3)
614		info["openTypeOS2TypoDescender"] = "abc"
615		self._writeInfoToPlist(info)
616		reader = UFOReader(self.dstDir, validate=True)
617		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
618		# openTypeOS2TypoLineGap
619		info = dict(fontInfoVersion3)
620		info["openTypeOS2TypoLineGap"] = "abc"
621		self._writeInfoToPlist(info)
622		reader = UFOReader(self.dstDir, validate=True)
623		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
624		# openTypeOS2WinAscent
625		info = dict(fontInfoVersion3)
626		info["openTypeOS2WinAscent"] = "abc"
627		self._writeInfoToPlist(info)
628		reader = UFOReader(self.dstDir, validate=True)
629		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
630		info = dict(fontInfoVersion3)
631		info["openTypeOS2WinAscent"] = -1
632		self._writeInfoToPlist(info)
633		reader = UFOReader(self.dstDir, validate=True)
634		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
635		# openTypeOS2WinDescent
636		info = dict(fontInfoVersion3)
637		info["openTypeOS2WinDescent"] = "abc"
638		self._writeInfoToPlist(info)
639		reader = UFOReader(self.dstDir, validate=True)
640		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
641		info = dict(fontInfoVersion3)
642		info["openTypeOS2WinDescent"] = -1
643		self._writeInfoToPlist(info)
644		reader = UFOReader(self.dstDir, validate=True)
645		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
646		# openTypeOS2Type
647		## not an int
648		info = dict(fontInfoVersion3)
649		info["openTypeOS2Type"] = ["1"]
650		self._writeInfoToPlist(info)
651		reader = UFOReader(self.dstDir, validate=True)
652		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
653		## out of range
654		info = dict(fontInfoVersion3)
655		info["openTypeOS2Type"] = [-1]
656		self._writeInfoToPlist(info)
657		reader = UFOReader(self.dstDir, validate=True)
658		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
659		# openTypeOS2SubscriptXSize
660		info = dict(fontInfoVersion3)
661		info["openTypeOS2SubscriptXSize"] = "abc"
662		self._writeInfoToPlist(info)
663		reader = UFOReader(self.dstDir, validate=True)
664		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
665		# openTypeOS2SubscriptYSize
666		info = dict(fontInfoVersion3)
667		info["openTypeOS2SubscriptYSize"] = "abc"
668		self._writeInfoToPlist(info)
669		reader = UFOReader(self.dstDir, validate=True)
670		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
671		# openTypeOS2SubscriptXOffset
672		info = dict(fontInfoVersion3)
673		info["openTypeOS2SubscriptXOffset"] = "abc"
674		self._writeInfoToPlist(info)
675		reader = UFOReader(self.dstDir, validate=True)
676		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
677		# openTypeOS2SubscriptYOffset
678		info = dict(fontInfoVersion3)
679		info["openTypeOS2SubscriptYOffset"] = "abc"
680		self._writeInfoToPlist(info)
681		reader = UFOReader(self.dstDir, validate=True)
682		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
683		# openTypeOS2SuperscriptXSize
684		info = dict(fontInfoVersion3)
685		info["openTypeOS2SuperscriptXSize"] = "abc"
686		self._writeInfoToPlist(info)
687		reader = UFOReader(self.dstDir, validate=True)
688		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
689		# openTypeOS2SuperscriptYSize
690		info = dict(fontInfoVersion3)
691		info["openTypeOS2SuperscriptYSize"] = "abc"
692		self._writeInfoToPlist(info)
693		reader = UFOReader(self.dstDir, validate=True)
694		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
695		# openTypeOS2SuperscriptXOffset
696		info = dict(fontInfoVersion3)
697		info["openTypeOS2SuperscriptXOffset"] = "abc"
698		self._writeInfoToPlist(info)
699		reader = UFOReader(self.dstDir, validate=True)
700		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
701		# openTypeOS2SuperscriptYOffset
702		info = dict(fontInfoVersion3)
703		info["openTypeOS2SuperscriptYOffset"] = "abc"
704		self._writeInfoToPlist(info)
705		reader = UFOReader(self.dstDir, validate=True)
706		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
707		# openTypeOS2StrikeoutSize
708		info = dict(fontInfoVersion3)
709		info["openTypeOS2StrikeoutSize"] = "abc"
710		self._writeInfoToPlist(info)
711		reader = UFOReader(self.dstDir, validate=True)
712		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
713		# openTypeOS2StrikeoutPosition
714		info = dict(fontInfoVersion3)
715		info["openTypeOS2StrikeoutPosition"] = "abc"
716		self._writeInfoToPlist(info)
717		reader = UFOReader(self.dstDir, validate=True)
718		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
719
720	def testVheaRead(self):
721		# openTypeVheaVertTypoAscender
722		info = dict(fontInfoVersion3)
723		info["openTypeVheaVertTypoAscender"] = "abc"
724		self._writeInfoToPlist(info)
725		reader = UFOReader(self.dstDir, validate=True)
726		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
727		# openTypeVheaVertTypoDescender
728		info = dict(fontInfoVersion3)
729		info["openTypeVheaVertTypoDescender"] = "abc"
730		self._writeInfoToPlist(info)
731		reader = UFOReader(self.dstDir, validate=True)
732		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
733		# openTypeVheaVertTypoLineGap
734		info = dict(fontInfoVersion3)
735		info["openTypeVheaVertTypoLineGap"] = "abc"
736		self._writeInfoToPlist(info)
737		reader = UFOReader(self.dstDir, validate=True)
738		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
739		# openTypeVheaCaretSlopeRise
740		info = dict(fontInfoVersion3)
741		info["openTypeVheaCaretSlopeRise"] = "abc"
742		self._writeInfoToPlist(info)
743		reader = UFOReader(self.dstDir, validate=True)
744		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
745		# openTypeVheaCaretSlopeRun
746		info = dict(fontInfoVersion3)
747		info["openTypeVheaCaretSlopeRun"] = "abc"
748		self._writeInfoToPlist(info)
749		reader = UFOReader(self.dstDir, validate=True)
750		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
751		# openTypeVheaCaretOffset
752		info = dict(fontInfoVersion3)
753		info["openTypeVheaCaretOffset"] = "abc"
754		self._writeInfoToPlist(info)
755		reader = UFOReader(self.dstDir, validate=True)
756		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
757
758	def testFONDRead(self):
759		# macintoshFONDFamilyID
760		info = dict(fontInfoVersion3)
761		info["macintoshFONDFamilyID"] = "abc"
762		self._writeInfoToPlist(info)
763		reader = UFOReader(self.dstDir, validate=True)
764		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
765		# macintoshFONDName
766		info = dict(fontInfoVersion3)
767		info["macintoshFONDName"] = 123
768		self._writeInfoToPlist(info)
769		reader = UFOReader(self.dstDir, validate=True)
770		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
771
772	def testPostscriptRead(self):
773		# postscriptFontName
774		info = dict(fontInfoVersion3)
775		info["postscriptFontName"] = 123
776		self._writeInfoToPlist(info)
777		reader = UFOReader(self.dstDir, validate=True)
778		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
779		# postscriptFullName
780		info = dict(fontInfoVersion3)
781		info["postscriptFullName"] = 123
782		self._writeInfoToPlist(info)
783		reader = UFOReader(self.dstDir, validate=True)
784		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
785		# postscriptSlantAngle
786		info = dict(fontInfoVersion3)
787		info["postscriptSlantAngle"] = "abc"
788		self._writeInfoToPlist(info)
789		reader = UFOReader(self.dstDir, validate=True)
790		self.assertRaises(UFOLibError, reader.readInfo, info=TestInfoObject())
791		# postscriptUniqueID
792		info = dict(fontInfoVersion3)
793		info["postscriptUniqueID"] = "abc"
794		self._writeInfoToPlist(info)
795		reader = UFOReader(self.dstDir, validate=True)
796		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
797		# postscriptUnderlineThickness
798		info = dict(fontInfoVersion3)
799		info["postscriptUnderlineThickness"] = "abc"
800		self._writeInfoToPlist(info)
801		reader = UFOReader(self.dstDir, validate=True)
802		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
803		# postscriptUnderlinePosition
804		info = dict(fontInfoVersion3)
805		info["postscriptUnderlinePosition"] = "abc"
806		self._writeInfoToPlist(info)
807		reader = UFOReader(self.dstDir, validate=True)
808		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
809		# postscriptIsFixedPitch
810		info = dict(fontInfoVersion3)
811		info["postscriptIsFixedPitch"] = 2
812		self._writeInfoToPlist(info)
813		reader = UFOReader(self.dstDir, validate=True)
814		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
815		# postscriptBlueValues
816		## not a list
817		info = dict(fontInfoVersion3)
818		info["postscriptBlueValues"] = "abc"
819		self._writeInfoToPlist(info)
820		reader = UFOReader(self.dstDir, validate=True)
821		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
822		## uneven value count
823		info = dict(fontInfoVersion3)
824		info["postscriptBlueValues"] = [500]
825		self._writeInfoToPlist(info)
826		reader = UFOReader(self.dstDir, validate=True)
827		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
828		## too many values
829		info = dict(fontInfoVersion3)
830		info["postscriptBlueValues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
831		self._writeInfoToPlist(info)
832		reader = UFOReader(self.dstDir, validate=True)
833		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
834		# postscriptOtherBlues
835		## not a list
836		info = dict(fontInfoVersion3)
837		info["postscriptOtherBlues"] = "abc"
838		self._writeInfoToPlist(info)
839		reader = UFOReader(self.dstDir, validate=True)
840		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
841		## uneven value count
842		info = dict(fontInfoVersion3)
843		info["postscriptOtherBlues"] = [500]
844		self._writeInfoToPlist(info)
845		reader = UFOReader(self.dstDir, validate=True)
846		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
847		## too many values
848		info = dict(fontInfoVersion3)
849		info["postscriptOtherBlues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
850		self._writeInfoToPlist(info)
851		reader = UFOReader(self.dstDir, validate=True)
852		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
853		# postscriptFamilyBlues
854		## not a list
855		info = dict(fontInfoVersion3)
856		info["postscriptFamilyBlues"] = "abc"
857		self._writeInfoToPlist(info)
858		reader = UFOReader(self.dstDir, validate=True)
859		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
860		## uneven value count
861		info = dict(fontInfoVersion3)
862		info["postscriptFamilyBlues"] = [500]
863		self._writeInfoToPlist(info)
864		reader = UFOReader(self.dstDir, validate=True)
865		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
866		## too many values
867		info = dict(fontInfoVersion3)
868		info["postscriptFamilyBlues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
869		self._writeInfoToPlist(info)
870		reader = UFOReader(self.dstDir, validate=True)
871		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
872		# postscriptFamilyOtherBlues
873		## not a list
874		info = dict(fontInfoVersion3)
875		info["postscriptFamilyOtherBlues"] = "abc"
876		self._writeInfoToPlist(info)
877		reader = UFOReader(self.dstDir, validate=True)
878		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
879		## uneven value count
880		info = dict(fontInfoVersion3)
881		info["postscriptFamilyOtherBlues"] = [500]
882		self._writeInfoToPlist(info)
883		reader = UFOReader(self.dstDir, validate=True)
884		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
885		## too many values
886		info = dict(fontInfoVersion3)
887		info["postscriptFamilyOtherBlues"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
888		self._writeInfoToPlist(info)
889		reader = UFOReader(self.dstDir, validate=True)
890		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
891		# postscriptStemSnapH
892		## not list
893		info = dict(fontInfoVersion3)
894		info["postscriptStemSnapH"] = "abc"
895		self._writeInfoToPlist(info)
896		reader = UFOReader(self.dstDir, validate=True)
897		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
898		## too many values
899		info = dict(fontInfoVersion3)
900		info["postscriptStemSnapH"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
901		self._writeInfoToPlist(info)
902		reader = UFOReader(self.dstDir, validate=True)
903		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
904		# postscriptStemSnapV
905		## not list
906		info = dict(fontInfoVersion3)
907		info["postscriptStemSnapV"] = "abc"
908		self._writeInfoToPlist(info)
909		reader = UFOReader(self.dstDir, validate=True)
910		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
911		## too many values
912		info = dict(fontInfoVersion3)
913		info["postscriptStemSnapV"] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
914		self._writeInfoToPlist(info)
915		reader = UFOReader(self.dstDir, validate=True)
916		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
917		# postscriptBlueFuzz
918		info = dict(fontInfoVersion3)
919		info["postscriptBlueFuzz"] = "abc"
920		self._writeInfoToPlist(info)
921		reader = UFOReader(self.dstDir, validate=True)
922		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
923		# postscriptBlueShift
924		info = dict(fontInfoVersion3)
925		info["postscriptBlueShift"] = "abc"
926		self._writeInfoToPlist(info)
927		reader = UFOReader(self.dstDir, validate=True)
928		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
929		# postscriptBlueScale
930		info = dict(fontInfoVersion3)
931		info["postscriptBlueScale"] = "abc"
932		self._writeInfoToPlist(info)
933		reader = UFOReader(self.dstDir, validate=True)
934		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
935		# postscriptForceBold
936		info = dict(fontInfoVersion3)
937		info["postscriptForceBold"] = "abc"
938		self._writeInfoToPlist(info)
939		reader = UFOReader(self.dstDir, validate=True)
940		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
941		# postscriptDefaultWidthX
942		info = dict(fontInfoVersion3)
943		info["postscriptDefaultWidthX"] = "abc"
944		self._writeInfoToPlist(info)
945		reader = UFOReader(self.dstDir, validate=True)
946		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
947		# postscriptNominalWidthX
948		info = dict(fontInfoVersion3)
949		info["postscriptNominalWidthX"] = "abc"
950		self._writeInfoToPlist(info)
951		reader = UFOReader(self.dstDir, validate=True)
952		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
953		# postscriptWeightName
954		info = dict(fontInfoVersion3)
955		info["postscriptWeightName"] = 123
956		self._writeInfoToPlist(info)
957		reader = UFOReader(self.dstDir, validate=True)
958		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
959		# postscriptDefaultCharacter
960		info = dict(fontInfoVersion3)
961		info["postscriptDefaultCharacter"] = 123
962		self._writeInfoToPlist(info)
963		reader = UFOReader(self.dstDir, validate=True)
964		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
965		# postscriptWindowsCharacterSet
966		info = dict(fontInfoVersion3)
967		info["postscriptWindowsCharacterSet"] = -1
968		self._writeInfoToPlist(info)
969		reader = UFOReader(self.dstDir, validate=True)
970		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
971		# macintoshFONDFamilyID
972		info = dict(fontInfoVersion3)
973		info["macintoshFONDFamilyID"] = "abc"
974		self._writeInfoToPlist(info)
975		reader = UFOReader(self.dstDir, validate=True)
976		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
977		# macintoshFONDName
978		info = dict(fontInfoVersion3)
979		info["macintoshFONDName"] = 123
980		self._writeInfoToPlist(info)
981		reader = UFOReader(self.dstDir, validate=True)
982		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
983
984	def testWOFFRead(self):
985		# woffMajorVersion
986		info = dict(fontInfoVersion3)
987		info["woffMajorVersion"] = 1.0
988		self._writeInfoToPlist(info)
989		reader = UFOReader(self.dstDir, validate=True)
990		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
991		info = dict(fontInfoVersion3)
992		info["woffMajorVersion"] = "abc"
993		self._writeInfoToPlist(info)
994		reader = UFOReader(self.dstDir, validate=True)
995		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
996		# woffMinorVersion
997		info = dict(fontInfoVersion3)
998		info["woffMinorVersion"] = 1.0
999		self._writeInfoToPlist(info)
1000		reader = UFOReader(self.dstDir, validate=True)
1001		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1002		info = dict(fontInfoVersion3)
1003		info["woffMinorVersion"] = "abc"
1004		self._writeInfoToPlist(info)
1005		reader = UFOReader(self.dstDir, validate=True)
1006		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1007		# woffMetadataUniqueID
1008		## none
1009		info = dict(fontInfoVersion3)
1010		del info["woffMetadataUniqueID"]
1011		self._writeInfoToPlist(info)
1012		reader = UFOReader(self.dstDir, validate=True)
1013		reader.readInfo(TestInfoObject())
1014		## not a dict
1015		info = dict(fontInfoVersion3)
1016		info["woffMetadataUniqueID"] = 1
1017		self._writeInfoToPlist(info)
1018		reader = UFOReader(self.dstDir, validate=True)
1019		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1020		## unknown key
1021		info = dict(fontInfoVersion3)
1022		info["woffMetadataUniqueID"] = dict(id="foo", notTheRightKey=1)
1023		self._writeInfoToPlist(info)
1024		reader = UFOReader(self.dstDir, validate=True)
1025		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1026		## no id
1027		info = dict(fontInfoVersion3)
1028		info["woffMetadataUniqueID"] = dict()
1029		self._writeInfoToPlist(info)
1030		reader = UFOReader(self.dstDir, validate=True)
1031		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1032		## not a string for id
1033		info = dict(fontInfoVersion3)
1034		info["woffMetadataUniqueID"] = dict(id=1)
1035		self._writeInfoToPlist(info)
1036		reader = UFOReader(self.dstDir, validate=True)
1037		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1038		## empty string
1039		info = dict(fontInfoVersion3)
1040		info["woffMetadataUniqueID"] = dict(id="")
1041		self._writeInfoToPlist(info)
1042		reader = UFOReader(self.dstDir, validate=True)
1043		reader.readInfo(TestInfoObject())
1044		# woffMetadataVendor
1045		## no name
1046		info = dict(fontInfoVersion3)
1047		info["woffMetadataVendor"] = dict(url="foo")
1048		self._writeInfoToPlist(info)
1049		reader = UFOReader(self.dstDir, validate=True)
1050		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1051		## name not a string
1052		info = dict(fontInfoVersion3)
1053		info["woffMetadataVendor"] = dict(name=1, url="foo")
1054		self._writeInfoToPlist(info)
1055		reader = UFOReader(self.dstDir, validate=True)
1056		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1057		## name an empty string
1058		info = dict(fontInfoVersion3)
1059		info["woffMetadataVendor"] = dict(name="", url="foo")
1060		self._writeInfoToPlist(info)
1061		reader = UFOReader(self.dstDir, validate=True)
1062		reader.readInfo(TestInfoObject())
1063		## no URL
1064		info = dict(fontInfoVersion3)
1065		info["woffMetadataVendor"] = dict(name="foo")
1066		self._writeInfoToPlist(info)
1067		reader = UFOReader(self.dstDir, validate=True)
1068		reader.readInfo(TestInfoObject())
1069		## url not a string
1070		info = dict(fontInfoVersion3)
1071		info["woffMetadataVendor"] = dict(name="foo", url=1)
1072		self._writeInfoToPlist(info)
1073		reader = UFOReader(self.dstDir, validate=True)
1074		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1075		## url empty string
1076		info = dict(fontInfoVersion3)
1077		info["woffMetadataVendor"] = dict(name="foo", url="")
1078		self._writeInfoToPlist(info)
1079		reader = UFOReader(self.dstDir, validate=True)
1080		reader.readInfo(TestInfoObject())
1081		## have dir
1082		info = dict(fontInfoVersion3)
1083		info["woffMetadataVendor"] = dict(name="foo", url="bar", dir="ltr")
1084		self._writeInfoToPlist(info)
1085		reader = UFOReader(self.dstDir, validate=True)
1086		reader.readInfo(TestInfoObject())
1087		info = dict(fontInfoVersion3)
1088		info["woffMetadataVendor"] = dict(name="foo", url="bar", dir="rtl")
1089		self._writeInfoToPlist(info)
1090		reader = UFOReader(self.dstDir, validate=True)
1091		reader.readInfo(TestInfoObject())
1092		## dir not a string
1093		info = dict(fontInfoVersion3)
1094		info["woffMetadataVendor"] = dict(name="foo", url="bar", dir=1)
1095		self._writeInfoToPlist(info)
1096		reader = UFOReader(self.dstDir, validate=True)
1097		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1098		## dir not ltr or rtl
1099		info = dict(fontInfoVersion3)
1100		info["woffMetadataVendor"] = dict(name="foo", url="bar", dir="utd")
1101		self._writeInfoToPlist(info)
1102		reader = UFOReader(self.dstDir, validate=True)
1103		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1104		## have class
1105		info = dict(fontInfoVersion3)
1106		info["woffMetadataVendor"] = {"name"  : "foo", "url" : "bar", "class" : "hello"}
1107		self._writeInfoToPlist(info)
1108		reader = UFOReader(self.dstDir, validate=True)
1109		reader.readInfo(TestInfoObject())
1110		## class not a string
1111		info = dict(fontInfoVersion3)
1112		info["woffMetadataVendor"] = {"name"  : "foo", "url" : "bar", "class" : 1}
1113		self._writeInfoToPlist(info)
1114		reader = UFOReader(self.dstDir, validate=True)
1115		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1116		## class empty string
1117		info = dict(fontInfoVersion3)
1118		info["woffMetadataVendor"] = {"name"  : "foo", "url" : "bar", "class" : ""}
1119		self._writeInfoToPlist(info)
1120		reader = UFOReader(self.dstDir, validate=True)
1121		reader.readInfo(TestInfoObject())
1122		# woffMetadataCredits
1123		## no credits attribute
1124		info = dict(fontInfoVersion3)
1125		info["woffMetadataCredits"] = {}
1126		self._writeInfoToPlist(info)
1127		reader = UFOReader(self.dstDir, validate=True)
1128		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1129		## unknown attribute
1130		info = dict(fontInfoVersion3)
1131		info["woffMetadataCredits"] = dict(credits=[dict(name="foo")], notTheRightKey=1)
1132		self._writeInfoToPlist(info)
1133		reader = UFOReader(self.dstDir, validate=True)
1134		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1135		## not a list
1136		info = dict(fontInfoVersion3)
1137		info["woffMetadataCredits"] = dict(credits="abc")
1138		self._writeInfoToPlist(info)
1139		reader = UFOReader(self.dstDir, validate=True)
1140		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1141		## no elements in credits
1142		info = dict(fontInfoVersion3)
1143		info["woffMetadataCredits"] = dict(credits=[])
1144		self._writeInfoToPlist(info)
1145		reader = UFOReader(self.dstDir, validate=True)
1146		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1147		## credit not a dict
1148		info = dict(fontInfoVersion3)
1149		info["woffMetadataCredits"] = dict(credits=["abc"])
1150		self._writeInfoToPlist(info)
1151		reader = UFOReader(self.dstDir, validate=True)
1152		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1153		## unknown key
1154		info = dict(fontInfoVersion3)
1155		info["woffMetadataCredits"] = dict(credits=[dict(name="foo", notTheRightKey=1)])
1156		self._writeInfoToPlist(info)
1157		reader = UFOReader(self.dstDir, validate=True)
1158		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1159		## no name
1160		info = dict(fontInfoVersion3)
1161		info["woffMetadataCredits"] = dict(credits=[dict(url="foo")])
1162		self._writeInfoToPlist(info)
1163		reader = UFOReader(self.dstDir, validate=True)
1164		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1165		## name not a string
1166		info = dict(fontInfoVersion3)
1167		info["woffMetadataCredits"] = dict(credits=[dict(name=1)])
1168		self._writeInfoToPlist(info)
1169		reader = UFOReader(self.dstDir, validate=True)
1170		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1171		## url not a string
1172		info = dict(fontInfoVersion3)
1173		info["woffMetadataCredits"] = dict(credits=[dict(name="foo", url=1)])
1174		self._writeInfoToPlist(info)
1175		reader = UFOReader(self.dstDir, validate=True)
1176		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1177		## role not a string
1178		info = dict(fontInfoVersion3)
1179		info["woffMetadataCredits"] = dict(credits=[dict(name="foo", role=1)])
1180		self._writeInfoToPlist(info)
1181		reader = UFOReader(self.dstDir, validate=True)
1182		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1183		## dir not a string
1184		info = dict(fontInfoVersion3)
1185		info["woffMetadataCredits"] = dict(credits=[dict(name="foo", dir=1)])
1186		self._writeInfoToPlist(info)
1187		reader = UFOReader(self.dstDir, validate=True)
1188		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1189		## dir not ltr or rtl
1190		info = dict(fontInfoVersion3)
1191		info["woffMetadataCredits"] = dict(credits=[dict(name="foo", dir="utd")])
1192		self._writeInfoToPlist(info)
1193		reader = UFOReader(self.dstDir, validate=True)
1194		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1195		## class not a string
1196		info = dict(fontInfoVersion3)
1197		info["woffMetadataCredits"] = dict(credits=[{"name"  : "foo", "class" : 1}])
1198		self._writeInfoToPlist(info)
1199		reader = UFOReader(self.dstDir, validate=True)
1200		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1201		# woffMetadataDescription
1202		## no url
1203		info = dict(fontInfoVersion3)
1204		info["woffMetadataDescription"] = dict(text=[dict(text="foo")])
1205		self._writeInfoToPlist(info)
1206		reader = UFOReader(self.dstDir, validate=True)
1207		reader.readInfo(TestInfoObject())
1208		## url not a string
1209		info = dict(fontInfoVersion3)
1210		info["woffMetadataDescription"] = dict(text=[dict(text="foo")], url=1)
1211		self._writeInfoToPlist(info)
1212		reader = UFOReader(self.dstDir, validate=True)
1213		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1214		## no text
1215		info = dict(fontInfoVersion3)
1216		info["woffMetadataDescription"] = dict(url="foo")
1217		self._writeInfoToPlist(info)
1218		reader = UFOReader(self.dstDir, validate=True)
1219		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1220		## text not a list
1221		info = dict(fontInfoVersion3)
1222		info["woffMetadataDescription"] = dict(text="abc")
1223		self._writeInfoToPlist(info)
1224		reader = UFOReader(self.dstDir, validate=True)
1225		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1226		## text item not a dict
1227		info = dict(fontInfoVersion3)
1228		info["woffMetadataDescription"] = dict(text=["abc"])
1229		self._writeInfoToPlist(info)
1230		reader = UFOReader(self.dstDir, validate=True)
1231		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1232		## text item unknown key
1233		info = dict(fontInfoVersion3)
1234		info["woffMetadataDescription"] = dict(text=[dict(text="foo", notTheRightKey=1)])
1235		self._writeInfoToPlist(info)
1236		reader = UFOReader(self.dstDir, validate=True)
1237		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1238		## text item missing text
1239		info = dict(fontInfoVersion3)
1240		info["woffMetadataDescription"] = dict(text=[dict(language="foo")])
1241		self._writeInfoToPlist(info)
1242		reader = UFOReader(self.dstDir, validate=True)
1243		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1244		## text not a string
1245		info = dict(fontInfoVersion3)
1246		info["woffMetadataDescription"] = dict(text=[dict(text=1)])
1247		self._writeInfoToPlist(info)
1248		reader = UFOReader(self.dstDir, validate=True)
1249		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1250		## url not a string
1251		info = dict(fontInfoVersion3)
1252		info["woffMetadataDescription"] = dict(text=[dict(text="foo", url=1)])
1253		self._writeInfoToPlist(info)
1254		reader = UFOReader(self.dstDir, validate=True)
1255		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1256		## language not a string
1257		info = dict(fontInfoVersion3)
1258		info["woffMetadataDescription"] = dict(text=[dict(text="foo", language=1)])
1259		self._writeInfoToPlist(info)
1260		reader = UFOReader(self.dstDir, validate=True)
1261		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1262		## dir not ltr or rtl
1263		info = dict(fontInfoVersion3)
1264		info["woffMetadataDescription"] = dict(text=[dict(text="foo", dir="utd")])
1265		self._writeInfoToPlist(info)
1266		reader = UFOReader(self.dstDir, validate=True)
1267		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1268		## class not a string
1269		info = dict(fontInfoVersion3)
1270		info["woffMetadataDescription"] = dict(text=[{"text"  : "foo", "class" : 1}])
1271		self._writeInfoToPlist(info)
1272		reader = UFOReader(self.dstDir, validate=True)
1273		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1274		# woffMetadataLicense
1275		## no url
1276		info = dict(fontInfoVersion3)
1277		info["woffMetadataLicense"] = dict(text=[dict(text="foo")])
1278		self._writeInfoToPlist(info)
1279		reader = UFOReader(self.dstDir, validate=True)
1280		reader.readInfo(TestInfoObject())
1281		## url not a string
1282		info = dict(fontInfoVersion3)
1283		info["woffMetadataLicense"] = dict(text=[dict(text="foo")], url=1)
1284		self._writeInfoToPlist(info)
1285		reader = UFOReader(self.dstDir, validate=True)
1286		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1287		## id not a string
1288		info = dict(fontInfoVersion3)
1289		info["woffMetadataLicense"] = dict(text=[dict(text="foo")], id=1)
1290		self._writeInfoToPlist(info)
1291		reader = UFOReader(self.dstDir, validate=True)
1292		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1293		## no text
1294		info = dict(fontInfoVersion3)
1295		info["woffMetadataLicense"] = dict(url="foo")
1296		self._writeInfoToPlist(info)
1297		reader = UFOReader(self.dstDir, validate=True)
1298		reader.readInfo(TestInfoObject())
1299		## text not a list
1300		info = dict(fontInfoVersion3)
1301		info["woffMetadataLicense"] = dict(text="abc")
1302		self._writeInfoToPlist(info)
1303		reader = UFOReader(self.dstDir, validate=True)
1304		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1305		## text item not a dict
1306		info = dict(fontInfoVersion3)
1307		info["woffMetadataLicense"] = dict(text=["abc"])
1308		self._writeInfoToPlist(info)
1309		reader = UFOReader(self.dstDir, validate=True)
1310		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1311		## text item unknown key
1312		info = dict(fontInfoVersion3)
1313		info["woffMetadataLicense"] = dict(text=[dict(text="foo", notTheRightKey=1)])
1314		self._writeInfoToPlist(info)
1315		reader = UFOReader(self.dstDir, validate=True)
1316		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1317		## text item missing text
1318		info = dict(fontInfoVersion3)
1319		info["woffMetadataLicense"] = dict(text=[dict(language="foo")])
1320		self._writeInfoToPlist(info)
1321		reader = UFOReader(self.dstDir, validate=True)
1322		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1323		## text not a string
1324		info = dict(fontInfoVersion3)
1325		info["woffMetadataLicense"] = dict(text=[dict(text=1)])
1326		self._writeInfoToPlist(info)
1327		reader = UFOReader(self.dstDir, validate=True)
1328		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1329		## url not a string
1330		info = dict(fontInfoVersion3)
1331		info["woffMetadataLicense"] = dict(text=[dict(text="foo", url=1)])
1332		self._writeInfoToPlist(info)
1333		reader = UFOReader(self.dstDir, validate=True)
1334		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1335		## language not a string
1336		info = dict(fontInfoVersion3)
1337		info["woffMetadataLicense"] = dict(text=[dict(text="foo", language=1)])
1338		self._writeInfoToPlist(info)
1339		reader = UFOReader(self.dstDir, validate=True)
1340		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1341		## dir not ltr or rtl
1342		info = dict(fontInfoVersion3)
1343		info["woffMetadataLicense"] = dict(text=[dict(text="foo", dir="utd")])
1344		self._writeInfoToPlist(info)
1345		reader = UFOReader(self.dstDir, validate=True)
1346		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1347		## class not a string
1348		info = dict(fontInfoVersion3)
1349		info["woffMetadataLicense"] = dict(text=[{"text"  : "foo", "class" : 1}])
1350		self._writeInfoToPlist(info)
1351		reader = UFOReader(self.dstDir, validate=True)
1352		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1353		# woffMetadataCopyright
1354		## unknown attribute
1355		info = dict(fontInfoVersion3)
1356		info["woffMetadataCopyright"] = dict(text=[dict(text="foo")], notTheRightKey=1)
1357		self._writeInfoToPlist(info)
1358		reader = UFOReader(self.dstDir, validate=True)
1359		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1360		## no text
1361		info = dict(fontInfoVersion3)
1362		info["woffMetadataCopyright"] = dict()
1363		self._writeInfoToPlist(info)
1364		reader = UFOReader(self.dstDir, validate=True)
1365		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1366		## text not a list
1367		info = dict(fontInfoVersion3)
1368		info["woffMetadataCopyright"] = dict(text="abc")
1369		self._writeInfoToPlist(info)
1370		reader = UFOReader(self.dstDir, validate=True)
1371		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1372		## text item not a dict
1373		info = dict(fontInfoVersion3)
1374		info["woffMetadataCopyright"] = dict(text=["abc"])
1375		self._writeInfoToPlist(info)
1376		reader = UFOReader(self.dstDir, validate=True)
1377		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1378		## text item unknown key
1379		info = dict(fontInfoVersion3)
1380		info["woffMetadataCopyright"] = dict(text=[dict(text="foo", notTheRightKey=1)])
1381		self._writeInfoToPlist(info)
1382		reader = UFOReader(self.dstDir, validate=True)
1383		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1384		## text item missing text
1385		info = dict(fontInfoVersion3)
1386		info["woffMetadataCopyright"] = dict(text=[dict(language="foo")])
1387		self._writeInfoToPlist(info)
1388		reader = UFOReader(self.dstDir, validate=True)
1389		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1390		## text not a string
1391		info = dict(fontInfoVersion3)
1392		info["woffMetadataCopyright"] = dict(text=[dict(text=1)])
1393		self._writeInfoToPlist(info)
1394		reader = UFOReader(self.dstDir, validate=True)
1395		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1396		## url not a string
1397		info = dict(fontInfoVersion3)
1398		info["woffMetadataCopyright"] = dict(text=[dict(text="foo", url=1)])
1399		self._writeInfoToPlist(info)
1400		reader = UFOReader(self.dstDir, validate=True)
1401		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1402		## language not a string
1403		info = dict(fontInfoVersion3)
1404		info["woffMetadataCopyright"] = dict(text=[dict(text="foo", language=1)])
1405		self._writeInfoToPlist(info)
1406		reader = UFOReader(self.dstDir, validate=True)
1407		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1408		## dir not ltr or rtl
1409		info = dict(fontInfoVersion3)
1410		info["woffMetadataCopyright"] = dict(text=[dict(text="foo", dir="utd")])
1411		self._writeInfoToPlist(info)
1412		reader = UFOReader(self.dstDir, validate=True)
1413		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1414		## class not a string
1415		info = dict(fontInfoVersion3)
1416		info["woffMetadataCopyright"] = dict(text=[{"text"  : "foo", "class" : 1}])
1417		self._writeInfoToPlist(info)
1418		reader = UFOReader(self.dstDir, validate=True)
1419		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1420		# woffMetadataTrademark
1421		## unknown attribute
1422		info = dict(fontInfoVersion3)
1423		info["woffMetadataTrademark"] = dict(text=[dict(text="foo")], notTheRightKey=1)
1424		self._writeInfoToPlist(info)
1425		reader = UFOReader(self.dstDir, validate=True)
1426		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1427		## no text
1428		info = dict(fontInfoVersion3)
1429		info["woffMetadataTrademark"] = dict()
1430		self._writeInfoToPlist(info)
1431		reader = UFOReader(self.dstDir, validate=True)
1432		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1433		## text not a list
1434		info = dict(fontInfoVersion3)
1435		info["woffMetadataTrademark"] = dict(text="abc")
1436		self._writeInfoToPlist(info)
1437		reader = UFOReader(self.dstDir, validate=True)
1438		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1439		## text item not a dict
1440		info = dict(fontInfoVersion3)
1441		info["woffMetadataTrademark"] = dict(text=["abc"])
1442		self._writeInfoToPlist(info)
1443		reader = UFOReader(self.dstDir, validate=True)
1444		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1445		## text item unknown key
1446		info = dict(fontInfoVersion3)
1447		info["woffMetadataTrademark"] = dict(text=[dict(text="foo", notTheRightKey=1)])
1448		self._writeInfoToPlist(info)
1449		reader = UFOReader(self.dstDir, validate=True)
1450		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1451		## text item missing text
1452		info = dict(fontInfoVersion3)
1453		info["woffMetadataTrademark"] = dict(text=[dict(language="foo")])
1454		self._writeInfoToPlist(info)
1455		reader = UFOReader(self.dstDir, validate=True)
1456		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1457		## text not a string
1458		info = dict(fontInfoVersion3)
1459		info["woffMetadataTrademark"] = dict(text=[dict(text=1)])
1460		self._writeInfoToPlist(info)
1461		reader = UFOReader(self.dstDir, validate=True)
1462		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1463		## url not a string
1464		info = dict(fontInfoVersion3)
1465		info["woffMetadataTrademark"] = dict(text=[dict(text="foo", url=1)])
1466		self._writeInfoToPlist(info)
1467		reader = UFOReader(self.dstDir, validate=True)
1468		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1469		## language not a string
1470		info = dict(fontInfoVersion3)
1471		info["woffMetadataTrademark"] = dict(text=[dict(text="foo", language=1)])
1472		self._writeInfoToPlist(info)
1473		reader = UFOReader(self.dstDir, validate=True)
1474		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1475		## dir not ltr or rtl
1476		info = dict(fontInfoVersion3)
1477		info["woffMetadataTrademark"] = dict(text=[dict(text="foo", dir="utd")])
1478		self._writeInfoToPlist(info)
1479		reader = UFOReader(self.dstDir, validate=True)
1480		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1481		## class not a string
1482		info = dict(fontInfoVersion3)
1483		info["woffMetadataTrademark"] = dict(text=[{"text"  : "foo", "class" : 1}])
1484		self._writeInfoToPlist(info)
1485		reader = UFOReader(self.dstDir, validate=True)
1486		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1487		# woffMetadataLicensee
1488		## no name
1489		info = dict(fontInfoVersion3)
1490		info["woffMetadataLicensee"] = dict()
1491		self._writeInfoToPlist(info)
1492		reader = UFOReader(self.dstDir, validate=True)
1493		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1494		## unknown attribute
1495		info = dict(fontInfoVersion3)
1496		info["woffMetadataLicensee"] = dict(name="foo", notTheRightKey=1)
1497		self._writeInfoToPlist(info)
1498		reader = UFOReader(self.dstDir, validate=True)
1499		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1500		## name not a string
1501		info = dict(fontInfoVersion3)
1502		info["woffMetadataLicensee"] = dict(name=1)
1503		self._writeInfoToPlist(info)
1504		reader = UFOReader(self.dstDir, validate=True)
1505		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1506		## dir options
1507		info = dict(fontInfoVersion3)
1508		info["woffMetadataLicensee"] = dict(name="foo", dir="ltr")
1509		self._writeInfoToPlist(info)
1510		reader = UFOReader(self.dstDir, validate=True)
1511		reader.readInfo(TestInfoObject())
1512		info = dict(fontInfoVersion3)
1513		info["woffMetadataLicensee"] = dict(name="foo", dir="rtl")
1514		self._writeInfoToPlist(info)
1515		reader = UFOReader(self.dstDir, validate=True)
1516		reader.readInfo(TestInfoObject())
1517		## dir not ltr or rtl
1518		info = dict(fontInfoVersion3)
1519		info["woffMetadataLicensee"] = dict(name="foo", dir="utd")
1520		self._writeInfoToPlist(info)
1521		reader = UFOReader(self.dstDir, validate=True)
1522		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1523		## have class
1524		info = dict(fontInfoVersion3)
1525		info["woffMetadataLicensee"] = {"name" : "foo", "class" : "hello"}
1526		self._writeInfoToPlist(info)
1527		reader = UFOReader(self.dstDir, validate=True)
1528		reader.readInfo(TestInfoObject())
1529		## class not a string
1530		info = dict(fontInfoVersion3)
1531		info["woffMetadataLicensee"] = {"name" : "foo", "class" : 1}
1532		self._writeInfoToPlist(info)
1533		reader = UFOReader(self.dstDir, validate=True)
1534		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1535
1536	def testGuidelinesRead(self):
1537		# x
1538		## not an int or float
1539		info = dict(fontInfoVersion3)
1540		info["guidelines"] = [dict(x="1")]
1541		self._writeInfoToPlist(info)
1542		reader = UFOReader(self.dstDir, validate=True)
1543		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1544		# y
1545		## not an int or float
1546		info = dict(fontInfoVersion3)
1547		info["guidelines"] = [dict(y="1")]
1548		self._writeInfoToPlist(info)
1549		reader = UFOReader(self.dstDir, validate=True)
1550		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1551		# angle
1552		## < 0
1553		info = dict(fontInfoVersion3)
1554		info["guidelines"] = [dict(x=0, y=0, angle=-1)]
1555		self._writeInfoToPlist(info)
1556		reader = UFOReader(self.dstDir, validate=True)
1557		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1558		## > 360
1559		info = dict(fontInfoVersion3)
1560		info["guidelines"] = [dict(x=0, y=0, angle=361)]
1561		self._writeInfoToPlist(info)
1562		reader = UFOReader(self.dstDir, validate=True)
1563		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1564		# name
1565		## not a string
1566		info = dict(fontInfoVersion3)
1567		info["guidelines"] = [dict(x=0, name=1)]
1568		self._writeInfoToPlist(info)
1569		reader = UFOReader(self.dstDir, validate=True)
1570		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1571		# color
1572		## not a string
1573		info = dict(fontInfoVersion3)
1574		info["guidelines"] = [dict(x=0, color=1)]
1575		self._writeInfoToPlist(info)
1576		reader = UFOReader(self.dstDir, validate=True)
1577		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1578		## not enough commas
1579		info = dict(fontInfoVersion3)
1580		info["guidelines"] = [dict(x=0, color="1 0, 0, 0")]
1581		self._writeInfoToPlist(info)
1582		reader = UFOReader(self.dstDir, validate=True)
1583		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1584		info = dict(fontInfoVersion3)
1585		info["guidelines"] = [dict(x=0, color="1 0 0, 0")]
1586		self._writeInfoToPlist(info)
1587		reader = UFOReader(self.dstDir, validate=True)
1588		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1589		info = dict(fontInfoVersion3)
1590		info["guidelines"] = [dict(x=0, color="1 0 0 0")]
1591		self._writeInfoToPlist(info)
1592		reader = UFOReader(self.dstDir, validate=True)
1593		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1594		## not enough parts
1595		info = dict(fontInfoVersion3)
1596		info["guidelines"] = [dict(x=0, color=", 0, 0, 0")]
1597		self._writeInfoToPlist(info)
1598		reader = UFOReader(self.dstDir, validate=True)
1599		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1600		info = dict(fontInfoVersion3)
1601		info["guidelines"] = [dict(x=0, color="1, , 0, 0")]
1602		self._writeInfoToPlist(info)
1603		reader = UFOReader(self.dstDir, validate=True)
1604		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1605		info = dict(fontInfoVersion3)
1606		info["guidelines"] = [dict(x=0, color="1, 0, , 0")]
1607		self._writeInfoToPlist(info)
1608		reader = UFOReader(self.dstDir, validate=True)
1609		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1610		info = dict(fontInfoVersion3)
1611		info["guidelines"] = [dict(x=0, color="1, 0, 0, ")]
1612		self._writeInfoToPlist(info)
1613		reader = UFOReader(self.dstDir, validate=True)
1614		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1615		info = dict(fontInfoVersion3)
1616		info["guidelines"] = [dict(x=0, color=", , , ")]
1617		self._writeInfoToPlist(info)
1618		reader = UFOReader(self.dstDir, validate=True)
1619		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1620		## not a number in all positions
1621		info = dict(fontInfoVersion3)
1622		info["guidelines"] = [dict(x=0, color="r, 1, 1, 1")]
1623		self._writeInfoToPlist(info)
1624		reader = UFOReader(self.dstDir, validate=True)
1625		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1626		info = dict(fontInfoVersion3)
1627		info["guidelines"] = [dict(x=0, color="1, g, 1, 1")]
1628		self._writeInfoToPlist(info)
1629		reader = UFOReader(self.dstDir, validate=True)
1630		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1631		info = dict(fontInfoVersion3)
1632		info["guidelines"] = [dict(x=0, color="1, 1, b, 1")]
1633		self._writeInfoToPlist(info)
1634		reader = UFOReader(self.dstDir, validate=True)
1635		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1636		info = dict(fontInfoVersion3)
1637		info["guidelines"] = [dict(x=0, color="1, 1, 1, a")]
1638		self._writeInfoToPlist(info)
1639		reader = UFOReader(self.dstDir, validate=True)
1640		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1641		## too many parts
1642		info = dict(fontInfoVersion3)
1643		info["guidelines"] = [dict(x=0, color="1, 0, 0, 0, 0")]
1644		self._writeInfoToPlist(info)
1645		reader = UFOReader(self.dstDir, validate=True)
1646		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1647		## < 0 in each position
1648		info = dict(fontInfoVersion3)
1649		info["guidelines"] = [dict(x=0, color="-1, 0, 0, 0")]
1650		self._writeInfoToPlist(info)
1651		reader = UFOReader(self.dstDir, validate=True)
1652		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1653		info = dict(fontInfoVersion3)
1654		info["guidelines"] = [dict(x=0, color="0, -1, 0, 0")]
1655		self._writeInfoToPlist(info)
1656		reader = UFOReader(self.dstDir, validate=True)
1657		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1658		info = dict(fontInfoVersion3)
1659		info["guidelines"] = [dict(x=0, color="0, 0, -1, 0")]
1660		self._writeInfoToPlist(info)
1661		reader = UFOReader(self.dstDir, validate=True)
1662		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1663		info = dict(fontInfoVersion3)
1664		info["guidelines"] = [dict(x=0, color="0, 0, 0, -1")]
1665		self._writeInfoToPlist(info)
1666		reader = UFOReader(self.dstDir, validate=True)
1667		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1668		## > 1 in each position
1669		info = dict(fontInfoVersion3)
1670		info["guidelines"] = [dict(x=0, color="2, 0, 0, 0")]
1671		self._writeInfoToPlist(info)
1672		reader = UFOReader(self.dstDir, validate=True)
1673		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1674		info = dict(fontInfoVersion3)
1675		info["guidelines"] = [dict(x=0, color="0, 2, 0, 0")]
1676		self._writeInfoToPlist(info)
1677		reader = UFOReader(self.dstDir, validate=True)
1678		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1679		info = dict(fontInfoVersion3)
1680		info["guidelines"] = [dict(x=0, color="0, 0, 2, 0")]
1681		self._writeInfoToPlist(info)
1682		reader = UFOReader(self.dstDir, validate=True)
1683		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1684		info = dict(fontInfoVersion3)
1685		info["guidelines"] = [dict(x=0, color="0, 0, 0, 2")]
1686		self._writeInfoToPlist(info)
1687		reader = UFOReader(self.dstDir, validate=True)
1688		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1689		# identifier
1690		## duplicate
1691		info = dict(fontInfoVersion3)
1692		info["guidelines"] = [dict(x=0, identifier="guide1"), dict(y=0, identifier="guide1")]
1693		self._writeInfoToPlist(info)
1694		reader = UFOReader(self.dstDir, validate=True)
1695		self.assertRaises(UFOLibError, reader.readInfo, TestInfoObject())
1696
1697
1698class WriteFontInfoVersion3TestCase(unittest.TestCase):
1699
1700	def setUp(self):
1701		self.tempDir = tempfile.mktemp()
1702		os.mkdir(self.tempDir)
1703		self.dstDir = os.path.join(self.tempDir, "test.ufo")
1704
1705	def tearDown(self):
1706		shutil.rmtree(self.tempDir)
1707
1708	def tearDownUFO(self):
1709		if os.path.exists(self.dstDir):
1710			shutil.rmtree(self.dstDir)
1711
1712	def makeInfoObject(self):
1713		infoObject = TestInfoObject()
1714		for attr, value in list(fontInfoVersion3.items()):
1715			setattr(infoObject, attr, value)
1716		return infoObject
1717
1718	def readPlist(self):
1719		path = os.path.join(self.dstDir, "fontinfo.plist")
1720		with open(path, "rb") as f:
1721			plist = plistlib.load(f)
1722		return plist
1723
1724	def testWrite(self):
1725		infoObject = self.makeInfoObject()
1726		writer = UFOWriter(self.dstDir, formatVersion=3)
1727		writer.writeInfo(infoObject)
1728		writtenData = self.readPlist()
1729		for attr, originalValue in list(fontInfoVersion3.items()):
1730			newValue = writtenData[attr]
1731			self.assertEqual(newValue, originalValue)
1732		self.tearDownUFO()
1733
1734	def testGenericWrite(self):
1735		# familyName
1736		infoObject = self.makeInfoObject()
1737		infoObject.familyName = 123
1738		writer = UFOWriter(self.dstDir, formatVersion=3)
1739		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1740		self.tearDownUFO()
1741		# styleName
1742		infoObject = self.makeInfoObject()
1743		infoObject.styleName = 123
1744		writer = UFOWriter(self.dstDir, formatVersion=3)
1745		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1746		self.tearDownUFO()
1747		# styleMapFamilyName
1748		infoObject = self.makeInfoObject()
1749		infoObject.styleMapFamilyName = 123
1750		writer = UFOWriter(self.dstDir, formatVersion=3)
1751		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1752		self.tearDownUFO()
1753		# styleMapStyleName
1754		## not a string
1755		infoObject = self.makeInfoObject()
1756		infoObject.styleMapStyleName = 123
1757		writer = UFOWriter(self.dstDir, formatVersion=3)
1758		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1759		self.tearDownUFO()
1760		## out of range
1761		infoObject = self.makeInfoObject()
1762		infoObject.styleMapStyleName = "REGULAR"
1763		writer = UFOWriter(self.dstDir, formatVersion=3)
1764		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1765		self.tearDownUFO()
1766		# versionMajor
1767		infoObject = self.makeInfoObject()
1768		infoObject.versionMajor = "1"
1769		writer = UFOWriter(self.dstDir, formatVersion=3)
1770		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1771		self.tearDownUFO()
1772		# versionMinor
1773		infoObject = self.makeInfoObject()
1774		infoObject.versionMinor = "0"
1775		writer = UFOWriter(self.dstDir, formatVersion=3)
1776		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1777		self.tearDownUFO()
1778		# copyright
1779		infoObject = self.makeInfoObject()
1780		infoObject.copyright = 123
1781		writer = UFOWriter(self.dstDir, formatVersion=3)
1782		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1783		self.tearDownUFO()
1784		# trademark
1785		infoObject = self.makeInfoObject()
1786		infoObject.trademark = 123
1787		writer = UFOWriter(self.dstDir, formatVersion=3)
1788		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1789		self.tearDownUFO()
1790		# unitsPerEm
1791		infoObject = self.makeInfoObject()
1792		infoObject.unitsPerEm = "abc"
1793		writer = UFOWriter(self.dstDir, formatVersion=3)
1794		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1795		self.tearDownUFO()
1796		# descender
1797		infoObject = self.makeInfoObject()
1798		infoObject.descender = "abc"
1799		writer = UFOWriter(self.dstDir, formatVersion=3)
1800		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1801		self.tearDownUFO()
1802		# xHeight
1803		infoObject = self.makeInfoObject()
1804		infoObject.xHeight = "abc"
1805		writer = UFOWriter(self.dstDir, formatVersion=3)
1806		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1807		self.tearDownUFO()
1808		# capHeight
1809		infoObject = self.makeInfoObject()
1810		infoObject.capHeight = "abc"
1811		writer = UFOWriter(self.dstDir, formatVersion=3)
1812		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1813		self.tearDownUFO()
1814		# ascender
1815		infoObject = self.makeInfoObject()
1816		infoObject.ascender = "abc"
1817		writer = UFOWriter(self.dstDir, formatVersion=3)
1818		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1819		self.tearDownUFO()
1820		# italicAngle
1821		infoObject = self.makeInfoObject()
1822		infoObject.italicAngle = "abc"
1823		writer = UFOWriter(self.dstDir, formatVersion=3)
1824		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1825		self.tearDownUFO()
1826
1827	def testGaspWrite(self):
1828		# not a list
1829		infoObject = self.makeInfoObject()
1830		infoObject.openTypeGaspRangeRecords = "abc"
1831		writer = UFOWriter(self.dstDir, formatVersion=3)
1832		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1833		self.tearDownUFO()
1834		# empty list
1835		infoObject = self.makeInfoObject()
1836		infoObject.openTypeGaspRangeRecords = []
1837		writer = UFOWriter(self.dstDir, formatVersion=3)
1838		writer.writeInfo(infoObject)
1839		self.tearDownUFO()
1840		# not a dict
1841		infoObject = self.makeInfoObject()
1842		infoObject.openTypeGaspRangeRecords = ["abc"]
1843		writer = UFOWriter(self.dstDir, formatVersion=3)
1844		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1845		self.tearDownUFO()
1846		# dict not properly formatted
1847		infoObject = self.makeInfoObject()
1848		infoObject.openTypeGaspRangeRecords = [dict(rangeMaxPPEM=0xFFFF, notTheRightKey=1)]
1849		writer = UFOWriter(self.dstDir, formatVersion=3)
1850		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1851		self.tearDownUFO()
1852		infoObject = self.makeInfoObject()
1853		infoObject.openTypeGaspRangeRecords = [dict(notTheRightKey=1, rangeGaspBehavior=[0])]
1854		writer = UFOWriter(self.dstDir, formatVersion=3)
1855		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1856		self.tearDownUFO()
1857		# not an int for ppem
1858		infoObject = self.makeInfoObject()
1859		infoObject.openTypeGaspRangeRecords = [dict(rangeMaxPPEM="abc", rangeGaspBehavior=[0]), dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0])]
1860		writer = UFOWriter(self.dstDir, formatVersion=3)
1861		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1862		self.tearDownUFO()
1863		# not a list for behavior
1864		infoObject = self.makeInfoObject()
1865		infoObject.openTypeGaspRangeRecords = [dict(rangeMaxPPEM=10, rangeGaspBehavior="abc"), dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0])]
1866		writer = UFOWriter(self.dstDir, formatVersion=3)
1867		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1868		self.tearDownUFO()
1869		# invalid behavior value
1870		infoObject = self.makeInfoObject()
1871		infoObject.openTypeGaspRangeRecords = [dict(rangeMaxPPEM=10, rangeGaspBehavior=[-1]), dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0])]
1872		writer = UFOWriter(self.dstDir, formatVersion=3)
1873		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1874		self.tearDownUFO()
1875		# not sorted
1876		infoObject = self.makeInfoObject()
1877		infoObject.openTypeGaspRangeRecords = [dict(rangeMaxPPEM=0xFFFF, rangeGaspBehavior=[0]), dict(rangeMaxPPEM=10, rangeGaspBehavior=[0])]
1878		writer = UFOWriter(self.dstDir, formatVersion=3)
1879		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1880		self.tearDownUFO()
1881		# no 0xFFFF
1882		infoObject = self.makeInfoObject()
1883		infoObject.openTypeGaspRangeRecords = [dict(rangeMaxPPEM=10, rangeGaspBehavior=[0]), dict(rangeMaxPPEM=20, rangeGaspBehavior=[0])]
1884		writer = UFOWriter(self.dstDir, formatVersion=3)
1885		writer.writeInfo(infoObject)
1886		self.tearDownUFO()
1887
1888	def testHeadWrite(self):
1889		# openTypeHeadCreated
1890		## not a string
1891		infoObject = self.makeInfoObject()
1892		infoObject.openTypeHeadCreated = 123
1893		writer = UFOWriter(self.dstDir, formatVersion=3)
1894		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1895		self.tearDownUFO()
1896		## invalid format
1897		infoObject = self.makeInfoObject()
1898		infoObject.openTypeHeadCreated = "2000-Jan-01 00:00:00"
1899		writer = UFOWriter(self.dstDir, formatVersion=3)
1900		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1901		self.tearDownUFO()
1902		# openTypeHeadLowestRecPPEM
1903		infoObject = self.makeInfoObject()
1904		infoObject.openTypeHeadLowestRecPPEM = "abc"
1905		writer = UFOWriter(self.dstDir, formatVersion=3)
1906		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1907		self.tearDownUFO()
1908		# openTypeHeadFlags
1909		infoObject = self.makeInfoObject()
1910		infoObject.openTypeHeadFlags = [-1]
1911		writer = UFOWriter(self.dstDir, formatVersion=3)
1912		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1913		self.tearDownUFO()
1914
1915	def testHheaWrite(self):
1916		# openTypeHheaAscender
1917		infoObject = self.makeInfoObject()
1918		infoObject.openTypeHheaAscender = "abc"
1919		writer = UFOWriter(self.dstDir, formatVersion=3)
1920		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1921		self.tearDownUFO()
1922		# openTypeHheaDescender
1923		infoObject = self.makeInfoObject()
1924		infoObject.openTypeHheaDescender = "abc"
1925		writer = UFOWriter(self.dstDir, formatVersion=3)
1926		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1927		self.tearDownUFO()
1928		# openTypeHheaLineGap
1929		infoObject = self.makeInfoObject()
1930		infoObject.openTypeHheaLineGap = "abc"
1931		writer = UFOWriter(self.dstDir, formatVersion=3)
1932		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1933		self.tearDownUFO()
1934		# openTypeHheaCaretSlopeRise
1935		infoObject = self.makeInfoObject()
1936		infoObject.openTypeHheaCaretSlopeRise = "abc"
1937		writer = UFOWriter(self.dstDir, formatVersion=3)
1938		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1939		self.tearDownUFO()
1940		# openTypeHheaCaretSlopeRun
1941		infoObject = self.makeInfoObject()
1942		infoObject.openTypeHheaCaretSlopeRun = "abc"
1943		writer = UFOWriter(self.dstDir, formatVersion=3)
1944		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1945		self.tearDownUFO()
1946		# openTypeHheaCaretOffset
1947		infoObject = self.makeInfoObject()
1948		infoObject.openTypeHheaCaretOffset = "abc"
1949		writer = UFOWriter(self.dstDir, formatVersion=3)
1950		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1951		self.tearDownUFO()
1952
1953	def testNameWrite(self):
1954		# openTypeNameDesigner
1955		infoObject = self.makeInfoObject()
1956		infoObject.openTypeNameDesigner = 123
1957		writer = UFOWriter(self.dstDir, formatVersion=3)
1958		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1959		self.tearDownUFO()
1960		# openTypeNameDesignerURL
1961		infoObject = self.makeInfoObject()
1962		infoObject.openTypeNameDesignerURL = 123
1963		writer = UFOWriter(self.dstDir, formatVersion=3)
1964		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1965		self.tearDownUFO()
1966		# openTypeNameManufacturer
1967		infoObject = self.makeInfoObject()
1968		infoObject.openTypeNameManufacturer = 123
1969		writer = UFOWriter(self.dstDir, formatVersion=3)
1970		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1971		self.tearDownUFO()
1972		# openTypeNameManufacturerURL
1973		infoObject = self.makeInfoObject()
1974		infoObject.openTypeNameManufacturerURL = 123
1975		writer = UFOWriter(self.dstDir, formatVersion=3)
1976		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1977		self.tearDownUFO()
1978		# openTypeNameLicense
1979		infoObject = self.makeInfoObject()
1980		infoObject.openTypeNameLicense = 123
1981		writer = UFOWriter(self.dstDir, formatVersion=3)
1982		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1983		self.tearDownUFO()
1984		# openTypeNameLicenseURL
1985		infoObject = self.makeInfoObject()
1986		infoObject.openTypeNameLicenseURL = 123
1987		writer = UFOWriter(self.dstDir, formatVersion=3)
1988		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1989		self.tearDownUFO()
1990		# openTypeNameVersion
1991		infoObject = self.makeInfoObject()
1992		infoObject.openTypeNameVersion = 123
1993		writer = UFOWriter(self.dstDir, formatVersion=3)
1994		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
1995		self.tearDownUFO()
1996		# openTypeNameUniqueID
1997		infoObject = self.makeInfoObject()
1998		infoObject.openTypeNameUniqueID = 123
1999		writer = UFOWriter(self.dstDir, formatVersion=3)
2000		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2001		self.tearDownUFO()
2002		# openTypeNameDescription
2003		infoObject = self.makeInfoObject()
2004		infoObject.openTypeNameDescription = 123
2005		writer = UFOWriter(self.dstDir, formatVersion=3)
2006		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2007		self.tearDownUFO()
2008		# openTypeNamePreferredFamilyName
2009		infoObject = self.makeInfoObject()
2010		infoObject.openTypeNamePreferredFamilyName = 123
2011		writer = UFOWriter(self.dstDir, formatVersion=3)
2012		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2013		self.tearDownUFO()
2014		# openTypeNamePreferredSubfamilyName
2015		infoObject = self.makeInfoObject()
2016		infoObject.openTypeNamePreferredSubfamilyName = 123
2017		writer = UFOWriter(self.dstDir, formatVersion=3)
2018		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2019		self.tearDownUFO()
2020		# openTypeNameCompatibleFullName
2021		infoObject = self.makeInfoObject()
2022		infoObject.openTypeNameCompatibleFullName = 123
2023		writer = UFOWriter(self.dstDir, formatVersion=3)
2024		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2025		self.tearDownUFO()
2026		# openTypeNameSampleText
2027		infoObject = self.makeInfoObject()
2028		infoObject.openTypeNameSampleText = 123
2029		writer = UFOWriter(self.dstDir, formatVersion=3)
2030		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2031		self.tearDownUFO()
2032		# openTypeNameWWSFamilyName
2033		infoObject = self.makeInfoObject()
2034		infoObject.openTypeNameWWSFamilyName = 123
2035		writer = UFOWriter(self.dstDir, formatVersion=3)
2036		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2037		self.tearDownUFO()
2038		# openTypeNameWWSSubfamilyName
2039		infoObject = self.makeInfoObject()
2040		infoObject.openTypeNameWWSSubfamilyName = 123
2041		writer = UFOWriter(self.dstDir, formatVersion=3)
2042		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2043		self.tearDownUFO()
2044		# openTypeNameRecords
2045		## not a list
2046		infoObject = self.makeInfoObject()
2047		infoObject.openTypeNameRecords = "abc"
2048		writer = UFOWriter(self.dstDir, formatVersion=3)
2049		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2050		self.tearDownUFO()
2051		## not a dict
2052		infoObject = self.makeInfoObject()
2053		infoObject.openTypeNameRecords = ["abc"]
2054		writer = UFOWriter(self.dstDir, formatVersion=3)
2055		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2056		self.tearDownUFO()
2057		## invalid dict structure
2058		infoObject = self.makeInfoObject()
2059		infoObject.openTypeNameRecords = [dict(foo="bar")]
2060		writer = UFOWriter(self.dstDir, formatVersion=3)
2061		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2062		self.tearDownUFO()
2063		## incorrect keys
2064		infoObject = self.makeInfoObject()
2065		infoObject.openTypeNameRecords = [
2066			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string="Name Record.", foo="bar")
2067		]
2068		writer = UFOWriter(self.dstDir, formatVersion=3)
2069		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2070		self.tearDownUFO()
2071		infoObject = self.makeInfoObject()
2072		infoObject.openTypeNameRecords = [
2073			dict(platformID=1, encodingID=1, languageID=1, string="Name Record.")
2074		]
2075		writer = UFOWriter(self.dstDir, formatVersion=3)
2076		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2077		self.tearDownUFO()
2078		infoObject = self.makeInfoObject()
2079		infoObject.openTypeNameRecords = [
2080			dict(nameID=1, encodingID=1, languageID=1, string="Name Record.")
2081		]
2082		writer = UFOWriter(self.dstDir, formatVersion=3)
2083		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2084		self.tearDownUFO()
2085		infoObject = self.makeInfoObject()
2086		infoObject.openTypeNameRecords = [
2087			dict(nameID=1, platformID=1, languageID=1, string="Name Record.")
2088		]
2089		writer = UFOWriter(self.dstDir, formatVersion=3)
2090		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2091		self.tearDownUFO()
2092		infoObject = self.makeInfoObject()
2093		infoObject.openTypeNameRecords = [
2094			dict(nameID=1, platformID=1, encodingID=1, string="Name Record.")
2095		]
2096		writer = UFOWriter(self.dstDir, formatVersion=3)
2097		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2098		self.tearDownUFO()
2099		infoObject = self.makeInfoObject()
2100		infoObject.openTypeNameRecords = [
2101			dict(nameID=1, platformID=1, encodingID=1, languageID=1)
2102		]
2103		writer = UFOWriter(self.dstDir, formatVersion=3)
2104		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2105		self.tearDownUFO()
2106		## invalid values
2107		infoObject = self.makeInfoObject()
2108		infoObject.openTypeNameRecords = [
2109			dict(nameID="1", platformID=1, encodingID=1, languageID=1, string="Name Record.")
2110		]
2111		writer = UFOWriter(self.dstDir, formatVersion=3)
2112		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2113		self.tearDownUFO()
2114		infoObject = self.makeInfoObject()
2115		infoObject.openTypeNameRecords = [
2116			dict(nameID=1, platformID="1", encodingID=1, languageID=1, string="Name Record.")
2117		]
2118		writer = UFOWriter(self.dstDir, formatVersion=3)
2119		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2120		self.tearDownUFO()
2121		infoObject = self.makeInfoObject()
2122		infoObject.openTypeNameRecords = [
2123			dict(nameID=1, platformID=1, encodingID="1", languageID=1, string="Name Record.")
2124		]
2125		writer = UFOWriter(self.dstDir, formatVersion=3)
2126		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2127		self.tearDownUFO()
2128		infoObject = self.makeInfoObject()
2129		infoObject.openTypeNameRecords = [
2130			dict(nameID=1, platformID=1, encodingID=1, languageID="1", string="Name Record.")
2131		]
2132		writer = UFOWriter(self.dstDir, formatVersion=3)
2133		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2134		self.tearDownUFO()
2135		infoObject = self.makeInfoObject()
2136		infoObject.openTypeNameRecords = [
2137			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string=1)
2138		]
2139		writer = UFOWriter(self.dstDir, formatVersion=3)
2140		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2141		self.tearDownUFO()
2142		## duplicate
2143		infoObject = self.makeInfoObject()
2144		infoObject.openTypeNameRecords = [
2145			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string="Name Record."),
2146			dict(nameID=1, platformID=1, encodingID=1, languageID=1, string="Name Record.")
2147		]
2148		writer = UFOWriter(self.dstDir, formatVersion=3)
2149		writer.writeInfo(infoObject)
2150
2151	def testOS2Write(self):
2152		# openTypeOS2WidthClass
2153		## not an int
2154		infoObject = self.makeInfoObject()
2155		infoObject.openTypeOS2WidthClass = "abc"
2156		writer = UFOWriter(self.dstDir, formatVersion=3)
2157		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2158		self.tearDownUFO()
2159		## out or range
2160		infoObject = self.makeInfoObject()
2161		infoObject.openTypeOS2WidthClass = 15
2162		writer = UFOWriter(self.dstDir, formatVersion=3)
2163		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2164		self.tearDownUFO()
2165		# openTypeOS2WeightClass
2166		## not an int
2167		infoObject = self.makeInfoObject()
2168		infoObject.openTypeOS2WeightClass = "abc"
2169		writer = UFOWriter(self.dstDir, formatVersion=3)
2170		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2171		self.tearDownUFO()
2172		## out of range
2173		infoObject = self.makeInfoObject()
2174		infoObject.openTypeOS2WeightClass = -50
2175		writer = UFOWriter(self.dstDir, formatVersion=3)
2176		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2177		self.tearDownUFO()
2178		# openTypeOS2Selection
2179		infoObject = self.makeInfoObject()
2180		infoObject.openTypeOS2Selection = [-1]
2181		writer = UFOWriter(self.dstDir, formatVersion=3)
2182		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2183		self.tearDownUFO()
2184		# openTypeOS2VendorID
2185		infoObject = self.makeInfoObject()
2186		infoObject.openTypeOS2VendorID = 1234
2187		writer = UFOWriter(self.dstDir, formatVersion=3)
2188		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2189		self.tearDownUFO()
2190		# openTypeOS2Panose
2191		## not an int
2192		infoObject = self.makeInfoObject()
2193		infoObject.openTypeOS2Panose = [0, 1, 2, 3, 4, 5, 6, 7, 8, str(9)]
2194		writer = UFOWriter(self.dstDir, formatVersion=3)
2195		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2196		self.tearDownUFO()
2197		## too few values
2198		infoObject = self.makeInfoObject()
2199		infoObject.openTypeOS2Panose = [0, 1, 2, 3]
2200		writer = UFOWriter(self.dstDir, formatVersion=3)
2201		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2202		self.tearDownUFO()
2203		## too many values
2204		infoObject = self.makeInfoObject()
2205		infoObject.openTypeOS2Panose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2206		writer = UFOWriter(self.dstDir, formatVersion=3)
2207		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2208		self.tearDownUFO()
2209		# openTypeOS2FamilyClass
2210		## not an int
2211		infoObject = self.makeInfoObject()
2212		infoObject.openTypeOS2FamilyClass = [0, str(1)]
2213		writer = UFOWriter(self.dstDir, formatVersion=3)
2214		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2215		self.tearDownUFO()
2216		## too few values
2217		infoObject = self.makeInfoObject()
2218		infoObject.openTypeOS2FamilyClass = [1]
2219		writer = UFOWriter(self.dstDir, formatVersion=3)
2220		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2221		self.tearDownUFO()
2222		## too many values
2223		infoObject = self.makeInfoObject()
2224		infoObject.openTypeOS2FamilyClass = [1, 1, 1]
2225		writer = UFOWriter(self.dstDir, formatVersion=3)
2226		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2227		self.tearDownUFO()
2228		## out of range
2229		infoObject = self.makeInfoObject()
2230		infoObject.openTypeOS2FamilyClass = [1, 20]
2231		writer = UFOWriter(self.dstDir, formatVersion=3)
2232		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2233		self.tearDownUFO()
2234		# openTypeOS2UnicodeRanges
2235		## not an int
2236		infoObject = self.makeInfoObject()
2237		infoObject.openTypeOS2UnicodeRanges = ["0"]
2238		writer = UFOWriter(self.dstDir, formatVersion=3)
2239		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2240		self.tearDownUFO()
2241		## out of range
2242		infoObject = self.makeInfoObject()
2243		infoObject.openTypeOS2UnicodeRanges = [-1]
2244		writer = UFOWriter(self.dstDir, formatVersion=3)
2245		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2246		self.tearDownUFO()
2247		# openTypeOS2CodePageRanges
2248		## not an int
2249		infoObject = self.makeInfoObject()
2250		infoObject.openTypeOS2CodePageRanges = ["0"]
2251		writer = UFOWriter(self.dstDir, formatVersion=3)
2252		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2253		self.tearDownUFO()
2254		## out of range
2255		infoObject = self.makeInfoObject()
2256		infoObject.openTypeOS2CodePageRanges = [-1]
2257		writer = UFOWriter(self.dstDir, formatVersion=3)
2258		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2259		self.tearDownUFO()
2260		# openTypeOS2TypoAscender
2261		infoObject = self.makeInfoObject()
2262		infoObject.openTypeOS2TypoAscender = "abc"
2263		writer = UFOWriter(self.dstDir, formatVersion=3)
2264		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2265		self.tearDownUFO()
2266		# openTypeOS2TypoDescender
2267		infoObject = self.makeInfoObject()
2268		infoObject.openTypeOS2TypoDescender = "abc"
2269		writer = UFOWriter(self.dstDir, formatVersion=3)
2270		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2271		self.tearDownUFO()
2272		# openTypeOS2TypoLineGap
2273		infoObject = self.makeInfoObject()
2274		infoObject.openTypeOS2TypoLineGap = "abc"
2275		writer = UFOWriter(self.dstDir, formatVersion=3)
2276		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2277		self.tearDownUFO()
2278		# openTypeOS2WinAscent
2279		infoObject = self.makeInfoObject()
2280		infoObject.openTypeOS2WinAscent = "abc"
2281		writer = UFOWriter(self.dstDir, formatVersion=3)
2282		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2283		self.tearDownUFO()
2284		infoObject = self.makeInfoObject()
2285		infoObject.openTypeOS2WinAscent = -1
2286		writer = UFOWriter(self.dstDir, formatVersion=3)
2287		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2288		self.tearDownUFO()
2289		# openTypeOS2WinDescent
2290		infoObject = self.makeInfoObject()
2291		infoObject.openTypeOS2WinDescent = "abc"
2292		writer = UFOWriter(self.dstDir, formatVersion=3)
2293		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2294		self.tearDownUFO()
2295		infoObject = self.makeInfoObject()
2296		infoObject.openTypeOS2WinDescent = -1
2297		writer = UFOWriter(self.dstDir, formatVersion=3)
2298		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2299		self.tearDownUFO()
2300		# openTypeOS2Type
2301		## not an int
2302		infoObject = self.makeInfoObject()
2303		infoObject.openTypeOS2Type = ["1"]
2304		writer = UFOWriter(self.dstDir, formatVersion=3)
2305		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2306		self.tearDownUFO()
2307		## out of range
2308		infoObject = self.makeInfoObject()
2309		infoObject.openTypeOS2Type = [-1]
2310		writer = UFOWriter(self.dstDir, formatVersion=3)
2311		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2312		self.tearDownUFO()
2313		# openTypeOS2SubscriptXSize
2314		infoObject = self.makeInfoObject()
2315		infoObject.openTypeOS2SubscriptXSize = "abc"
2316		writer = UFOWriter(self.dstDir, formatVersion=3)
2317		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2318		self.tearDownUFO()
2319		# openTypeOS2SubscriptYSize
2320		infoObject = self.makeInfoObject()
2321		infoObject.openTypeOS2SubscriptYSize = "abc"
2322		writer = UFOWriter(self.dstDir, formatVersion=3)
2323		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2324		self.tearDownUFO()
2325		# openTypeOS2SubscriptXOffset
2326		infoObject = self.makeInfoObject()
2327		infoObject.openTypeOS2SubscriptXOffset = "abc"
2328		writer = UFOWriter(self.dstDir, formatVersion=3)
2329		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2330		self.tearDownUFO()
2331		# openTypeOS2SubscriptYOffset
2332		infoObject = self.makeInfoObject()
2333		infoObject.openTypeOS2SubscriptYOffset = "abc"
2334		writer = UFOWriter(self.dstDir, formatVersion=3)
2335		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2336		self.tearDownUFO()
2337		# openTypeOS2SuperscriptXSize
2338		infoObject = self.makeInfoObject()
2339		infoObject.openTypeOS2SuperscriptXSize = "abc"
2340		writer = UFOWriter(self.dstDir, formatVersion=3)
2341		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2342		self.tearDownUFO()
2343		# openTypeOS2SuperscriptYSize
2344		infoObject = self.makeInfoObject()
2345		infoObject.openTypeOS2SuperscriptYSize = "abc"
2346		writer = UFOWriter(self.dstDir, formatVersion=3)
2347		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2348		self.tearDownUFO()
2349		# openTypeOS2SuperscriptXOffset
2350		infoObject = self.makeInfoObject()
2351		infoObject.openTypeOS2SuperscriptXOffset = "abc"
2352		writer = UFOWriter(self.dstDir, formatVersion=3)
2353		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2354		self.tearDownUFO()
2355		# openTypeOS2SuperscriptYOffset
2356		infoObject = self.makeInfoObject()
2357		infoObject.openTypeOS2SuperscriptYOffset = "abc"
2358		writer = UFOWriter(self.dstDir, formatVersion=3)
2359		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2360		self.tearDownUFO()
2361		# openTypeOS2StrikeoutSize
2362		infoObject = self.makeInfoObject()
2363		infoObject.openTypeOS2StrikeoutSize = "abc"
2364		writer = UFOWriter(self.dstDir, formatVersion=3)
2365		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2366		self.tearDownUFO()
2367		# openTypeOS2StrikeoutPosition
2368		infoObject = self.makeInfoObject()
2369		infoObject.openTypeOS2StrikeoutPosition = "abc"
2370		writer = UFOWriter(self.dstDir, formatVersion=3)
2371		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2372		self.tearDownUFO()
2373
2374	def testVheaWrite(self):
2375		# openTypeVheaVertTypoAscender
2376		infoObject = self.makeInfoObject()
2377		infoObject.openTypeVheaVertTypoAscender = "abc"
2378		writer = UFOWriter(self.dstDir, formatVersion=3)
2379		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2380		self.tearDownUFO()
2381		# openTypeVheaVertTypoDescender
2382		infoObject = self.makeInfoObject()
2383		infoObject.openTypeVheaVertTypoDescender = "abc"
2384		writer = UFOWriter(self.dstDir, formatVersion=3)
2385		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2386		self.tearDownUFO()
2387		# openTypeVheaVertTypoLineGap
2388		infoObject = self.makeInfoObject()
2389		infoObject.openTypeVheaVertTypoLineGap = "abc"
2390		writer = UFOWriter(self.dstDir, formatVersion=3)
2391		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2392		self.tearDownUFO()
2393		# openTypeVheaCaretSlopeRise
2394		infoObject = self.makeInfoObject()
2395		infoObject.openTypeVheaCaretSlopeRise = "abc"
2396		writer = UFOWriter(self.dstDir, formatVersion=3)
2397		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2398		self.tearDownUFO()
2399		# openTypeVheaCaretSlopeRun
2400		infoObject = self.makeInfoObject()
2401		infoObject.openTypeVheaCaretSlopeRun = "abc"
2402		writer = UFOWriter(self.dstDir, formatVersion=3)
2403		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2404		self.tearDownUFO()
2405		# openTypeVheaCaretOffset
2406		infoObject = self.makeInfoObject()
2407		infoObject.openTypeVheaCaretOffset = "abc"
2408		writer = UFOWriter(self.dstDir, formatVersion=3)
2409		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2410		self.tearDownUFO()
2411
2412	def testFONDWrite(self):
2413		# macintoshFONDFamilyID
2414		infoObject = self.makeInfoObject()
2415		infoObject.macintoshFONDFamilyID = "abc"
2416		writer = UFOWriter(self.dstDir, formatVersion=3)
2417		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2418		self.tearDownUFO()
2419		# macintoshFONDName
2420		infoObject = self.makeInfoObject()
2421		infoObject.macintoshFONDName = 123
2422		writer = UFOWriter(self.dstDir, formatVersion=3)
2423		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2424		self.tearDownUFO()
2425
2426	def testPostscriptWrite(self):
2427		# postscriptFontName
2428		infoObject = self.makeInfoObject()
2429		infoObject.postscriptFontName = 123
2430		writer = UFOWriter(self.dstDir, formatVersion=3)
2431		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2432		self.tearDownUFO()
2433		# postscriptFullName
2434		infoObject = self.makeInfoObject()
2435		infoObject.postscriptFullName = 123
2436		writer = UFOWriter(self.dstDir, formatVersion=3)
2437		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2438		self.tearDownUFO()
2439		# postscriptSlantAngle
2440		infoObject = self.makeInfoObject()
2441		infoObject.postscriptSlantAngle = "abc"
2442		writer = UFOWriter(self.dstDir, formatVersion=3)
2443		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2444		self.tearDownUFO()
2445		# postscriptUniqueID
2446		infoObject = self.makeInfoObject()
2447		infoObject.postscriptUniqueID = "abc"
2448		writer = UFOWriter(self.dstDir, formatVersion=3)
2449		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2450		self.tearDownUFO()
2451		# postscriptUnderlineThickness
2452		infoObject = self.makeInfoObject()
2453		infoObject.postscriptUnderlineThickness = "abc"
2454		writer = UFOWriter(self.dstDir, formatVersion=3)
2455		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2456		self.tearDownUFO()
2457		# postscriptUnderlinePosition
2458		infoObject = self.makeInfoObject()
2459		infoObject.postscriptUnderlinePosition = "abc"
2460		writer = UFOWriter(self.dstDir, formatVersion=3)
2461		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2462		self.tearDownUFO()
2463		# postscriptIsFixedPitch
2464		infoObject = self.makeInfoObject()
2465		infoObject.postscriptIsFixedPitch = 2
2466		writer = UFOWriter(self.dstDir, formatVersion=3)
2467		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2468		self.tearDownUFO()
2469		# postscriptBlueValues
2470		## not a list
2471		infoObject = self.makeInfoObject()
2472		infoObject.postscriptBlueValues = "abc"
2473		writer = UFOWriter(self.dstDir, formatVersion=3)
2474		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2475		self.tearDownUFO()
2476		## uneven value count
2477		infoObject = self.makeInfoObject()
2478		infoObject.postscriptBlueValues = [500]
2479		writer = UFOWriter(self.dstDir, formatVersion=3)
2480		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2481		self.tearDownUFO()
2482		## too many values
2483		infoObject = self.makeInfoObject()
2484		infoObject.postscriptBlueValues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
2485		writer = UFOWriter(self.dstDir, formatVersion=3)
2486		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2487		self.tearDownUFO()
2488		# postscriptOtherBlues
2489		## not a list
2490		infoObject = self.makeInfoObject()
2491		infoObject.postscriptOtherBlues = "abc"
2492		writer = UFOWriter(self.dstDir, formatVersion=3)
2493		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2494		self.tearDownUFO()
2495		## uneven value count
2496		infoObject = self.makeInfoObject()
2497		infoObject.postscriptOtherBlues = [500]
2498		writer = UFOWriter(self.dstDir, formatVersion=3)
2499		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2500		self.tearDownUFO()
2501		## too many values
2502		infoObject = self.makeInfoObject()
2503		infoObject.postscriptOtherBlues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
2504		writer = UFOWriter(self.dstDir, formatVersion=3)
2505		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2506		self.tearDownUFO()
2507		# postscriptFamilyBlues
2508		## not a list
2509		infoObject = self.makeInfoObject()
2510		infoObject.postscriptFamilyBlues = "abc"
2511		writer = UFOWriter(self.dstDir, formatVersion=3)
2512		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2513		self.tearDownUFO()
2514		## uneven value count
2515		infoObject = self.makeInfoObject()
2516		infoObject.postscriptFamilyBlues = [500]
2517		writer = UFOWriter(self.dstDir, formatVersion=3)
2518		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2519		self.tearDownUFO()
2520		## too many values
2521		infoObject = self.makeInfoObject()
2522		infoObject.postscriptFamilyBlues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
2523		writer = UFOWriter(self.dstDir, formatVersion=3)
2524		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2525		self.tearDownUFO()
2526		# postscriptFamilyOtherBlues
2527		## not a list
2528		infoObject = self.makeInfoObject()
2529		infoObject.postscriptFamilyOtherBlues = "abc"
2530		writer = UFOWriter(self.dstDir, formatVersion=3)
2531		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2532		self.tearDownUFO()
2533		## uneven value count
2534		infoObject = self.makeInfoObject()
2535		infoObject.postscriptFamilyOtherBlues = [500]
2536		writer = UFOWriter(self.dstDir, formatVersion=3)
2537		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2538		self.tearDownUFO()
2539		## too many values
2540		infoObject = self.makeInfoObject()
2541		infoObject.postscriptFamilyOtherBlues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
2542		writer = UFOWriter(self.dstDir, formatVersion=3)
2543		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2544		self.tearDownUFO()
2545		# postscriptStemSnapH
2546		## not list
2547		infoObject = self.makeInfoObject()
2548		infoObject.postscriptStemSnapH = "abc"
2549		writer = UFOWriter(self.dstDir, formatVersion=3)
2550		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2551		self.tearDownUFO()
2552		## too many values
2553		infoObject = self.makeInfoObject()
2554		infoObject.postscriptStemSnapH = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
2555		writer = UFOWriter(self.dstDir, formatVersion=3)
2556		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2557		self.tearDownUFO()
2558		# postscriptStemSnapV
2559		## not list
2560		infoObject = self.makeInfoObject()
2561		infoObject.postscriptStemSnapV = "abc"
2562		writer = UFOWriter(self.dstDir, formatVersion=3)
2563		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2564		self.tearDownUFO()
2565		## too many values
2566		infoObject = self.makeInfoObject()
2567		infoObject.postscriptStemSnapV = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
2568		writer = UFOWriter(self.dstDir, formatVersion=3)
2569		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2570		self.tearDownUFO()
2571		# postscriptBlueFuzz
2572		infoObject = self.makeInfoObject()
2573		infoObject.postscriptBlueFuzz = "abc"
2574		writer = UFOWriter(self.dstDir, formatVersion=3)
2575		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2576		self.tearDownUFO()
2577		# postscriptBlueShift
2578		infoObject = self.makeInfoObject()
2579		infoObject.postscriptBlueShift = "abc"
2580		writer = UFOWriter(self.dstDir, formatVersion=3)
2581		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2582		self.tearDownUFO()
2583		# postscriptBlueScale
2584		infoObject = self.makeInfoObject()
2585		infoObject.postscriptBlueScale = "abc"
2586		writer = UFOWriter(self.dstDir, formatVersion=3)
2587		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2588		self.tearDownUFO()
2589		# postscriptForceBold
2590		infoObject = self.makeInfoObject()
2591		infoObject.postscriptForceBold = "abc"
2592		writer = UFOWriter(self.dstDir, formatVersion=3)
2593		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2594		self.tearDownUFO()
2595		# postscriptDefaultWidthX
2596		infoObject = self.makeInfoObject()
2597		infoObject.postscriptDefaultWidthX = "abc"
2598		writer = UFOWriter(self.dstDir, formatVersion=3)
2599		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2600		self.tearDownUFO()
2601		# postscriptNominalWidthX
2602		infoObject = self.makeInfoObject()
2603		infoObject.postscriptNominalWidthX = "abc"
2604		writer = UFOWriter(self.dstDir, formatVersion=3)
2605		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2606		self.tearDownUFO()
2607		# postscriptWeightName
2608		infoObject = self.makeInfoObject()
2609		infoObject.postscriptWeightName = 123
2610		writer = UFOWriter(self.dstDir, formatVersion=3)
2611		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2612		self.tearDownUFO()
2613		# postscriptDefaultCharacter
2614		infoObject = self.makeInfoObject()
2615		infoObject.postscriptDefaultCharacter = 123
2616		writer = UFOWriter(self.dstDir, formatVersion=3)
2617		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2618		self.tearDownUFO()
2619		# postscriptWindowsCharacterSet
2620		infoObject = self.makeInfoObject()
2621		infoObject.postscriptWindowsCharacterSet = -1
2622		writer = UFOWriter(self.dstDir, formatVersion=3)
2623		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2624		self.tearDownUFO()
2625		# macintoshFONDFamilyID
2626		infoObject = self.makeInfoObject()
2627		infoObject.macintoshFONDFamilyID = "abc"
2628		writer = UFOWriter(self.dstDir, formatVersion=3)
2629		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2630		self.tearDownUFO()
2631		# macintoshFONDName
2632		infoObject = self.makeInfoObject()
2633		infoObject.macintoshFONDName = 123
2634		writer = UFOWriter(self.dstDir, formatVersion=3)
2635		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2636		self.tearDownUFO()
2637
2638	def testWOFFWrite(self):
2639		# woffMajorVersion
2640		infoObject = self.makeInfoObject()
2641		infoObject.woffMajorVersion = 1.0
2642		writer = UFOWriter(self.dstDir, formatVersion=3)
2643		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2644		self.tearDownUFO()
2645		infoObject = self.makeInfoObject()
2646		infoObject.woffMajorVersion = "abc"
2647		writer = UFOWriter(self.dstDir, formatVersion=3)
2648		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2649		self.tearDownUFO()
2650		# woffMinorVersion
2651		infoObject = self.makeInfoObject()
2652		infoObject.woffMinorVersion = 1.0
2653		writer = UFOWriter(self.dstDir, formatVersion=3)
2654		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2655		self.tearDownUFO()
2656		infoObject = self.makeInfoObject()
2657		infoObject.woffMinorVersion = "abc"
2658		writer = UFOWriter(self.dstDir, formatVersion=3)
2659		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2660		self.tearDownUFO()
2661		# woffMetadataUniqueID
2662		## none
2663		infoObject = self.makeInfoObject()
2664		infoObject.woffMetadataUniqueID = None
2665		writer = UFOWriter(self.dstDir, formatVersion=3)
2666		writer.writeInfo(infoObject)
2667		self.tearDownUFO()
2668		## not a dict
2669		infoObject = self.makeInfoObject()
2670		infoObject.woffMetadataUniqueID = 1
2671		writer = UFOWriter(self.dstDir, formatVersion=3)
2672		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2673		self.tearDownUFO()
2674		## unknown key
2675		infoObject = self.makeInfoObject()
2676		infoObject.woffMetadataUniqueID = dict(id="foo", notTheRightKey=1)
2677		writer = UFOWriter(self.dstDir, formatVersion=3)
2678		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2679		self.tearDownUFO()
2680		## no id
2681		infoObject = self.makeInfoObject()
2682		infoObject.woffMetadataUniqueID = dict()
2683		writer = UFOWriter(self.dstDir, formatVersion=3)
2684		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2685		self.tearDownUFO()
2686		## not a string for id
2687		infoObject = self.makeInfoObject()
2688		infoObject.woffMetadataUniqueID = dict(id=1)
2689		writer = UFOWriter(self.dstDir, formatVersion=3)
2690		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2691		self.tearDownUFO()
2692		## empty string
2693		infoObject = self.makeInfoObject()
2694		infoObject.woffMetadataUniqueID = dict(id="")
2695		writer = UFOWriter(self.dstDir, formatVersion=3)
2696		writer.writeInfo(infoObject)
2697		self.tearDownUFO()
2698		# woffMetadataVendor
2699		## no name
2700		infoObject = self.makeInfoObject()
2701		infoObject.woffMetadataVendor = dict(url="foo")
2702		writer = UFOWriter(self.dstDir, formatVersion=3)
2703		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2704		self.tearDownUFO()
2705		## name not a string
2706		infoObject = self.makeInfoObject()
2707		infoObject.woffMetadataVendor = dict(name=1, url="foo")
2708		writer = UFOWriter(self.dstDir, formatVersion=3)
2709		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2710		self.tearDownUFO()
2711		## name an empty string
2712		infoObject = self.makeInfoObject()
2713		infoObject.woffMetadataVendor = dict(name="", url="foo")
2714		writer = UFOWriter(self.dstDir, formatVersion=3)
2715		writer.writeInfo(infoObject)
2716		self.tearDownUFO()
2717		## no URL
2718		infoObject = self.makeInfoObject()
2719		infoObject.woffMetadataVendor = dict(name="foo")
2720		writer = UFOWriter(self.dstDir, formatVersion=3)
2721		writer.writeInfo(infoObject)
2722		self.tearDownUFO()
2723		## url not a string
2724		infoObject = self.makeInfoObject()
2725		infoObject.woffMetadataVendor = dict(name="foo", url=1)
2726		writer = UFOWriter(self.dstDir, formatVersion=3)
2727		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2728		self.tearDownUFO()
2729		## url empty string
2730		infoObject = self.makeInfoObject()
2731		infoObject.woffMetadataVendor = dict(name="foo", url="")
2732		writer = UFOWriter(self.dstDir, formatVersion=3)
2733		writer.writeInfo(infoObject)
2734		self.tearDownUFO()
2735		## have dir
2736		infoObject = self.makeInfoObject()
2737		infoObject.woffMetadataVendor = dict(name="foo", url="bar", dir="ltr")
2738		writer = UFOWriter(self.dstDir, formatVersion=3)
2739		writer.writeInfo(infoObject)
2740		self.tearDownUFO()
2741		infoObject = self.makeInfoObject()
2742		infoObject.woffMetadataVendor = dict(name="foo", url="bar", dir="rtl")
2743		writer = UFOWriter(self.dstDir, formatVersion=3)
2744		writer.writeInfo(infoObject)
2745		self.tearDownUFO()
2746		## dir not a string
2747		infoObject = self.makeInfoObject()
2748		infoObject.woffMetadataVendor = dict(name="foo", url="bar", dir=1)
2749		writer = UFOWriter(self.dstDir, formatVersion=3)
2750		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2751		self.tearDownUFO()
2752		## dir not ltr or rtl
2753		infoObject = self.makeInfoObject()
2754		infoObject.woffMetadataVendor = dict(name="foo", url="bar", dir="utd")
2755		writer = UFOWriter(self.dstDir, formatVersion=3)
2756		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2757		self.tearDownUFO()
2758		## have class
2759		infoObject = self.makeInfoObject()
2760		infoObject.woffMetadataVendor = {"name"  : "foo", "url" : "bar", "class" : "hello"}
2761		writer = UFOWriter(self.dstDir, formatVersion=3)
2762		writer.writeInfo(infoObject)
2763		self.tearDownUFO()
2764		## class not a string
2765		infoObject = self.makeInfoObject()
2766		infoObject.woffMetadataVendor = {"name"  : "foo", "url" : "bar", "class" : 1}
2767		writer = UFOWriter(self.dstDir, formatVersion=3)
2768		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2769		self.tearDownUFO()
2770		## class empty string
2771		infoObject = self.makeInfoObject()
2772		infoObject.woffMetadataVendor = {"name"  : "foo", "url" : "bar", "class" : ""}
2773		writer = UFOWriter(self.dstDir, formatVersion=3)
2774		writer.writeInfo(infoObject)
2775		self.tearDownUFO()
2776		# woffMetadataCredits
2777		## no credits attribute
2778		infoObject = self.makeInfoObject()
2779		infoObject.woffMetadataCredits = {}
2780		writer = UFOWriter(self.dstDir, formatVersion=3)
2781		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2782		self.tearDownUFO()
2783		## unknown attribute
2784		infoObject = self.makeInfoObject()
2785		infoObject.woffMetadataCredits = dict(credits=[dict(name="foo")], notTheRightKey=1)
2786		writer = UFOWriter(self.dstDir, formatVersion=3)
2787		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2788		self.tearDownUFO()
2789		## not a list
2790		infoObject = self.makeInfoObject()
2791		infoObject.woffMetadataCredits = dict(credits="abc")
2792		writer = UFOWriter(self.dstDir, formatVersion=3)
2793		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2794		self.tearDownUFO()
2795		## no elements in credits
2796		infoObject = self.makeInfoObject()
2797		infoObject.woffMetadataCredits = dict(credits=[])
2798		writer = UFOWriter(self.dstDir, formatVersion=3)
2799		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2800		self.tearDownUFO()
2801		## credit not a dict
2802		infoObject = self.makeInfoObject()
2803		infoObject.woffMetadataCredits = dict(credits=["abc"])
2804		writer = UFOWriter(self.dstDir, formatVersion=3)
2805		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2806		self.tearDownUFO()
2807		## unknown key
2808		infoObject = self.makeInfoObject()
2809		infoObject.woffMetadataCredits = dict(credits=[dict(name="foo", notTheRightKey=1)])
2810		writer = UFOWriter(self.dstDir, formatVersion=3)
2811		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2812		self.tearDownUFO()
2813		## no name
2814		infoObject = self.makeInfoObject()
2815		infoObject.woffMetadataCredits = dict(credits=[dict(url="foo")])
2816		writer = UFOWriter(self.dstDir, formatVersion=3)
2817		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2818		self.tearDownUFO()
2819		## name not a string
2820		infoObject = self.makeInfoObject()
2821		infoObject.woffMetadataCredits = dict(credits=[dict(name=1)])
2822		writer = UFOWriter(self.dstDir, formatVersion=3)
2823		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2824		self.tearDownUFO()
2825		## url not a string
2826		infoObject = self.makeInfoObject()
2827		infoObject.woffMetadataCredits = dict(credits=[dict(name="foo", url=1)])
2828		writer = UFOWriter(self.dstDir, formatVersion=3)
2829		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2830		self.tearDownUFO()
2831		## role not a string
2832		infoObject = self.makeInfoObject()
2833		infoObject.woffMetadataCredits = dict(credits=[dict(name="foo", role=1)])
2834		writer = UFOWriter(self.dstDir, formatVersion=3)
2835		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2836		self.tearDownUFO()
2837		## dir not a string
2838		infoObject = self.makeInfoObject()
2839		infoObject.woffMetadataCredits = dict(credits=[dict(name="foo", dir=1)])
2840		writer = UFOWriter(self.dstDir, formatVersion=3)
2841		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2842		self.tearDownUFO()
2843		## dir not ltr or rtl
2844		infoObject = self.makeInfoObject()
2845		infoObject.woffMetadataCredits = dict(credits=[dict(name="foo", dir="utd")])
2846		writer = UFOWriter(self.dstDir, formatVersion=3)
2847		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2848		self.tearDownUFO()
2849		## class not a string
2850		infoObject = self.makeInfoObject()
2851		infoObject.woffMetadataCredits = dict(credits=[{"name"  : "foo", "class" : 1}])
2852		writer = UFOWriter(self.dstDir, formatVersion=3)
2853		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2854		self.tearDownUFO()
2855		# woffMetadataDescription
2856		## no url
2857		infoObject = self.makeInfoObject()
2858		infoObject.woffMetadataDescription = dict(text=[dict(text="foo")])
2859		writer = UFOWriter(self.dstDir, formatVersion=3)
2860		writer.writeInfo(infoObject)
2861		self.tearDownUFO()
2862		## url not a string
2863		infoObject = self.makeInfoObject()
2864		infoObject.woffMetadataDescription = dict(text=[dict(text="foo")], url=1)
2865		writer = UFOWriter(self.dstDir, formatVersion=3)
2866		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2867		self.tearDownUFO()
2868		## no text
2869		infoObject = self.makeInfoObject()
2870		infoObject.woffMetadataDescription = dict(url="foo")
2871		writer = UFOWriter(self.dstDir, formatVersion=3)
2872		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2873		self.tearDownUFO()
2874		## text not a list
2875		infoObject = self.makeInfoObject()
2876		infoObject.woffMetadataDescription = dict(text="abc")
2877		writer = UFOWriter(self.dstDir, formatVersion=3)
2878		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2879		self.tearDownUFO()
2880		## text item not a dict
2881		infoObject = self.makeInfoObject()
2882		infoObject.woffMetadataDescription = dict(text=["abc"])
2883		writer = UFOWriter(self.dstDir, formatVersion=3)
2884		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2885		self.tearDownUFO()
2886		## text item unknown key
2887		infoObject = self.makeInfoObject()
2888		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", notTheRightKey=1)])
2889		writer = UFOWriter(self.dstDir, formatVersion=3)
2890		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2891		self.tearDownUFO()
2892		## text item missing text
2893		infoObject = self.makeInfoObject()
2894		infoObject.woffMetadataDescription = dict(text=[dict(language="foo")])
2895		writer = UFOWriter(self.dstDir, formatVersion=3)
2896		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2897		self.tearDownUFO()
2898		## text not a string
2899		infoObject = self.makeInfoObject()
2900		infoObject.woffMetadataDescription = dict(text=[dict(text=1)])
2901		writer = UFOWriter(self.dstDir, formatVersion=3)
2902		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2903		self.tearDownUFO()
2904		## url not a string
2905		infoObject = self.makeInfoObject()
2906		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", url=1)])
2907		writer = UFOWriter(self.dstDir, formatVersion=3)
2908		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2909		self.tearDownUFO()
2910		## language not a string
2911		infoObject = self.makeInfoObject()
2912		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", language=1)])
2913		writer = UFOWriter(self.dstDir, formatVersion=3)
2914		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2915		self.tearDownUFO()
2916		## dir not ltr or rtl
2917		infoObject = self.makeInfoObject()
2918		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", dir="utd")])
2919		writer = UFOWriter(self.dstDir, formatVersion=3)
2920		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2921		self.tearDownUFO()
2922		## class not a string
2923		infoObject = self.makeInfoObject()
2924		infoObject.woffMetadataDescription = dict(text=[{"text"  : "foo", "class" : 1}])
2925		writer = UFOWriter(self.dstDir, formatVersion=3)
2926		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2927		self.tearDownUFO()
2928		# woffMetadataLicense
2929		## no url
2930		infoObject = self.makeInfoObject()
2931		infoObject.woffMetadataLicense = dict(text=[dict(text="foo")])
2932		writer = UFOWriter(self.dstDir, formatVersion=3)
2933		writer.writeInfo(infoObject)
2934		self.tearDownUFO()
2935		## url not a string
2936		infoObject = self.makeInfoObject()
2937		infoObject.woffMetadataLicense = dict(text=[dict(text="foo")], url=1)
2938		writer = UFOWriter(self.dstDir, formatVersion=3)
2939		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2940		self.tearDownUFO()
2941		## id not a string
2942		infoObject = self.makeInfoObject()
2943		infoObject.woffMetadataLicense = dict(text=[dict(text="foo")], id=1)
2944		writer = UFOWriter(self.dstDir, formatVersion=3)
2945		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2946		self.tearDownUFO()
2947		## no text
2948		infoObject = self.makeInfoObject()
2949		infoObject.woffMetadataLicense = dict(url="foo")
2950		writer = UFOWriter(self.dstDir, formatVersion=3)
2951		writer.writeInfo(infoObject)
2952		self.tearDownUFO()
2953		## text not a list
2954		infoObject = self.makeInfoObject()
2955		infoObject.woffMetadataLicense = dict(text="abc")
2956		writer = UFOWriter(self.dstDir, formatVersion=3)
2957		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2958		self.tearDownUFO()
2959		## text item not a dict
2960		infoObject = self.makeInfoObject()
2961		infoObject.woffMetadataLicense = dict(text=["abc"])
2962		writer = UFOWriter(self.dstDir, formatVersion=3)
2963		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2964		self.tearDownUFO()
2965		## text item unknown key
2966		infoObject = self.makeInfoObject()
2967		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", notTheRightKey=1)])
2968		writer = UFOWriter(self.dstDir, formatVersion=3)
2969		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2970		self.tearDownUFO()
2971		## text item missing text
2972		infoObject = self.makeInfoObject()
2973		writer = UFOWriter(self.dstDir, formatVersion=3)
2974		infoObject.woffMetadataLicense = dict(text=[dict(language="foo")])
2975		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2976		self.tearDownUFO()
2977		## text not a string
2978		infoObject = self.makeInfoObject()
2979		writer = UFOWriter(self.dstDir, formatVersion=3)
2980		infoObject.woffMetadataLicense = dict(text=[dict(text=1)])
2981		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2982		self.tearDownUFO()
2983		## url not a string
2984		infoObject = self.makeInfoObject()
2985		writer = UFOWriter(self.dstDir, formatVersion=3)
2986		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", url=1)])
2987		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2988		self.tearDownUFO()
2989		## language not a string
2990		infoObject = self.makeInfoObject()
2991		writer = UFOWriter(self.dstDir, formatVersion=3)
2992		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", language=1)])
2993		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2994		self.tearDownUFO()
2995		## dir not ltr or rtl
2996		infoObject = self.makeInfoObject()
2997		writer = UFOWriter(self.dstDir, formatVersion=3)
2998		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", dir="utd")])
2999		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3000		self.tearDownUFO()
3001		## class not a string
3002		infoObject = self.makeInfoObject()
3003		writer = UFOWriter(self.dstDir, formatVersion=3)
3004		infoObject.woffMetadataLicense = dict(text=[{"text"  : "foo", "class" : 1}])
3005		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3006		self.tearDownUFO()
3007		# woffMetadataCopyright
3008		## unknown attribute
3009		infoObject = self.makeInfoObject()
3010		writer = UFOWriter(self.dstDir, formatVersion=3)
3011		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo")], notTheRightKey=1)
3012		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3013		self.tearDownUFO()
3014		## no text
3015		infoObject = self.makeInfoObject()
3016		writer = UFOWriter(self.dstDir, formatVersion=3)
3017		infoObject.woffMetadataCopyright = dict()
3018		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3019		self.tearDownUFO()
3020		## text not a list
3021		infoObject = self.makeInfoObject()
3022		writer = UFOWriter(self.dstDir, formatVersion=3)
3023		infoObject.woffMetadataCopyright = dict(text="abc")
3024		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3025		self.tearDownUFO()
3026		## text item not a dict
3027		infoObject = self.makeInfoObject()
3028		writer = UFOWriter(self.dstDir, formatVersion=3)
3029		infoObject.woffMetadataCopyright = dict(text=["abc"])
3030		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3031		self.tearDownUFO()
3032		## text item unknown key
3033		infoObject = self.makeInfoObject()
3034		writer = UFOWriter(self.dstDir, formatVersion=3)
3035		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", notTheRightKey=1)])
3036		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3037		self.tearDownUFO()
3038		## text item missing text
3039		infoObject = self.makeInfoObject()
3040		infoObject.woffMetadataCopyright = dict(text=[dict(language="foo")])
3041		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3042		self.tearDownUFO()
3043		## text not a string
3044		infoObject = self.makeInfoObject()
3045		writer = UFOWriter(self.dstDir, formatVersion=3)
3046		infoObject.woffMetadataCopyright = dict(text=[dict(text=1)])
3047		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3048		self.tearDownUFO()
3049		## url not a string
3050		infoObject = self.makeInfoObject()
3051		writer = UFOWriter(self.dstDir, formatVersion=3)
3052		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", url=1)])
3053		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3054		self.tearDownUFO()
3055		## language not a string
3056		infoObject = self.makeInfoObject()
3057		writer = UFOWriter(self.dstDir, formatVersion=3)
3058		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", language=1)])
3059		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3060		self.tearDownUFO()
3061		## dir not ltr or rtl
3062		infoObject = self.makeInfoObject()
3063		writer = UFOWriter(self.dstDir, formatVersion=3)
3064		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", dir="utd")])
3065		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3066		self.tearDownUFO()
3067		## class not a string
3068		infoObject = self.makeInfoObject()
3069		writer = UFOWriter(self.dstDir, formatVersion=3)
3070		infoObject.woffMetadataCopyright = dict(text=[{"text"  : "foo", "class" : 1}])
3071		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3072		self.tearDownUFO()
3073		# woffMetadataTrademark
3074		## unknown attribute
3075		infoObject = self.makeInfoObject()
3076		writer = UFOWriter(self.dstDir, formatVersion=3)
3077		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo")], notTheRightKey=1)
3078		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3079		self.tearDownUFO()
3080		## no text
3081		infoObject = self.makeInfoObject()
3082		writer = UFOWriter(self.dstDir, formatVersion=3)
3083		infoObject.woffMetadataTrademark = dict()
3084		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3085		self.tearDownUFO()
3086		## text not a list
3087		infoObject = self.makeInfoObject()
3088		writer = UFOWriter(self.dstDir, formatVersion=3)
3089		infoObject.woffMetadataTrademark = dict(text="abc")
3090		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3091		self.tearDownUFO()
3092		## text item not a dict
3093		infoObject = self.makeInfoObject()
3094		writer = UFOWriter(self.dstDir, formatVersion=3)
3095		infoObject.woffMetadataTrademark = dict(text=["abc"])
3096		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3097		self.tearDownUFO()
3098		## text item unknown key
3099		infoObject = self.makeInfoObject()
3100		writer = UFOWriter(self.dstDir, formatVersion=3)
3101		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", notTheRightKey=1)])
3102		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3103		self.tearDownUFO()
3104		## text item missing text
3105		infoObject = self.makeInfoObject()
3106		writer = UFOWriter(self.dstDir, formatVersion=3)
3107		infoObject.woffMetadataTrademark = dict(text=[dict(language="foo")])
3108		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3109		self.tearDownUFO()
3110		## text not a string
3111		infoObject = self.makeInfoObject()
3112		writer = UFOWriter(self.dstDir, formatVersion=3)
3113		infoObject.woffMetadataTrademark = dict(text=[dict(text=1)])
3114		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3115		self.tearDownUFO()
3116		## url not a string
3117		infoObject = self.makeInfoObject()
3118		writer = UFOWriter(self.dstDir, formatVersion=3)
3119		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", url=1)])
3120		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3121		self.tearDownUFO()
3122		## language not a string
3123		infoObject = self.makeInfoObject()
3124		writer = UFOWriter(self.dstDir, formatVersion=3)
3125		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", language=1)])
3126		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3127		self.tearDownUFO()
3128		## dir not ltr or rtl
3129		infoObject = self.makeInfoObject()
3130		writer = UFOWriter(self.dstDir, formatVersion=3)
3131		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", dir="utd")])
3132		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3133		self.tearDownUFO()
3134		## class not a string
3135		infoObject = self.makeInfoObject()
3136		writer = UFOWriter(self.dstDir, formatVersion=3)
3137		infoObject.woffMetadataTrademark = dict(text=[{"text"  : "foo", "class" : 1}])
3138		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3139		self.tearDownUFO()
3140		# woffMetadataLicensee
3141		## no name
3142		infoObject = self.makeInfoObject()
3143		writer = UFOWriter(self.dstDir, formatVersion=3)
3144		infoObject.woffMetadataLicensee = dict()
3145		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3146		self.tearDownUFO()
3147		## unknown attribute
3148		infoObject = self.makeInfoObject()
3149		writer = UFOWriter(self.dstDir, formatVersion=3)
3150		infoObject.woffMetadataLicensee = dict(name="foo", notTheRightKey=1)
3151		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3152		self.tearDownUFO()
3153		## name not a string
3154		infoObject = self.makeInfoObject()
3155		writer = UFOWriter(self.dstDir, formatVersion=3)
3156		infoObject.woffMetadataLicensee = dict(name=1)
3157		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3158		self.tearDownUFO()
3159		## dir options
3160		infoObject = self.makeInfoObject()
3161		infoObject.woffMetadataLicensee = dict(name="foo", dir="ltr")
3162		writer = UFOWriter(self.dstDir, formatVersion=3)
3163		writer.writeInfo(infoObject)
3164		self.tearDownUFO()
3165		infoObject = self.makeInfoObject()
3166		infoObject.woffMetadataLicensee = dict(name="foo", dir="rtl")
3167		writer = UFOWriter(self.dstDir, formatVersion=3)
3168		writer.writeInfo(infoObject)
3169		self.tearDownUFO()
3170		## dir not ltr or rtl
3171		infoObject = self.makeInfoObject()
3172		infoObject.woffMetadataLicensee = dict(name="foo", dir="utd")
3173		writer = UFOWriter(self.dstDir, formatVersion=3)
3174		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3175		self.tearDownUFO()
3176		## have class
3177		infoObject = self.makeInfoObject()
3178		infoObject.woffMetadataLicensee = {"name" : "foo", "class" : "hello"}
3179		writer = UFOWriter(self.dstDir, formatVersion=3)
3180		writer.writeInfo(infoObject)
3181		self.tearDownUFO()
3182		## class not a string
3183		infoObject = self.makeInfoObject()
3184		infoObject.woffMetadataLicensee = {"name" : "foo", "class" : 1}
3185		writer = UFOWriter(self.dstDir, formatVersion=3)
3186		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3187		self.tearDownUFO()
3188
3189	def testGuidelinesWrite(self):
3190		# x
3191		## not an int or float
3192		infoObject = self.makeInfoObject()
3193		infoObject.guidelines = [dict(x="1")]
3194		writer = UFOWriter(self.dstDir, formatVersion=3)
3195		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3196		self.tearDownUFO()
3197		# y
3198		## not an int or float
3199		infoObject = self.makeInfoObject()
3200		infoObject.guidelines = [dict(y="1")]
3201		writer = UFOWriter(self.dstDir, formatVersion=3)
3202		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3203		self.tearDownUFO()
3204		# angle
3205		## < 0
3206		infoObject = self.makeInfoObject()
3207		infoObject.guidelines = [dict(x=0, y=0, angle=-1)]
3208		writer = UFOWriter(self.dstDir, formatVersion=3)
3209		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3210		self.tearDownUFO()
3211		## > 360
3212		infoObject = self.makeInfoObject()
3213		infoObject.guidelines = [dict(x=0, y=0, angle=361)]
3214		writer = UFOWriter(self.dstDir, formatVersion=3)
3215		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3216		self.tearDownUFO()
3217		# name
3218		## not a string
3219		infoObject = self.makeInfoObject()
3220		infoObject.guidelines = [dict(x=0, name=1)]
3221		writer = UFOWriter(self.dstDir, formatVersion=3)
3222		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3223		self.tearDownUFO()
3224		# color
3225		## not a string
3226		infoObject = self.makeInfoObject()
3227		infoObject.guidelines = [dict(x=0, color=1)]
3228		writer = UFOWriter(self.dstDir, formatVersion=3)
3229		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3230		self.tearDownUFO()
3231		## not enough commas
3232		infoObject = self.makeInfoObject()
3233		infoObject.guidelines = [dict(x=0, color="1 0, 0, 0")]
3234		writer = UFOWriter(self.dstDir, formatVersion=3)
3235		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3236		self.tearDownUFO()
3237		infoObject = self.makeInfoObject()
3238		infoObject.guidelines = [dict(x=0, color="1 0 0, 0")]
3239		writer = UFOWriter(self.dstDir, formatVersion=3)
3240		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3241		self.tearDownUFO()
3242		infoObject = self.makeInfoObject()
3243		infoObject.guidelines = [dict(x=0, color="1 0 0 0")]
3244		writer = UFOWriter(self.dstDir, formatVersion=3)
3245		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3246		self.tearDownUFO()
3247		## not enough parts
3248		infoObject = self.makeInfoObject()
3249		infoObject.guidelines = [dict(x=0, color=", 0, 0, 0")]
3250		writer = UFOWriter(self.dstDir, formatVersion=3)
3251		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3252		self.tearDownUFO()
3253		infoObject = self.makeInfoObject()
3254		infoObject.guidelines = [dict(x=0, color="1, , 0, 0")]
3255		writer = UFOWriter(self.dstDir, formatVersion=3)
3256		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3257		self.tearDownUFO()
3258		infoObject = self.makeInfoObject()
3259		infoObject.guidelines = [dict(x=0, color="1, 0, , 0")]
3260		writer = UFOWriter(self.dstDir, formatVersion=3)
3261		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3262		self.tearDownUFO()
3263		infoObject = self.makeInfoObject()
3264		infoObject.guidelines = [dict(x=0, color="1, 0, 0, ")]
3265		writer = UFOWriter(self.dstDir, formatVersion=3)
3266		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3267		self.tearDownUFO()
3268		infoObject = self.makeInfoObject()
3269		infoObject.guidelines = [dict(x=0, color=", , , ")]
3270		writer = UFOWriter(self.dstDir, formatVersion=3)
3271		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3272		self.tearDownUFO()
3273		## not a number in all positions
3274		infoObject = self.makeInfoObject()
3275		infoObject.guidelines = [dict(x=0, color="r, 1, 1, 1")]
3276		writer = UFOWriter(self.dstDir, formatVersion=3)
3277		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3278		self.tearDownUFO()
3279		infoObject = self.makeInfoObject()
3280		infoObject.guidelines = [dict(x=0, color="1, g, 1, 1")]
3281		writer = UFOWriter(self.dstDir, formatVersion=3)
3282		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3283		self.tearDownUFO()
3284		infoObject = self.makeInfoObject()
3285		infoObject.guidelines = [dict(x=0, color="1, 1, b, 1")]
3286		writer = UFOWriter(self.dstDir, formatVersion=3)
3287		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3288		self.tearDownUFO()
3289		infoObject = self.makeInfoObject()
3290		infoObject.guidelines = [dict(x=0, color="1, 1, 1, a")]
3291		writer = UFOWriter(self.dstDir, formatVersion=3)
3292		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3293		self.tearDownUFO()
3294		## too many parts
3295		infoObject = self.makeInfoObject()
3296		infoObject.guidelines = [dict(x=0, color="1, 0, 0, 0, 0")]
3297		writer = UFOWriter(self.dstDir, formatVersion=3)
3298		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3299		self.tearDownUFO()
3300		## < 0 in each position
3301		infoObject = self.makeInfoObject()
3302		infoObject.guidelines = [dict(x=0, color="-1, 0, 0, 0")]
3303		writer = UFOWriter(self.dstDir, formatVersion=3)
3304		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3305		self.tearDownUFO()
3306		infoObject = self.makeInfoObject()
3307		infoObject.guidelines = [dict(x=0, color="0, -1, 0, 0")]
3308		writer = UFOWriter(self.dstDir, formatVersion=3)
3309		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3310		self.tearDownUFO()
3311		infoObject = self.makeInfoObject()
3312		infoObject.guidelines = [dict(x=0, color="0, 0, -1, 0")]
3313		writer = UFOWriter(self.dstDir, formatVersion=3)
3314		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3315		self.tearDownUFO()
3316		infoObject = self.makeInfoObject()
3317		infoObject.guidelines = [dict(x=0, color="0, 0, 0, -1")]
3318		writer = UFOWriter(self.dstDir, formatVersion=3)
3319		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3320		self.tearDownUFO()
3321		## > 1 in each position
3322		infoObject = self.makeInfoObject()
3323		infoObject.guidelines = [dict(x=0, color="2, 0, 0, 0")]
3324		writer = UFOWriter(self.dstDir, formatVersion=3)
3325		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3326		self.tearDownUFO()
3327		infoObject = self.makeInfoObject()
3328		infoObject.guidelines = [dict(x=0, color="0, 2, 0, 0")]
3329		writer = UFOWriter(self.dstDir, formatVersion=3)
3330		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3331		self.tearDownUFO()
3332		infoObject = self.makeInfoObject()
3333		infoObject.guidelines = [dict(x=0, color="0, 0, 2, 0")]
3334		writer = UFOWriter(self.dstDir, formatVersion=3)
3335		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3336		self.tearDownUFO()
3337		infoObject = self.makeInfoObject()
3338		infoObject.guidelines = [dict(x=0, color="0, 0, 0, 2")]
3339		writer = UFOWriter(self.dstDir, formatVersion=3)
3340		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3341		self.tearDownUFO()
3342		# identifier
3343		## duplicate
3344		infoObject = self.makeInfoObject()
3345		infoObject.guidelines = [dict(x=0, identifier="guide1"), dict(y=0, identifier="guide1")]
3346		writer = UFOWriter(self.dstDir, formatVersion=3)
3347		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3348		self.tearDownUFO()
3349		## below min
3350		infoObject = self.makeInfoObject()
3351		infoObject.guidelines = [dict(x=0, identifier="\0x1F")]
3352		writer = UFOWriter(self.dstDir, formatVersion=3)
3353		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3354		self.tearDownUFO()
3355		## above max
3356		infoObject = self.makeInfoObject()
3357		infoObject.guidelines = [dict(x=0, identifier="\0x7F")]
3358		writer = UFOWriter(self.dstDir, formatVersion=3)
3359		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3360		self.tearDownUFO()
3361
3362
3363# ------
3364# layers
3365# ------
3366
3367class UFO3ReadLayersTestCase(unittest.TestCase):
3368
3369	def setUp(self):
3370		self.tempDir = tempfile.mktemp()
3371		os.mkdir(self.tempDir)
3372		self.ufoPath = os.path.join(self.tempDir, "test.ufo")
3373
3374	def tearDown(self):
3375		shutil.rmtree(self.tempDir)
3376
3377	def makeUFO(self, metaInfo=None, layerContents=None):
3378		self.clearUFO()
3379		if not os.path.exists(self.ufoPath):
3380			os.mkdir(self.ufoPath)
3381		# metainfo.plist
3382		if metaInfo is None:
3383			metaInfo = dict(creator="test", formatVersion=3)
3384		path = os.path.join(self.ufoPath, "metainfo.plist")
3385		with open(path, "wb") as f:
3386			plistlib.dump(metaInfo, f)
3387		# layers
3388		if layerContents is None:
3389			layerContents = [
3390				("public.default", "glyphs"),
3391				("layer 1", "glyphs.layer 1"),
3392				("layer 2", "glyphs.layer 2"),
3393			]
3394		if layerContents:
3395			path = os.path.join(self.ufoPath, "layercontents.plist")
3396			with open(path, "wb") as f:
3397				plistlib.dump(layerContents, f)
3398		else:
3399			layerContents = [("", "glyphs")]
3400		for name, directory in layerContents:
3401			glyphsPath = os.path.join(self.ufoPath, directory)
3402			os.mkdir(glyphsPath)
3403			contents = dict(a="a.glif")
3404			path = os.path.join(glyphsPath, "contents.plist")
3405			with open(path, "wb") as f:
3406				plistlib.dump(contents, f)
3407			path = os.path.join(glyphsPath, "a.glif")
3408			with open(path, "w") as f:
3409				f.write(" ")
3410
3411	def clearUFO(self):
3412		if os.path.exists(self.ufoPath):
3413			shutil.rmtree(self.ufoPath)
3414
3415	# valid
3416
3417	def testValidRead(self):
3418		# UFO 1
3419		self.makeUFO(
3420			metaInfo=dict(creator="test", formatVersion=1),
3421			layerContents=dict()
3422		)
3423		reader = UFOReader(self.ufoPath, validate=True)
3424		reader.getGlyphSet()
3425		# UFO 2
3426		self.makeUFO(
3427			metaInfo=dict(creator="test", formatVersion=2),
3428			layerContents=dict()
3429		)
3430		reader = UFOReader(self.ufoPath, validate=True)
3431		reader.getGlyphSet()
3432		# UFO 3
3433		self.makeUFO()
3434		reader = UFOReader(self.ufoPath, validate=True)
3435		reader.getGlyphSet()
3436
3437	# missing layer contents
3438
3439	def testMissingLayerContents(self):
3440		self.makeUFO()
3441		path = os.path.join(self.ufoPath, "layercontents.plist")
3442		os.remove(path)
3443		reader = UFOReader(self.ufoPath, validate=True)
3444		self.assertRaises(UFOLibError, reader.getGlyphSet)
3445
3446	# layer contents invalid format
3447
3448	def testInvalidLayerContentsFormat(self):
3449		# bogus
3450		self.makeUFO()
3451		path = os.path.join(self.ufoPath, "layercontents.plist")
3452		os.remove(path)
3453		with open(path, "w") as f:
3454			f.write("test")
3455		reader = UFOReader(self.ufoPath, validate=True)
3456		self.assertRaises(UFOLibError, reader.getGlyphSet)
3457		# dict
3458		self.makeUFO()
3459		path = os.path.join(self.ufoPath, "layercontents.plist")
3460		os.remove(path)
3461		layerContents = {
3462			"public.default" : "glyphs",
3463			"layer 1" : "glyphs.layer 1",
3464			"layer 2" : "glyphs.layer 2",
3465		}
3466		with open(path, "wb") as f:
3467			plistlib.dump(layerContents, f)
3468		reader = UFOReader(self.ufoPath, validate=True)
3469		self.assertRaises(UFOLibError, reader.getGlyphSet)
3470
3471	# layer contents invalid name format
3472
3473	def testInvalidLayerContentsNameFormat(self):
3474		self.makeUFO()
3475		path = os.path.join(self.ufoPath, "layercontents.plist")
3476		os.remove(path)
3477		layerContents = [
3478			(1, "glyphs"),
3479			("layer 1", "glyphs.layer 1"),
3480			("layer 2", "glyphs.layer 2")
3481		]
3482		with open(path, "wb") as f:
3483			plistlib.dump(layerContents, f)
3484		reader = UFOReader(self.ufoPath, validate=True)
3485		self.assertRaises(UFOLibError, reader.getGlyphSet)
3486
3487	# layer contents invalid directory format
3488
3489	def testInvalidLayerContentsDirectoryFormat(self):
3490		self.makeUFO()
3491		path = os.path.join(self.ufoPath, "layercontents.plist")
3492		os.remove(path)
3493		layerContents = [
3494			("public.foregound", "glyphs"),
3495			("layer 1", 1),
3496			("layer 2", "glyphs.layer 2")
3497		]
3498		with open(path, "wb") as f:
3499			plistlib.dump(layerContents, f)
3500		reader = UFOReader(self.ufoPath, validate=True)
3501		self.assertRaises(UFOLibError, reader.getGlyphSet)
3502
3503	# directory listed in contents not on disk
3504
3505	def testLayerContentsHasMissingDirectory(self):
3506		self.makeUFO()
3507		path = os.path.join(self.ufoPath, "layercontents.plist")
3508		os.remove(path)
3509		layerContents = [
3510			("public.foregound", "glyphs"),
3511			("layer 1", "glyphs.doesnotexist"),
3512			("layer 2", "glyphs.layer 2")
3513		]
3514		with open(path, "wb") as f:
3515			plistlib.dump(layerContents, f)
3516		reader = UFOReader(self.ufoPath, validate=True)
3517		self.assertRaises(UFOLibError, reader.getGlyphSet)
3518
3519	# # directory on disk not listed in contents
3520	# XXX should this raise an error?
3521	#
3522	# def testLayerContentsHasMissingDirectory(self):
3523	# 	self.makeUFO()
3524	# 	path = os.path.join(self.ufoPath, "layercontents.plist")
3525	# 	os.remove(path)
3526	# 	layerContents = [
3527	# 		("public.foregound", "glyphs"),
3528	# 		("layer 1", "glyphs.layer 2")
3529	# 	]
3530	# 	with open(path, "wb") as f:
3531	# 		plistlib.dump(layerContents, f)
3532	# 	reader = UFOReader(self.ufoPath, validate=True)
3533	# 	with self.assertRaises(UFOLibError):
3534	# 		reader.getGlyphSet()
3535
3536	# no default layer on disk
3537
3538	def testMissingDefaultLayer(self):
3539		self.makeUFO()
3540		path = os.path.join(self.ufoPath, "layercontents.plist")
3541		os.remove(path)
3542		layerContents = [
3543			("layer 1", "glyphs.layer 1"),
3544			("layer 2", "glyphs.layer 2")
3545		]
3546		with open(path, "wb") as f:
3547			plistlib.dump(layerContents, f)
3548		reader = UFOReader(self.ufoPath, validate=True)
3549		self.assertRaises(UFOLibError, reader.getGlyphSet)
3550
3551	# duplicate layer name
3552
3553	def testDuplicateLayerName(self):
3554		self.makeUFO()
3555		path = os.path.join(self.ufoPath, "layercontents.plist")
3556		os.remove(path)
3557		layerContents = [
3558			("public.foregound", "glyphs"),
3559			("layer 1", "glyphs.layer 1"),
3560			("layer 1", "glyphs.layer 2")
3561		]
3562		with open(path, "wb") as f:
3563			plistlib.dump(layerContents, f)
3564		reader = UFOReader(self.ufoPath, validate=True)
3565		self.assertRaises(UFOLibError, reader.getGlyphSet)
3566
3567	# directory referenced by two layer names
3568
3569	def testDuplicateLayerDirectory(self):
3570		self.makeUFO()
3571		path = os.path.join(self.ufoPath, "layercontents.plist")
3572		os.remove(path)
3573		layerContents = [
3574			("public.foregound", "glyphs"),
3575			("layer 1", "glyphs.layer 1"),
3576			("layer 2", "glyphs.layer 1")
3577		]
3578		with open(path, "wb") as f:
3579			plistlib.dump(layerContents, f)
3580		reader = UFOReader(self.ufoPath, validate=True)
3581		self.assertRaises(UFOLibError, reader.getGlyphSet)
3582
3583	# default without a name
3584
3585	def testDefaultLayerNoName(self):
3586		# get the glyph set
3587		self.makeUFO()
3588		path = os.path.join(self.ufoPath, "layercontents.plist")
3589		os.remove(path)
3590		layerContents = [
3591			("public.foregound", "glyphs"),
3592			("layer 1", "glyphs.layer 1"),
3593			("layer 2", "glyphs.layer 2")
3594		]
3595		with open(path, "wb") as f:
3596			plistlib.dump(layerContents, f)
3597		reader = UFOReader(self.ufoPath, validate=True)
3598		reader.getGlyphSet()
3599
3600	# default with a name
3601
3602	def testDefaultLayerName(self):
3603		# get the name
3604		self.makeUFO()
3605		path = os.path.join(self.ufoPath, "layercontents.plist")
3606		os.remove(path)
3607		layerContents = [
3608			("custom name", "glyphs"),
3609			("layer 1", "glyphs.layer 1"),
3610			("layer 2", "glyphs.layer 2")
3611		]
3612		expected = layerContents[0][0]
3613		with open(path, "wb") as f:
3614			plistlib.dump(layerContents, f)
3615		reader = UFOReader(self.ufoPath, validate=True)
3616		result = reader.getDefaultLayerName()
3617		self.assertEqual(expected, result)
3618		# get the glyph set
3619		self.makeUFO()
3620		path = os.path.join(self.ufoPath, "layercontents.plist")
3621		os.remove(path)
3622		layerContents = [
3623			("custom name", "glyphs"),
3624			("layer 1", "glyphs.layer 1"),
3625			("layer 2", "glyphs.layer 2")
3626		]
3627		with open(path, "wb") as f:
3628			plistlib.dump(layerContents, f)
3629		reader = UFOReader(self.ufoPath, validate=True)
3630		reader.getGlyphSet(expected)
3631
3632	# layer order
3633
3634	def testLayerOrder(self):
3635		self.makeUFO()
3636		path = os.path.join(self.ufoPath, "layercontents.plist")
3637		os.remove(path)
3638		layerContents = [
3639			("public.foregound", "glyphs"),
3640			("layer 1", "glyphs.layer 1"),
3641			("layer 2", "glyphs.layer 2")
3642		]
3643		expected = [name for (name, directory) in layerContents]
3644		with open(path, "wb") as f:
3645			plistlib.dump(layerContents, f)
3646		reader = UFOReader(self.ufoPath, validate=True)
3647		result = reader.getLayerNames()
3648		self.assertEqual(expected, result)
3649		self.makeUFO()
3650		path = os.path.join(self.ufoPath, "layercontents.plist")
3651		os.remove(path)
3652		layerContents = [
3653			("layer 1", "glyphs.layer 1"),
3654			("public.foregound", "glyphs"),
3655			("layer 2", "glyphs.layer 2")
3656		]
3657		expected = [name for (name, directory) in layerContents]
3658		with open(path, "wb") as f:
3659			plistlib.dump(layerContents, f)
3660		reader = UFOReader(self.ufoPath, validate=True)
3661		result = reader.getLayerNames()
3662		self.assertEqual(expected, result)
3663		self.makeUFO()
3664		path = os.path.join(self.ufoPath, "layercontents.plist")
3665		os.remove(path)
3666		layerContents = [
3667			("layer 2", "glyphs.layer 2"),
3668			("layer 1", "glyphs.layer 1"),
3669			("public.foregound", "glyphs")
3670		]
3671		expected = [name for (name, directory) in layerContents]
3672		with open(path, "wb") as f:
3673			plistlib.dump(layerContents, f)
3674		reader = UFOReader(self.ufoPath, validate=True)
3675		result = reader.getLayerNames()
3676		self.assertEqual(expected, result)
3677
3678
3679class UFO3WriteLayersTestCase(unittest.TestCase):
3680
3681	def setUp(self):
3682		self.tempDir = tempfile.mktemp()
3683		os.mkdir(self.tempDir)
3684		self.ufoPath = os.path.join(self.tempDir, "test.ufo")
3685
3686	def tearDown(self):
3687		shutil.rmtree(self.tempDir)
3688
3689	def makeUFO(self, metaInfo=None, layerContents=None):
3690		self.clearUFO()
3691		if not os.path.exists(self.ufoPath):
3692			os.mkdir(self.ufoPath)
3693		# metainfo.plist
3694		if metaInfo is None:
3695			metaInfo = dict(creator="test", formatVersion=3)
3696		path = os.path.join(self.ufoPath, "metainfo.plist")
3697		with open(path, "wb") as f:
3698			plistlib.dump(metaInfo, f)
3699		# layers
3700		if layerContents is None:
3701			layerContents = [
3702				("public.default", "glyphs"),
3703				("layer 1", "glyphs.layer 1"),
3704				("layer 2", "glyphs.layer 2"),
3705			]
3706		if layerContents:
3707			path = os.path.join(self.ufoPath, "layercontents.plist")
3708			with open(path, "wb") as f:
3709				plistlib.dump(layerContents, f)
3710		else:
3711			layerContents = [("", "glyphs")]
3712		for name, directory in layerContents:
3713			glyphsPath = os.path.join(self.ufoPath, directory)
3714			os.mkdir(glyphsPath)
3715			contents = dict(a="a.glif")
3716			path = os.path.join(glyphsPath, "contents.plist")
3717			with open(path, "wb") as f:
3718				plistlib.dump(contents, f)
3719			path = os.path.join(glyphsPath, "a.glif")
3720			with open(path, "w") as f:
3721				f.write(" ")
3722
3723	def clearUFO(self):
3724		if os.path.exists(self.ufoPath):
3725			shutil.rmtree(self.ufoPath)
3726
3727	# __init__: missing layer contents
3728
3729	def testMissingLayerContents(self):
3730		self.makeUFO()
3731		path = os.path.join(self.ufoPath, "layercontents.plist")
3732		os.remove(path)
3733		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3734
3735	# __init__: layer contents invalid format
3736
3737	def testInvalidLayerContentsFormat(self):
3738		# bogus
3739		self.makeUFO()
3740		path = os.path.join(self.ufoPath, "layercontents.plist")
3741		os.remove(path)
3742		with open(path, "w") as f:
3743			f.write("test")
3744		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3745		# dict
3746		self.makeUFO()
3747		path = os.path.join(self.ufoPath, "layercontents.plist")
3748		os.remove(path)
3749		layerContents = {
3750			"public.default" : "glyphs",
3751			"layer 1" : "glyphs.layer 1",
3752			"layer 2" : "glyphs.layer 2",
3753		}
3754		with open(path, "wb") as f:
3755			plistlib.dump(layerContents, f)
3756		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3757
3758	# __init__: layer contents invalid name format
3759
3760	def testInvalidLayerContentsNameFormat(self):
3761		self.makeUFO()
3762		path = os.path.join(self.ufoPath, "layercontents.plist")
3763		os.remove(path)
3764		layerContents = [
3765			(1, "glyphs"),
3766			("layer 1", "glyphs.layer 1"),
3767			("layer 2", "glyphs.layer 2")
3768		]
3769		with open(path, "wb") as f:
3770			plistlib.dump(layerContents, f)
3771		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3772
3773	# __init__: layer contents invalid directory format
3774
3775	def testInvalidLayerContentsDirectoryFormat(self):
3776		self.makeUFO()
3777		path = os.path.join(self.ufoPath, "layercontents.plist")
3778		os.remove(path)
3779		layerContents = [
3780			("public.foregound", "glyphs"),
3781			("layer 1", 1),
3782			("layer 2", "glyphs.layer 2")
3783		]
3784		with open(path, "wb") as f:
3785			plistlib.dump(layerContents, f)
3786		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3787
3788	# __init__: directory listed in contents not on disk
3789
3790	def testLayerContentsHasMissingDirectory(self):
3791		self.makeUFO()
3792		path = os.path.join(self.ufoPath, "layercontents.plist")
3793		os.remove(path)
3794		layerContents = [
3795			("public.foregound", "glyphs"),
3796			("layer 1", "glyphs.doesnotexist"),
3797			("layer 2", "glyphs.layer 2")
3798		]
3799		with open(path, "wb") as f:
3800			plistlib.dump(layerContents, f)
3801		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3802
3803	# __init__: no default layer on disk
3804
3805	def testMissingDefaultLayer(self):
3806		self.makeUFO()
3807		path = os.path.join(self.ufoPath, "layercontents.plist")
3808		os.remove(path)
3809		layerContents = [
3810			("layer 1", "glyphs.layer 1"),
3811			("layer 2", "glyphs.layer 2")
3812		]
3813		with open(path, "wb") as f:
3814			plistlib.dump(layerContents, f)
3815		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3816
3817	# __init__: duplicate layer name
3818
3819	def testDuplicateLayerName(self):
3820		self.makeUFO()
3821		path = os.path.join(self.ufoPath, "layercontents.plist")
3822		os.remove(path)
3823		layerContents = [
3824			("public.foregound", "glyphs"),
3825			("layer 1", "glyphs.layer 1"),
3826			("layer 1", "glyphs.layer 2")
3827		]
3828		with open(path, "wb") as f:
3829			plistlib.dump(layerContents, f)
3830		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3831
3832	# __init__: directory referenced by two layer names
3833
3834	def testDuplicateLayerDirectory(self):
3835		self.makeUFO()
3836		path = os.path.join(self.ufoPath, "layercontents.plist")
3837		os.remove(path)
3838		layerContents = [
3839			("public.foregound", "glyphs"),
3840			("layer 1", "glyphs.layer 1"),
3841			("layer 2", "glyphs.layer 1")
3842		]
3843		with open(path, "wb") as f:
3844			plistlib.dump(layerContents, f)
3845		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3846
3847	# __init__: default without a name
3848
3849	def testDefaultLayerNoName(self):
3850		# get the glyph set
3851		self.makeUFO()
3852		path = os.path.join(self.ufoPath, "layercontents.plist")
3853		os.remove(path)
3854		layerContents = [
3855			("public.foregound", "glyphs"),
3856			("layer 1", "glyphs.layer 1"),
3857			("layer 2", "glyphs.layer 2")
3858		]
3859		with open(path, "wb") as f:
3860			plistlib.dump(layerContents, f)
3861		writer = UFOWriter(self.ufoPath)
3862
3863	# __init__: default with a name
3864
3865	def testDefaultLayerName(self):
3866		self.makeUFO()
3867		path = os.path.join(self.ufoPath, "layercontents.plist")
3868		os.remove(path)
3869		layerContents = [
3870			("custom name", "glyphs"),
3871			("layer 1", "glyphs.layer 1"),
3872			("layer 2", "glyphs.layer 2")
3873		]
3874		with open(path, "wb") as f:
3875			plistlib.dump(layerContents, f)
3876		writer = UFOWriter(self.ufoPath)
3877
3878	# __init__: up convert 1 > 3
3879
3880	def testUpConvert1To3(self):
3881		self.makeUFO(
3882			metaInfo=dict(creator="test", formatVersion=1),
3883			layerContents=dict()
3884		)
3885		writer = UFOWriter(self.ufoPath)
3886		writer.writeLayerContents(["public.default"])
3887		path = os.path.join(self.ufoPath, "layercontents.plist")
3888		with open(path, "rb") as f:
3889			result = plistlib.load(f)
3890		expected = [["public.default", "glyphs"]]
3891		self.assertEqual(expected, result)
3892
3893	# __init__: up convert 2 > 3
3894
3895	def testUpConvert2To3(self):
3896		self.makeUFO(
3897			metaInfo=dict(creator="test", formatVersion=2),
3898			layerContents=dict()
3899		)
3900		writer = UFOWriter(self.ufoPath)
3901		writer.writeLayerContents(["public.default"])
3902		path = os.path.join(self.ufoPath, "layercontents.plist")
3903		with open(path, "rb") as f:
3904			result = plistlib.load(f)
3905		expected = [["public.default", "glyphs"]]
3906		self.assertEqual(expected, result)
3907
3908	# __init__: down convert 3 > 1
3909
3910	def testDownConvert3To1(self):
3911		self.makeUFO()
3912		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath, formatVersion=1)
3913
3914	# __init__: down convert 3 > 2
3915
3916	def testDownConvert3To2(self):
3917		self.makeUFO()
3918		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath, formatVersion=2)
3919
3920	# get glyph sets
3921
3922	def testGetGlyphSets(self):
3923		self.makeUFO()
3924		# hack contents.plist
3925		path = os.path.join(self.ufoPath, "glyphs.layer 1", "contents.plist")
3926		with open(path, "wb") as f:
3927			plistlib.dump(dict(b="a.glif"), f)
3928		path = os.path.join(self.ufoPath, "glyphs.layer 2", "contents.plist")
3929		with open(path, "wb") as f:
3930			plistlib.dump(dict(c="a.glif"), f)
3931		# now test
3932		writer = UFOWriter(self.ufoPath)
3933		# default
3934		expected = ["a"]
3935		result = list(writer.getGlyphSet().keys())
3936		self.assertEqual(expected, result)
3937		# layer 1
3938		expected = ["b"]
3939		result = list(writer.getGlyphSet("layer 1", defaultLayer=False).keys())
3940		self.assertEqual(expected, result)
3941		# layer 2
3942		expected = ["c"]
3943		result = list(writer.getGlyphSet("layer 2", defaultLayer=False).keys())
3944		self.assertEqual(expected, result)
3945
3946	# make a new font with two layers
3947
3948	def testNewFontOneLayer(self):
3949		self.clearUFO()
3950		writer = UFOWriter(self.ufoPath)
3951		writer.getGlyphSet()
3952		writer.writeLayerContents(["public.default"])
3953		# directory
3954		path = os.path.join(self.ufoPath, "glyphs")
3955		exists = os.path.exists(path)
3956		self.assertEqual(True, exists)
3957		# layer contents
3958		path = os.path.join(self.ufoPath, "layercontents.plist")
3959		with open(path, "rb") as f:
3960			result = plistlib.load(f)
3961		expected = [["public.default", "glyphs"]]
3962		self.assertEqual(expected, result)
3963
3964	def testNewFontThreeLayers(self):
3965		self.clearUFO()
3966		writer = UFOWriter(self.ufoPath)
3967		writer.getGlyphSet("layer 1", defaultLayer=False)
3968		writer.getGlyphSet()
3969		writer.getGlyphSet("layer 2", defaultLayer=False)
3970		writer.writeLayerContents(["layer 1", "public.default", "layer 2"])
3971		# directories
3972		path = os.path.join(self.ufoPath, "glyphs")
3973		exists = os.path.exists(path)
3974		self.assertEqual(True, exists)
3975		path = os.path.join(self.ufoPath, "glyphs.layer 1")
3976		exists = os.path.exists(path)
3977		self.assertEqual(True, exists)
3978		path = os.path.join(self.ufoPath, "glyphs.layer 2")
3979		exists = os.path.exists(path)
3980		self.assertEqual(True, exists)
3981		# layer contents
3982		path = os.path.join(self.ufoPath, "layercontents.plist")
3983		with open(path, "rb") as f:
3984			result = plistlib.load(f)
3985		expected = [["layer 1", "glyphs.layer 1"], ["public.default", "glyphs"], ["layer 2", "glyphs.layer 2"]]
3986		self.assertEqual(expected, result)
3987
3988	# add a layer to an existing font
3989
3990	def testAddLayerToExistingFont(self):
3991		self.makeUFO()
3992		writer = UFOWriter(self.ufoPath)
3993		writer.getGlyphSet("layer 3", defaultLayer=False)
3994		writer.writeLayerContents(["public.default", "layer 1", "layer 2", "layer 3"])
3995		# directories
3996		path = os.path.join(self.ufoPath, "glyphs")
3997		exists = os.path.exists(path)
3998		self.assertEqual(True, exists)
3999		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4000		exists = os.path.exists(path)
4001		self.assertEqual(True, exists)
4002		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4003		exists = os.path.exists(path)
4004		self.assertEqual(True, exists)
4005		path = os.path.join(self.ufoPath, "glyphs.layer 3")
4006		exists = os.path.exists(path)
4007		self.assertEqual(True, exists)
4008		# layer contents
4009		path = os.path.join(self.ufoPath, "layercontents.plist")
4010		with open(path, "rb") as f:
4011			result = plistlib.load(f)
4012		expected = [['public.default', 'glyphs'], ['layer 1', 'glyphs.layer 1'], ['layer 2', 'glyphs.layer 2'], ["layer 3", "glyphs.layer 3"]]
4013		self.assertEqual(expected, result)
4014
4015	# rename valid name
4016
4017	def testRenameLayer(self):
4018		self.makeUFO()
4019		writer = UFOWriter(self.ufoPath)
4020		writer.renameGlyphSet("layer 1", "layer 3")
4021		writer.writeLayerContents(["public.default", "layer 3", "layer 2"])
4022		# directories
4023		path = os.path.join(self.ufoPath, "glyphs")
4024		exists = os.path.exists(path)
4025		self.assertEqual(True, exists)
4026		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4027		exists = os.path.exists(path)
4028		self.assertEqual(False, exists)
4029		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4030		exists = os.path.exists(path)
4031		self.assertEqual(True, exists)
4032		path = os.path.join(self.ufoPath, "glyphs.layer 3")
4033		exists = os.path.exists(path)
4034		self.assertEqual(True, exists)
4035		# layer contents
4036		path = os.path.join(self.ufoPath, "layercontents.plist")
4037		with open(path, "rb") as f:
4038			result = plistlib.load(f)
4039		expected = [['public.default', 'glyphs'], ['layer 3', 'glyphs.layer 3'], ['layer 2', 'glyphs.layer 2']]
4040		self.assertEqual(expected, result)
4041
4042	def testRenameLayerDefault(self):
4043		self.makeUFO()
4044		writer = UFOWriter(self.ufoPath)
4045		writer.renameGlyphSet("public.default", "layer xxx")
4046		writer.renameGlyphSet("layer 1", "layer 1", defaultLayer=True)
4047		writer.writeLayerContents(["layer xxx", "layer 1", "layer 2"])
4048		path = os.path.join(self.ufoPath, "glyphs")
4049		exists = os.path.exists(path)
4050		self.assertEqual(True, exists)
4051		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4052		exists = os.path.exists(path)
4053		self.assertEqual(False, exists)
4054		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4055		exists = os.path.exists(path)
4056		self.assertEqual(True, exists)
4057		path = os.path.join(self.ufoPath, "glyphs.layer xxx")
4058		exists = os.path.exists(path)
4059		self.assertEqual(True, exists)
4060		# layer contents
4061		path = os.path.join(self.ufoPath, "layercontents.plist")
4062		with open(path, "rb") as f:
4063			result = plistlib.load(f)
4064		expected = [['layer xxx', 'glyphs.layer xxx'], ['layer 1', 'glyphs'], ['layer 2', 'glyphs.layer 2']]
4065		self.assertEqual(expected, result)
4066
4067	# rename duplicate name
4068
4069	def testRenameLayerDuplicateName(self):
4070		self.makeUFO()
4071		writer = UFOWriter(self.ufoPath)
4072		self.assertRaises(UFOLibError, writer.renameGlyphSet, "layer 1", "layer 2")
4073
4074	# rename unknown layer
4075
4076	def testRenameLayerUnknownName(self):
4077		self.makeUFO()
4078		writer = UFOWriter(self.ufoPath)
4079		self.assertRaises(UFOLibError, writer.renameGlyphSet, "does not exist", "layer 2")
4080
4081	# remove valid layer
4082
4083	def testRemoveLayer(self):
4084		self.makeUFO()
4085		writer = UFOWriter(self.ufoPath)
4086		writer.deleteGlyphSet("layer 1")
4087		writer.writeLayerContents(["public.default", "layer 2"])
4088		# directories
4089		path = os.path.join(self.ufoPath, "glyphs")
4090		exists = os.path.exists(path)
4091		self.assertEqual(True, exists)
4092		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4093		exists = os.path.exists(path)
4094		self.assertEqual(False, exists)
4095		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4096		exists = os.path.exists(path)
4097		self.assertEqual(True, exists)
4098		# layer contents
4099		path = os.path.join(self.ufoPath, "layercontents.plist")
4100		with open(path, "rb") as f:
4101			result = plistlib.load(f)
4102		expected = [["public.default", "glyphs"], ["layer 2", "glyphs.layer 2"]]
4103		self.assertEqual(expected, result)
4104
4105	# remove default layer
4106
4107	def testRemoveDefaultLayer(self):
4108		self.makeUFO()
4109		writer = UFOWriter(self.ufoPath)
4110		writer.deleteGlyphSet("public.default")
4111		# directories
4112		path = os.path.join(self.ufoPath, "glyphs")
4113		exists = os.path.exists(path)
4114		self.assertEqual(False, exists)
4115		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4116		exists = os.path.exists(path)
4117		self.assertEqual(True, exists)
4118		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4119		exists = os.path.exists(path)
4120		self.assertEqual(True, exists)
4121		# layer contents
4122		path = os.path.join(self.ufoPath, "layercontents.plist")
4123		with open(path, "rb") as f:
4124			result = plistlib.load(f)
4125		expected = [["layer 1", "glyphs.layer 1"], ["layer 2", "glyphs.layer 2"]]
4126		self.assertEqual(expected, result)
4127
4128	# remove unknown layer
4129
4130	def testRemoveDefaultLayer(self):
4131		self.makeUFO()
4132		writer = UFOWriter(self.ufoPath)
4133		self.assertRaises(UFOLibError, writer.deleteGlyphSet, "does not exist")
4134
4135	def testWriteAsciiLayerOrder(self):
4136		self.makeUFO(
4137			layerContents=[
4138				["public.default", "glyphs"],
4139				["layer 1", "glyphs.layer 1"],
4140				["layer 2", "glyphs.layer 2"],
4141			]
4142		)
4143		writer = UFOWriter(self.ufoPath)
4144		# if passed bytes string, it'll be decoded to ASCII unicode string
4145		writer.writeLayerContents(["public.default", "layer 2", b"layer 1"])
4146		path = os.path.join(self.ufoPath, "layercontents.plist")
4147		with open(path, "rb") as f:
4148			result = plistlib.load(f)
4149		expected = [
4150			["public.default", "glyphs"],
4151			["layer 2", "glyphs.layer 2"],
4152			["layer 1", "glyphs.layer 1"],
4153		]
4154		self.assertEqual(expected, result)
4155		for layerName, directory in result:
4156			assert isinstance(layerName, unicode)
4157
4158# -----
4159# /data
4160# -----
4161
4162
4163class UFO3ReadDataTestCase(unittest.TestCase):
4164
4165	def getFontPath(self):
4166		testdata = os.path.join(os.path.dirname(__file__), "testdata")
4167		return os.path.join(testdata, "UFO3-Read Data.ufo")
4168
4169	def testUFOReaderDataDirectoryListing(self):
4170		reader = UFOReader(self.getFontPath())
4171		found = reader.getDataDirectoryListing()
4172		expected = [
4173			'org.unifiedfontobject.directory/bar/lol.txt',
4174			'org.unifiedfontobject.directory/foo.txt',
4175			'org.unifiedfontobject.file.txt'
4176		]
4177		self.assertEqual(set(found), set(expected))
4178
4179	def testUFOReaderBytesFromPath(self):
4180		reader = UFOReader(self.getFontPath())
4181		found = reader.readBytesFromPath("data/org.unifiedfontobject.file.txt")
4182		expected = b"file.txt"
4183		self.assertEqual(found, expected)
4184		found = reader.readBytesFromPath("data/org.unifiedfontobject.directory/bar/lol.txt")
4185		expected = b"lol.txt"
4186		self.assertEqual(found, expected)
4187		found = reader.readBytesFromPath("data/org.unifiedfontobject.doesNotExist")
4188		expected = None
4189		self.assertEqual(found, expected)
4190
4191	def testUFOReaderReadFileFromPath(self):
4192		reader = UFOReader(self.getFontPath())
4193		fileObject = reader.getReadFileForPath("data/org.unifiedfontobject.file.txt")
4194		self.assertNotEqual(fileObject, None)
4195		hasRead = hasattr(fileObject, "read")
4196		self.assertEqual(hasRead, True)
4197		fileObject.close()
4198		fileObject = reader.getReadFileForPath("data/org.unifiedfontobject.doesNotExist")
4199		self.assertEqual(fileObject, None)
4200
4201
4202class UFO3WriteDataTestCase(unittest.TestCase):
4203
4204	def setUp(self):
4205		self.tempDir = tempfile.mktemp()
4206		os.mkdir(self.tempDir)
4207		self.dstDir = os.path.join(self.tempDir, "test.ufo")
4208
4209	def tearDown(self):
4210		shutil.rmtree(self.tempDir)
4211
4212	def tearDownUFO(self):
4213		if os.path.exists(self.dstDir):
4214			shutil.rmtree(self.dstDir)
4215
4216	def testUFOWriterWriteBytesToPath(self):
4217		# basic file
4218		path = "data/org.unifiedfontobject.writebytesbasicfile.txt"
4219		testBytes = b"test"
4220		writer = UFOWriter(self.dstDir, formatVersion=3)
4221		writer.writeBytesToPath(path, testBytes)
4222		path = os.path.join(self.dstDir, path)
4223		self.assertEqual(os.path.exists(path), True)
4224		with open(path, "rb") as f:
4225			written = f.read()
4226		self.assertEqual(testBytes, written)
4227		self.tearDownUFO()
4228		# basic file with unicode text
4229		path = "data/org.unifiedfontobject.writebytesbasicunicodefile.txt"
4230		text = b"t\xeb\xdft"
4231		writer = UFOWriter(self.dstDir, formatVersion=3)
4232		writer.writeBytesToPath(path, text)
4233		path = os.path.join(self.dstDir, path)
4234		self.assertEqual(os.path.exists(path), True)
4235		with open(path, "rb") as f:
4236			written = f.read()
4237		self.assertEqual(text, written)
4238		self.tearDownUFO()
4239		# basic directory
4240		path = "data/org.unifiedfontobject.writebytesdirectory/level1/level2/file.txt"
4241		testBytes = b"test"
4242		writer = UFOWriter(self.dstDir, formatVersion=3)
4243		writer.writeBytesToPath(path, testBytes)
4244		path = os.path.join(self.dstDir, path)
4245		self.assertEqual(os.path.exists(path), True)
4246		with open(path, "rb") as f:
4247			written = f.read()
4248		self.assertEqual(testBytes, written)
4249		self.tearDownUFO()
4250
4251	def testUFOWriterWriteFileToPath(self):
4252		# basic file
4253		path = "data/org.unifiedfontobject.getwritefile.txt"
4254		writer = UFOWriter(self.dstDir, formatVersion=3)
4255		fileObject = writer.getFileObjectForPath(path)
4256		self.assertNotEqual(fileObject, None)
4257		hasRead = hasattr(fileObject, "read")
4258		self.assertEqual(hasRead, True)
4259		fileObject.close()
4260		self.tearDownUFO()
4261
4262	def testUFOWriterRemoveFile(self):
4263		path1 = "data/org.unifiedfontobject.removefile/level1/level2/file1.txt"
4264		path2 = "data/org.unifiedfontobject.removefile/level1/level2/file2.txt"
4265		path3 = "data/org.unifiedfontobject.removefile/level1/file3.txt"
4266		writer = UFOWriter(self.dstDir, formatVersion=3)
4267		writer.writeBytesToPath(path1, b"test")
4268		writer.writeBytesToPath(path2, b"test")
4269		writer.writeBytesToPath(path3, b"test")
4270		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path1)), True)
4271		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path2)), True)
4272		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), True)
4273		writer.removeFileForPath(path1)
4274		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path1)), False)
4275		self.assertEqual(os.path.exists(os.path.dirname(os.path.join(self.dstDir, path1))), True)
4276		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path2)), True)
4277		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), True)
4278		writer.removeFileForPath(path2)
4279		self.assertEqual(os.path.exists(os.path.dirname(os.path.join(self.dstDir, path1))), False)
4280		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path2)), False)
4281		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), True)
4282		writer.removeFileForPath(path3)
4283		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), False)
4284		self.assertEqual(os.path.exists(os.path.dirname(os.path.join(self.dstDir, path2))), False)
4285		self.assertEqual(os.path.exists(os.path.join(self.dstDir, "data/org.unifiedfontobject.removefile")), False)
4286		self.assertRaises(UFOLibError, writer.removeFileForPath, path="data/org.unifiedfontobject.doesNotExist.txt")
4287		self.tearDownUFO()
4288
4289	def testUFOWriterCopy(self):
4290		sourceDir = self.dstDir.replace(".ufo", "") + "-copy source" + ".ufo"
4291		dataPath = "data/org.unifiedfontobject.copy/level1/level2/file1.txt"
4292		writer = UFOWriter(sourceDir, formatVersion=3)
4293		writer.writeBytesToPath(dataPath, b"test")
4294		# copy a file
4295		reader = UFOReader(sourceDir)
4296		writer = UFOWriter(self.dstDir, formatVersion=3)
4297		writer.copyFromReader(reader, dataPath, dataPath)
4298		path = os.path.join(self.dstDir, dataPath)
4299		self.assertEqual(os.path.exists(path), True)
4300		self.tearDownUFO()
4301		# copy a directory
4302		reader = UFOReader(sourceDir)
4303		writer = UFOWriter(self.dstDir, formatVersion=3)
4304		p = "data/org.unifiedfontobject.copy"
4305		writer.copyFromReader(reader, p, p)
4306		path = os.path.join(self.dstDir, dataPath)
4307		self.assertEqual(os.path.exists(path), True)
4308		self.tearDownUFO()
4309
4310# ---------------
4311# layerinfo.plist
4312# ---------------
4313
4314class TestLayerInfoObject(object):
4315
4316	color = guidelines = lib = None
4317
4318
4319class UFO3ReadLayerInfoTestCase(unittest.TestCase):
4320
4321	def setUp(self):
4322		self.tempDir = tempfile.mktemp()
4323		os.mkdir(self.tempDir)
4324		self.ufoPath = os.path.join(self.tempDir, "test.ufo")
4325
4326	def tearDown(self):
4327		shutil.rmtree(self.tempDir)
4328
4329	def makeUFO(self, formatVersion=3, layerInfo=None):
4330		self.clearUFO()
4331		if not os.path.exists(self.ufoPath):
4332			os.mkdir(self.ufoPath)
4333		# metainfo.plist
4334		metaInfo = dict(creator="test", formatVersion=formatVersion)
4335		path = os.path.join(self.ufoPath, "metainfo.plist")
4336		with open(path, "wb") as f:
4337			plistlib.dump(metaInfo, f)
4338		# layercontents.plist
4339		layerContents = [("public.default", "glyphs")]
4340		path = os.path.join(self.ufoPath, "layercontents.plist")
4341		with open(path, "wb") as f:
4342			plistlib.dump(layerContents, f)
4343		# glyphs
4344		glyphsPath = os.path.join(self.ufoPath, "glyphs")
4345		os.mkdir(glyphsPath)
4346		contents = dict(a="a.glif")
4347		path = os.path.join(glyphsPath, "contents.plist")
4348		with open(path, "wb") as f:
4349			plistlib.dump(contents, f)
4350		path = os.path.join(glyphsPath, "a.glif")
4351		with open(path, "w") as f:
4352			f.write(" ")
4353		# layerinfo.plist
4354		if layerInfo is None:
4355			layerInfo = dict(
4356				color="0,0,0,1",
4357				lib={"foo" : "bar"}
4358			)
4359		path = os.path.join(glyphsPath, "layerinfo.plist")
4360		with open(path, "wb") as f:
4361			plistlib.dump(layerInfo, f)
4362
4363	def clearUFO(self):
4364		if os.path.exists(self.ufoPath):
4365			shutil.rmtree(self.ufoPath)
4366
4367	def testValidLayerInfo(self):
4368		self.makeUFO()
4369		reader = UFOReader(self.ufoPath, validate=True)
4370		glyphSet = reader.getGlyphSet()
4371		info = TestLayerInfoObject()
4372		glyphSet.readLayerInfo(info)
4373		expectedColor = "0,0,0,1"
4374		self.assertEqual(expectedColor, info.color)
4375		expectedLib = {"foo": "bar"}
4376		self.assertEqual(expectedLib, info.lib)
4377
4378	def testMissingLayerInfo(self):
4379		self.makeUFO()
4380		path = os.path.join(self.ufoPath, "glyphs", "layerinfo.plist")
4381		os.remove(path)
4382		# read
4383		reader = UFOReader(self.ufoPath, validate=True)
4384		glyphSet = reader.getGlyphSet()
4385		info = TestLayerInfoObject()
4386		glyphSet.readLayerInfo(info)
4387		self.assertEqual(None, info.color)
4388		self.assertEqual(None, info.guidelines)
4389		self.assertEqual(None, info.lib)
4390
4391	def testBogusLayerInfo(self):
4392		self.makeUFO()
4393		path = os.path.join(self.ufoPath, "glyphs", "layerinfo.plist")
4394		os.remove(path)
4395		with open(path, "w") as f:
4396			f.write("test")
4397		# read
4398		reader = UFOReader(self.ufoPath, validate=True)
4399		glyphSet = reader.getGlyphSet()
4400		info = TestLayerInfoObject()
4401		self.assertRaises(UFOLibError, glyphSet.readLayerInfo, info)
4402
4403	def testInvalidFormatLayerInfo(self):
4404		self.makeUFO()
4405		path = os.path.join(self.ufoPath, "glyphs", "layerinfo.plist")
4406		info = [("color", "0,0,0,0")]
4407		with open(path, "wb") as f:
4408			plistlib.dump(info, f)
4409		# read
4410		reader = UFOReader(self.ufoPath, validate=True)
4411		glyphSet = reader.getGlyphSet()
4412		info = TestLayerInfoObject()
4413		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, info)
4414
4415	def testColor(self):
4416		## not a string
4417		info = {}
4418		info["color"] = 1
4419		self.makeUFO(layerInfo=info)
4420		reader = UFOReader(self.ufoPath, validate=True)
4421		glyphSet = reader.getGlyphSet()
4422		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4423		## not enough commas
4424		info = {}
4425		info["color"] = "1 0, 0, 0"
4426		self.makeUFO(layerInfo=info)
4427		reader = UFOReader(self.ufoPath, validate=True)
4428		glyphSet = reader.getGlyphSet()
4429		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4430		info = {}
4431		info["color"] = "1 0 0, 0"
4432		self.makeUFO(layerInfo=info)
4433		reader = UFOReader(self.ufoPath, validate=True)
4434		glyphSet = reader.getGlyphSet()
4435		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4436		info = {}
4437		info["color"] = "1 0 0 0"
4438		self.makeUFO(layerInfo=info)
4439		reader = UFOReader(self.ufoPath, validate=True)
4440		glyphSet = reader.getGlyphSet()
4441		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4442		## not enough parts
4443		info = {}
4444		info["color"] = ", 0, 0, 0"
4445		self.makeUFO(layerInfo=info)
4446		reader = UFOReader(self.ufoPath, validate=True)
4447		glyphSet = reader.getGlyphSet()
4448		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4449		info = {}
4450		info["color"] = "1, , 0, 0"
4451		self.makeUFO(layerInfo=info)
4452		reader = UFOReader(self.ufoPath, validate=True)
4453		glyphSet = reader.getGlyphSet()
4454		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4455		info = {}
4456		info["color"] = "1, 0, , 0"
4457		self.makeUFO(layerInfo=info)
4458		reader = UFOReader(self.ufoPath, validate=True)
4459		glyphSet = reader.getGlyphSet()
4460		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4461		info = {}
4462		info["color"] = "1, 0, 0, "
4463		self.makeUFO(layerInfo=info)
4464		reader = UFOReader(self.ufoPath, validate=True)
4465		glyphSet = reader.getGlyphSet()
4466		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4467		info = {}
4468		info["color"] = ", , , "
4469		self.makeUFO(layerInfo=info)
4470		reader = UFOReader(self.ufoPath, validate=True)
4471		glyphSet = reader.getGlyphSet()
4472		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4473		## not a number in all positions
4474		info = {}
4475		info["color"] = "r, 1, 1, 1"
4476		self.makeUFO(layerInfo=info)
4477		reader = UFOReader(self.ufoPath, validate=True)
4478		glyphSet = reader.getGlyphSet()
4479		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4480		info = {}
4481		info["color"] = "1, g, 1, 1"
4482		self.makeUFO(layerInfo=info)
4483		reader = UFOReader(self.ufoPath, validate=True)
4484		glyphSet = reader.getGlyphSet()
4485		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4486		info = {}
4487		info["color"] = "1, 1, b, 1"
4488		self.makeUFO(layerInfo=info)
4489		reader = UFOReader(self.ufoPath, validate=True)
4490		glyphSet = reader.getGlyphSet()
4491		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4492		info = {}
4493		info["color"] = "1, 1, 1, a"
4494		self.makeUFO(layerInfo=info)
4495		reader = UFOReader(self.ufoPath, validate=True)
4496		glyphSet = reader.getGlyphSet()
4497		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4498		## too many parts
4499		info = {}
4500		info["color"] = "1, 0, 0, 0, 0"
4501		self.makeUFO(layerInfo=info)
4502		reader = UFOReader(self.ufoPath, validate=True)
4503		glyphSet = reader.getGlyphSet()
4504		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4505		## < 0 in each position
4506		info = {}
4507		info["color"] = "-1, 0, 0, 0"
4508		self.makeUFO(layerInfo=info)
4509		reader = UFOReader(self.ufoPath, validate=True)
4510		glyphSet = reader.getGlyphSet()
4511		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4512		info = {}
4513		info["color"] = "0, -1, 0, 0"
4514		self.makeUFO(layerInfo=info)
4515		reader = UFOReader(self.ufoPath, validate=True)
4516		glyphSet = reader.getGlyphSet()
4517		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4518		info = {}
4519		info["color"] = "0, 0, -1, 0"
4520		self.makeUFO(layerInfo=info)
4521		reader = UFOReader(self.ufoPath, validate=True)
4522		glyphSet = reader.getGlyphSet()
4523		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4524		info = {}
4525		info["color"] = "0, 0, 0, -1"
4526		self.makeUFO(layerInfo=info)
4527		reader = UFOReader(self.ufoPath, validate=True)
4528		glyphSet = reader.getGlyphSet()
4529		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4530		## > 1 in each position
4531		info = {}
4532		info["color"] = "2, 0, 0, 0"
4533		self.makeUFO(layerInfo=info)
4534		reader = UFOReader(self.ufoPath, validate=True)
4535		glyphSet = reader.getGlyphSet()
4536		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4537		info = {}
4538		info["color"] = "0, 2, 0, 0"
4539		self.makeUFO(layerInfo=info)
4540		reader = UFOReader(self.ufoPath, validate=True)
4541		glyphSet = reader.getGlyphSet()
4542		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4543		info = {}
4544		info["color"] = "0, 0, 2, 0"
4545		self.makeUFO(layerInfo=info)
4546		reader = UFOReader(self.ufoPath, validate=True)
4547		glyphSet = reader.getGlyphSet()
4548		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4549		info = {}
4550		info["color"] = "0, 0, 0, 2"
4551		self.makeUFO(layerInfo=info)
4552		reader = UFOReader(self.ufoPath, validate=True)
4553		glyphSet = reader.getGlyphSet()
4554		self.assertRaises(GlifLibError, glyphSet.readLayerInfo, TestLayerInfoObject())
4555
4556
4557class UFO3WriteLayerInfoTestCase(unittest.TestCase):
4558
4559	def setUp(self):
4560		self.tempDir = tempfile.mktemp()
4561		os.mkdir(self.tempDir)
4562		self.ufoPath = os.path.join(self.tempDir, "test.ufo")
4563
4564	def tearDown(self):
4565		shutil.rmtree(self.tempDir)
4566
4567	def makeGlyphSet(self):
4568		self.clearUFO()
4569		writer = UFOWriter(self.ufoPath)
4570		return writer.getGlyphSet()
4571
4572	def clearUFO(self):
4573		if os.path.exists(self.ufoPath):
4574			shutil.rmtree(self.ufoPath)
4575
4576	def testValidWrite(self):
4577		expected = dict(
4578			color="0,0,0,1",
4579			lib={"foo" : "bar"}
4580		)
4581		info = TestLayerInfoObject()
4582		info.color = expected["color"]
4583		info.lib = expected["lib"]
4584		glyphSet = self.makeGlyphSet()
4585		glyphSet.writeLayerInfo(info)
4586		path = os.path.join(self.ufoPath, "glyphs", "layerinfo.plist")
4587		with open(path, "rb") as f:
4588			result = plistlib.load(f)
4589		self.assertEqual(expected, result)
4590
4591	def testColor(self):
4592		## not a string
4593		info = TestLayerInfoObject()
4594		info.color = 1
4595		glyphSet = self.makeGlyphSet()
4596		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4597		## not enough commas
4598		info = TestLayerInfoObject()
4599		info.color = "1 0, 0, 0"
4600		glyphSet = self.makeGlyphSet()
4601		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4602		info = TestLayerInfoObject()
4603		info.color = "1 0 0, 0"
4604		glyphSet = self.makeGlyphSet()
4605		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4606		info = TestLayerInfoObject()
4607		info.color = "1 0 0 0"
4608		glyphSet = self.makeGlyphSet()
4609		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4610		## not enough parts
4611		info = TestLayerInfoObject()
4612		info.color = ", 0, 0, 0"
4613		glyphSet = self.makeGlyphSet()
4614		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4615		info = TestLayerInfoObject()
4616		info.color = "1, , 0, 0"
4617		glyphSet = self.makeGlyphSet()
4618		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4619		info = TestLayerInfoObject()
4620		info.color = "1, 0, , 0"
4621		glyphSet = self.makeGlyphSet()
4622		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4623		info = TestLayerInfoObject()
4624		info.color = "1, 0, 0, "
4625		glyphSet = self.makeGlyphSet()
4626		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4627		info = TestLayerInfoObject()
4628		info.color = ", , , "
4629		glyphSet = self.makeGlyphSet()
4630		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4631		## not a number in all positions
4632		info = TestLayerInfoObject()
4633		info.color = "r, 1, 1, 1"
4634		glyphSet = self.makeGlyphSet()
4635		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4636		info = TestLayerInfoObject()
4637		info.color = "1, g, 1, 1"
4638		glyphSet = self.makeGlyphSet()
4639		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4640		info = TestLayerInfoObject()
4641		info.color = "1, 1, b, 1"
4642		glyphSet = self.makeGlyphSet()
4643		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4644		info = TestLayerInfoObject()
4645		info.color = "1, 1, 1, a"
4646		glyphSet = self.makeGlyphSet()
4647		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4648		## too many parts
4649		info = TestLayerInfoObject()
4650		info.color = "1, 0, 0, 0, 0"
4651		glyphSet = self.makeGlyphSet()
4652		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4653		## < 0 in each position
4654		info = TestLayerInfoObject()
4655		info.color = "-1, 0, 0, 0"
4656		glyphSet = self.makeGlyphSet()
4657		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4658		info = TestLayerInfoObject()
4659		info.color = "0, -1, 0, 0"
4660		glyphSet = self.makeGlyphSet()
4661		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4662		info = TestLayerInfoObject()
4663		info.color = "0, 0, -1, 0"
4664		glyphSet = self.makeGlyphSet()
4665		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4666		info = TestLayerInfoObject()
4667		info.color = "0, 0, 0, -1"
4668		glyphSet = self.makeGlyphSet()
4669		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4670		## > 1 in each position
4671		info = TestLayerInfoObject()
4672		info.color = "2, 0, 0, 0"
4673		glyphSet = self.makeGlyphSet()
4674		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4675		info = TestLayerInfoObject()
4676		info.color = "0, 2, 0, 0"
4677		glyphSet = self.makeGlyphSet()
4678		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4679		info = TestLayerInfoObject()
4680		info.color = "0, 0, 2, 0"
4681		glyphSet = self.makeGlyphSet()
4682		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4683		info = TestLayerInfoObject()
4684		info.color = "0, 0, 0, 2"
4685		glyphSet = self.makeGlyphSet()
4686		self.assertRaises(GlifLibError, glyphSet.writeLayerInfo, info)
4687