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 ufoLib import UFOReader, UFOWriter, UFOLibError
10from ufoLib.glifLib import GlifLibError
11from ufoLib import plistlib
12from ufoLib.test.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(TestInfoObject())
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(TestInfoObject())
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(TestInfoObject())
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(TestInfoObject())
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(TestInfoObject())
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(TestInfoObject())
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(TestInfoObject())
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(TestInfoObject())
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(TestInfoObject())
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.writeInfo(TestInfoObject())
2860		self.tearDownUFO()
2861		## url not a string
2862		infoObject = self.makeInfoObject()
2863		infoObject.woffMetadataDescription = dict(text=[dict(text="foo")], url=1)
2864		writer = UFOWriter(self.dstDir, formatVersion=3)
2865		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2866		self.tearDownUFO()
2867		## no text
2868		infoObject = self.makeInfoObject()
2869		infoObject.woffMetadataDescription = dict(url="foo")
2870		writer = UFOWriter(self.dstDir, formatVersion=3)
2871		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2872		self.tearDownUFO()
2873		## text not a list
2874		infoObject = self.makeInfoObject()
2875		infoObject.woffMetadataDescription = dict(text="abc")
2876		writer = UFOWriter(self.dstDir, formatVersion=3)
2877		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2878		self.tearDownUFO()
2879		## text item not a dict
2880		infoObject = self.makeInfoObject()
2881		infoObject.woffMetadataDescription = dict(text=["abc"])
2882		writer = UFOWriter(self.dstDir, formatVersion=3)
2883		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2884		self.tearDownUFO()
2885		## text item unknown key
2886		infoObject = self.makeInfoObject()
2887		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", notTheRightKey=1)])
2888		writer = UFOWriter(self.dstDir, formatVersion=3)
2889		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2890		self.tearDownUFO()
2891		## text item missing text
2892		infoObject = self.makeInfoObject()
2893		infoObject.woffMetadataDescription = dict(text=[dict(language="foo")])
2894		writer = UFOWriter(self.dstDir, formatVersion=3)
2895		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2896		self.tearDownUFO()
2897		## text not a string
2898		infoObject = self.makeInfoObject()
2899		infoObject.woffMetadataDescription = dict(text=[dict(text=1)])
2900		writer = UFOWriter(self.dstDir, formatVersion=3)
2901		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2902		self.tearDownUFO()
2903		## url not a string
2904		infoObject = self.makeInfoObject()
2905		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", url=1)])
2906		writer = UFOWriter(self.dstDir, formatVersion=3)
2907		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2908		self.tearDownUFO()
2909		## language not a string
2910		infoObject = self.makeInfoObject()
2911		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", language=1)])
2912		writer = UFOWriter(self.dstDir, formatVersion=3)
2913		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2914		self.tearDownUFO()
2915		## dir not ltr or rtl
2916		infoObject = self.makeInfoObject()
2917		infoObject.woffMetadataDescription = dict(text=[dict(text="foo", dir="utd")])
2918		writer = UFOWriter(self.dstDir, formatVersion=3)
2919		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2920		self.tearDownUFO()
2921		## class not a string
2922		infoObject = self.makeInfoObject()
2923		infoObject.woffMetadataDescription = dict(text=[{"text"  : "foo", "class" : 1}])
2924		writer = UFOWriter(self.dstDir, formatVersion=3)
2925		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2926		self.tearDownUFO()
2927		# woffMetadataLicense
2928		## no url
2929		infoObject = self.makeInfoObject()
2930		infoObject.woffMetadataLicense = dict(text=[dict(text="foo")])
2931		writer = UFOWriter(self.dstDir, formatVersion=3)
2932		writer.writeInfo(TestInfoObject())
2933		self.tearDownUFO()
2934		## url not a string
2935		infoObject = self.makeInfoObject()
2936		infoObject.woffMetadataLicense = dict(text=[dict(text="foo")], url=1)
2937		writer = UFOWriter(self.dstDir, formatVersion=3)
2938		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2939		self.tearDownUFO()
2940		## id not a string
2941		infoObject = self.makeInfoObject()
2942		infoObject.woffMetadataLicense = dict(text=[dict(text="foo")], id=1)
2943		writer = UFOWriter(self.dstDir, formatVersion=3)
2944		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2945		self.tearDownUFO()
2946		## no text
2947		infoObject = self.makeInfoObject()
2948		infoObject.woffMetadataLicense = dict(url="foo")
2949		writer = UFOWriter(self.dstDir, formatVersion=3)
2950		writer.writeInfo(TestInfoObject())
2951		self.tearDownUFO()
2952		## text not a list
2953		infoObject = self.makeInfoObject()
2954		infoObject.woffMetadataLicense = dict(text="abc")
2955		writer = UFOWriter(self.dstDir, formatVersion=3)
2956		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2957		self.tearDownUFO()
2958		## text item not a dict
2959		infoObject = self.makeInfoObject()
2960		infoObject.woffMetadataLicense = dict(text=["abc"])
2961		writer = UFOWriter(self.dstDir, formatVersion=3)
2962		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2963		self.tearDownUFO()
2964		## text item unknown key
2965		infoObject = self.makeInfoObject()
2966		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", notTheRightKey=1)])
2967		writer = UFOWriter(self.dstDir, formatVersion=3)
2968		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2969		self.tearDownUFO()
2970		## text item missing text
2971		infoObject = self.makeInfoObject()
2972		writer = UFOWriter(self.dstDir, formatVersion=3)
2973		infoObject.woffMetadataLicense = dict(text=[dict(language="foo")])
2974		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2975		self.tearDownUFO()
2976		## text not a string
2977		infoObject = self.makeInfoObject()
2978		writer = UFOWriter(self.dstDir, formatVersion=3)
2979		infoObject.woffMetadataLicense = dict(text=[dict(text=1)])
2980		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2981		self.tearDownUFO()
2982		## url not a string
2983		infoObject = self.makeInfoObject()
2984		writer = UFOWriter(self.dstDir, formatVersion=3)
2985		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", url=1)])
2986		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2987		self.tearDownUFO()
2988		## language not a string
2989		infoObject = self.makeInfoObject()
2990		writer = UFOWriter(self.dstDir, formatVersion=3)
2991		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", language=1)])
2992		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2993		self.tearDownUFO()
2994		## dir not ltr or rtl
2995		infoObject = self.makeInfoObject()
2996		writer = UFOWriter(self.dstDir, formatVersion=3)
2997		infoObject.woffMetadataLicense = dict(text=[dict(text="foo", dir="utd")])
2998		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
2999		self.tearDownUFO()
3000		## class not a string
3001		infoObject = self.makeInfoObject()
3002		writer = UFOWriter(self.dstDir, formatVersion=3)
3003		infoObject.woffMetadataLicense = dict(text=[{"text"  : "foo", "class" : 1}])
3004		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3005		self.tearDownUFO()
3006		# woffMetadataCopyright
3007		## unknown attribute
3008		infoObject = self.makeInfoObject()
3009		writer = UFOWriter(self.dstDir, formatVersion=3)
3010		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo")], notTheRightKey=1)
3011		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3012		self.tearDownUFO()
3013		## no text
3014		infoObject = self.makeInfoObject()
3015		writer = UFOWriter(self.dstDir, formatVersion=3)
3016		infoObject.woffMetadataCopyright = dict()
3017		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3018		self.tearDownUFO()
3019		## text not a list
3020		infoObject = self.makeInfoObject()
3021		writer = UFOWriter(self.dstDir, formatVersion=3)
3022		infoObject.woffMetadataCopyright = dict(text="abc")
3023		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3024		self.tearDownUFO()
3025		## text item not a dict
3026		infoObject = self.makeInfoObject()
3027		writer = UFOWriter(self.dstDir, formatVersion=3)
3028		infoObject.woffMetadataCopyright = dict(text=["abc"])
3029		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3030		self.tearDownUFO()
3031		## text item unknown key
3032		infoObject = self.makeInfoObject()
3033		writer = UFOWriter(self.dstDir, formatVersion=3)
3034		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", notTheRightKey=1)])
3035		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3036		self.tearDownUFO()
3037		## text item missing text
3038		infoObject = self.makeInfoObject()
3039		infoObject.woffMetadataCopyright = dict(text=[dict(language="foo")])
3040		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3041		self.tearDownUFO()
3042		## text not a string
3043		infoObject = self.makeInfoObject()
3044		writer = UFOWriter(self.dstDir, formatVersion=3)
3045		infoObject.woffMetadataCopyright = dict(text=[dict(text=1)])
3046		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3047		self.tearDownUFO()
3048		## url not a string
3049		infoObject = self.makeInfoObject()
3050		writer = UFOWriter(self.dstDir, formatVersion=3)
3051		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", url=1)])
3052		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3053		self.tearDownUFO()
3054		## language not a string
3055		infoObject = self.makeInfoObject()
3056		writer = UFOWriter(self.dstDir, formatVersion=3)
3057		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", language=1)])
3058		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3059		self.tearDownUFO()
3060		## dir not ltr or rtl
3061		infoObject = self.makeInfoObject()
3062		writer = UFOWriter(self.dstDir, formatVersion=3)
3063		infoObject.woffMetadataCopyright = dict(text=[dict(text="foo", dir="utd")])
3064		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3065		self.tearDownUFO()
3066		## class not a string
3067		infoObject = self.makeInfoObject()
3068		writer = UFOWriter(self.dstDir, formatVersion=3)
3069		infoObject.woffMetadataCopyright = dict(text=[{"text"  : "foo", "class" : 1}])
3070		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3071		self.tearDownUFO()
3072		# woffMetadataTrademark
3073		## unknown attribute
3074		infoObject = self.makeInfoObject()
3075		writer = UFOWriter(self.dstDir, formatVersion=3)
3076		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo")], notTheRightKey=1)
3077		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3078		self.tearDownUFO()
3079		## no text
3080		infoObject = self.makeInfoObject()
3081		writer = UFOWriter(self.dstDir, formatVersion=3)
3082		infoObject.woffMetadataTrademark = dict()
3083		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3084		self.tearDownUFO()
3085		## text not a list
3086		infoObject = self.makeInfoObject()
3087		writer = UFOWriter(self.dstDir, formatVersion=3)
3088		infoObject.woffMetadataTrademark = dict(text="abc")
3089		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3090		self.tearDownUFO()
3091		## text item not a dict
3092		infoObject = self.makeInfoObject()
3093		writer = UFOWriter(self.dstDir, formatVersion=3)
3094		infoObject.woffMetadataTrademark = dict(text=["abc"])
3095		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3096		self.tearDownUFO()
3097		## text item unknown key
3098		infoObject = self.makeInfoObject()
3099		writer = UFOWriter(self.dstDir, formatVersion=3)
3100		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", notTheRightKey=1)])
3101		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3102		self.tearDownUFO()
3103		## text item missing text
3104		infoObject = self.makeInfoObject()
3105		writer = UFOWriter(self.dstDir, formatVersion=3)
3106		infoObject.woffMetadataTrademark = dict(text=[dict(language="foo")])
3107		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3108		self.tearDownUFO()
3109		## text not a string
3110		infoObject = self.makeInfoObject()
3111		writer = UFOWriter(self.dstDir, formatVersion=3)
3112		infoObject.woffMetadataTrademark = dict(text=[dict(text=1)])
3113		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3114		self.tearDownUFO()
3115		## url not a string
3116		infoObject = self.makeInfoObject()
3117		writer = UFOWriter(self.dstDir, formatVersion=3)
3118		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", url=1)])
3119		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3120		self.tearDownUFO()
3121		## language not a string
3122		infoObject = self.makeInfoObject()
3123		writer = UFOWriter(self.dstDir, formatVersion=3)
3124		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", language=1)])
3125		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3126		self.tearDownUFO()
3127		## dir not ltr or rtl
3128		infoObject = self.makeInfoObject()
3129		writer = UFOWriter(self.dstDir, formatVersion=3)
3130		infoObject.woffMetadataTrademark = dict(text=[dict(text="foo", dir="utd")])
3131		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3132		self.tearDownUFO()
3133		## class not a string
3134		infoObject = self.makeInfoObject()
3135		writer = UFOWriter(self.dstDir, formatVersion=3)
3136		infoObject.woffMetadataTrademark = dict(text=[{"text"  : "foo", "class" : 1}])
3137		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3138		self.tearDownUFO()
3139		# woffMetadataLicensee
3140		## no name
3141		infoObject = self.makeInfoObject()
3142		writer = UFOWriter(self.dstDir, formatVersion=3)
3143		infoObject.woffMetadataLicensee = dict()
3144		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3145		self.tearDownUFO()
3146		## unknown attribute
3147		infoObject = self.makeInfoObject()
3148		writer = UFOWriter(self.dstDir, formatVersion=3)
3149		infoObject.woffMetadataLicensee = dict(name="foo", notTheRightKey=1)
3150		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3151		self.tearDownUFO()
3152		## name not a string
3153		infoObject = self.makeInfoObject()
3154		writer = UFOWriter(self.dstDir, formatVersion=3)
3155		infoObject.woffMetadataLicensee = dict(name=1)
3156		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3157		self.tearDownUFO()
3158		## dir options
3159		infoObject = self.makeInfoObject()
3160		infoObject.woffMetadataLicensee = dict(name="foo", dir="ltr")
3161		writer = UFOWriter(self.dstDir, formatVersion=3)
3162		writer.writeInfo(infoObject)
3163		self.tearDownUFO()
3164		infoObject = self.makeInfoObject()
3165		infoObject.woffMetadataLicensee = dict(name="foo", dir="rtl")
3166		writer = UFOWriter(self.dstDir, formatVersion=3)
3167		writer.writeInfo(infoObject)
3168		self.tearDownUFO()
3169		## dir not ltr or rtl
3170		infoObject = self.makeInfoObject()
3171		infoObject.woffMetadataLicensee = dict(name="foo", dir="utd")
3172		writer = UFOWriter(self.dstDir, formatVersion=3)
3173		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3174		self.tearDownUFO()
3175		## have class
3176		infoObject = self.makeInfoObject()
3177		infoObject.woffMetadataLicensee = {"name" : "foo", "class" : "hello"}
3178		writer = UFOWriter(self.dstDir, formatVersion=3)
3179		writer.writeInfo(infoObject)
3180		self.tearDownUFO()
3181		## class not a string
3182		infoObject = self.makeInfoObject()
3183		infoObject.woffMetadataLicensee = {"name" : "foo", "class" : 1}
3184		writer = UFOWriter(self.dstDir, formatVersion=3)
3185		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3186		self.tearDownUFO()
3187
3188	def testGuidelinesWrite(self):
3189		# x
3190		## not an int or float
3191		infoObject = self.makeInfoObject()
3192		infoObject.guidelines = [dict(x="1")]
3193		writer = UFOWriter(self.dstDir, formatVersion=3)
3194		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3195		self.tearDownUFO()
3196		# y
3197		## not an int or float
3198		infoObject = self.makeInfoObject()
3199		infoObject.guidelines = [dict(y="1")]
3200		writer = UFOWriter(self.dstDir, formatVersion=3)
3201		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3202		self.tearDownUFO()
3203		# angle
3204		## < 0
3205		infoObject = self.makeInfoObject()
3206		infoObject.guidelines = [dict(x=0, y=0, angle=-1)]
3207		writer = UFOWriter(self.dstDir, formatVersion=3)
3208		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3209		self.tearDownUFO()
3210		## > 360
3211		infoObject = self.makeInfoObject()
3212		infoObject.guidelines = [dict(x=0, y=0, angle=361)]
3213		writer = UFOWriter(self.dstDir, formatVersion=3)
3214		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3215		self.tearDownUFO()
3216		# name
3217		## not a string
3218		infoObject = self.makeInfoObject()
3219		infoObject.guidelines = [dict(x=0, name=1)]
3220		writer = UFOWriter(self.dstDir, formatVersion=3)
3221		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3222		self.tearDownUFO()
3223		# color
3224		## not a string
3225		infoObject = self.makeInfoObject()
3226		infoObject.guidelines = [dict(x=0, color=1)]
3227		writer = UFOWriter(self.dstDir, formatVersion=3)
3228		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3229		self.tearDownUFO()
3230		## not enough commas
3231		infoObject = self.makeInfoObject()
3232		infoObject.guidelines = [dict(x=0, color="1 0, 0, 0")]
3233		writer = UFOWriter(self.dstDir, formatVersion=3)
3234		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3235		self.tearDownUFO()
3236		infoObject = self.makeInfoObject()
3237		infoObject.guidelines = [dict(x=0, color="1 0 0, 0")]
3238		writer = UFOWriter(self.dstDir, formatVersion=3)
3239		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3240		self.tearDownUFO()
3241		infoObject = self.makeInfoObject()
3242		infoObject.guidelines = [dict(x=0, color="1 0 0 0")]
3243		writer = UFOWriter(self.dstDir, formatVersion=3)
3244		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3245		self.tearDownUFO()
3246		## not enough parts
3247		infoObject = self.makeInfoObject()
3248		infoObject.guidelines = [dict(x=0, color=", 0, 0, 0")]
3249		writer = UFOWriter(self.dstDir, formatVersion=3)
3250		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3251		self.tearDownUFO()
3252		infoObject = self.makeInfoObject()
3253		infoObject.guidelines = [dict(x=0, color="1, , 0, 0")]
3254		writer = UFOWriter(self.dstDir, formatVersion=3)
3255		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3256		self.tearDownUFO()
3257		infoObject = self.makeInfoObject()
3258		infoObject.guidelines = [dict(x=0, color="1, 0, , 0")]
3259		writer = UFOWriter(self.dstDir, formatVersion=3)
3260		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3261		self.tearDownUFO()
3262		infoObject = self.makeInfoObject()
3263		infoObject.guidelines = [dict(x=0, color="1, 0, 0, ")]
3264		writer = UFOWriter(self.dstDir, formatVersion=3)
3265		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3266		self.tearDownUFO()
3267		infoObject = self.makeInfoObject()
3268		infoObject.guidelines = [dict(x=0, color=", , , ")]
3269		writer = UFOWriter(self.dstDir, formatVersion=3)
3270		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3271		self.tearDownUFO()
3272		## not a number in all positions
3273		infoObject = self.makeInfoObject()
3274		infoObject.guidelines = [dict(x=0, color="r, 1, 1, 1")]
3275		writer = UFOWriter(self.dstDir, formatVersion=3)
3276		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3277		self.tearDownUFO()
3278		infoObject = self.makeInfoObject()
3279		infoObject.guidelines = [dict(x=0, color="1, g, 1, 1")]
3280		writer = UFOWriter(self.dstDir, formatVersion=3)
3281		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3282		self.tearDownUFO()
3283		infoObject = self.makeInfoObject()
3284		infoObject.guidelines = [dict(x=0, color="1, 1, b, 1")]
3285		writer = UFOWriter(self.dstDir, formatVersion=3)
3286		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3287		self.tearDownUFO()
3288		infoObject = self.makeInfoObject()
3289		infoObject.guidelines = [dict(x=0, color="1, 1, 1, a")]
3290		writer = UFOWriter(self.dstDir, formatVersion=3)
3291		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3292		self.tearDownUFO()
3293		## too many parts
3294		infoObject = self.makeInfoObject()
3295		infoObject.guidelines = [dict(x=0, color="1, 0, 0, 0, 0")]
3296		writer = UFOWriter(self.dstDir, formatVersion=3)
3297		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3298		self.tearDownUFO()
3299		## < 0 in each position
3300		infoObject = self.makeInfoObject()
3301		infoObject.guidelines = [dict(x=0, color="-1, 0, 0, 0")]
3302		writer = UFOWriter(self.dstDir, formatVersion=3)
3303		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3304		self.tearDownUFO()
3305		infoObject = self.makeInfoObject()
3306		infoObject.guidelines = [dict(x=0, color="0, -1, 0, 0")]
3307		writer = UFOWriter(self.dstDir, formatVersion=3)
3308		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3309		self.tearDownUFO()
3310		infoObject = self.makeInfoObject()
3311		infoObject.guidelines = [dict(x=0, color="0, 0, -1, 0")]
3312		writer = UFOWriter(self.dstDir, formatVersion=3)
3313		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3314		self.tearDownUFO()
3315		infoObject = self.makeInfoObject()
3316		infoObject.guidelines = [dict(x=0, color="0, 0, 0, -1")]
3317		writer = UFOWriter(self.dstDir, formatVersion=3)
3318		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3319		self.tearDownUFO()
3320		## > 1 in each position
3321		infoObject = self.makeInfoObject()
3322		infoObject.guidelines = [dict(x=0, color="2, 0, 0, 0")]
3323		writer = UFOWriter(self.dstDir, formatVersion=3)
3324		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3325		self.tearDownUFO()
3326		infoObject = self.makeInfoObject()
3327		infoObject.guidelines = [dict(x=0, color="0, 2, 0, 0")]
3328		writer = UFOWriter(self.dstDir, formatVersion=3)
3329		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3330		self.tearDownUFO()
3331		infoObject = self.makeInfoObject()
3332		infoObject.guidelines = [dict(x=0, color="0, 0, 2, 0")]
3333		writer = UFOWriter(self.dstDir, formatVersion=3)
3334		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3335		self.tearDownUFO()
3336		infoObject = self.makeInfoObject()
3337		infoObject.guidelines = [dict(x=0, color="0, 0, 0, 2")]
3338		writer = UFOWriter(self.dstDir, formatVersion=3)
3339		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3340		self.tearDownUFO()
3341		# identifier
3342		## duplicate
3343		infoObject = self.makeInfoObject()
3344		infoObject.guidelines = [dict(x=0, identifier="guide1"), dict(y=0, identifier="guide1")]
3345		writer = UFOWriter(self.dstDir, formatVersion=3)
3346		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3347		self.tearDownUFO()
3348		## below min
3349		infoObject = self.makeInfoObject()
3350		infoObject.guidelines = [dict(x=0, identifier="\0x1F")]
3351		writer = UFOWriter(self.dstDir, formatVersion=3)
3352		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3353		self.tearDownUFO()
3354		## above max
3355		infoObject = self.makeInfoObject()
3356		infoObject.guidelines = [dict(x=0, identifier="\0x7F")]
3357		writer = UFOWriter(self.dstDir, formatVersion=3)
3358		self.assertRaises(UFOLibError, writer.writeInfo, info=infoObject)
3359		self.tearDownUFO()
3360
3361
3362# ------
3363# layers
3364# ------
3365
3366class UFO3ReadLayersTestCase(unittest.TestCase):
3367
3368	def setUp(self):
3369		self.tempDir = tempfile.mktemp()
3370		os.mkdir(self.tempDir)
3371		self.ufoPath = os.path.join(self.tempDir, "test.ufo")
3372
3373	def tearDown(self):
3374		shutil.rmtree(self.tempDir)
3375
3376	def makeUFO(self, metaInfo=None, layerContents=None):
3377		self.clearUFO()
3378		if not os.path.exists(self.ufoPath):
3379			os.mkdir(self.ufoPath)
3380		# metainfo.plist
3381		if metaInfo is None:
3382			metaInfo = dict(creator="test", formatVersion=3)
3383		path = os.path.join(self.ufoPath, "metainfo.plist")
3384		with open(path, "wb") as f:
3385			plistlib.dump(metaInfo, f)
3386		# layers
3387		if layerContents is None:
3388			layerContents = [
3389				("public.default", "glyphs"),
3390				("layer 1", "glyphs.layer 1"),
3391				("layer 2", "glyphs.layer 2"),
3392			]
3393		if layerContents:
3394			path = os.path.join(self.ufoPath, "layercontents.plist")
3395			with open(path, "wb") as f:
3396				plistlib.dump(layerContents, f)
3397		else:
3398			layerContents = [("", "glyphs")]
3399		for name, directory in layerContents:
3400			glyphsPath = os.path.join(self.ufoPath, directory)
3401			os.mkdir(glyphsPath)
3402			contents = dict(a="a.glif")
3403			path = os.path.join(glyphsPath, "contents.plist")
3404			with open(path, "wb") as f:
3405				plistlib.dump(contents, f)
3406			path = os.path.join(glyphsPath, "a.glif")
3407			with open(path, "w") as f:
3408				f.write(" ")
3409
3410	def clearUFO(self):
3411		if os.path.exists(self.ufoPath):
3412			shutil.rmtree(self.ufoPath)
3413
3414	# valid
3415
3416	def testValidRead(self):
3417		# UFO 1
3418		self.makeUFO(
3419			metaInfo=dict(creator="test", formatVersion=1),
3420			layerContents=dict()
3421		)
3422		reader = UFOReader(self.ufoPath, validate=True)
3423		reader.getGlyphSet()
3424		# UFO 2
3425		self.makeUFO(
3426			metaInfo=dict(creator="test", formatVersion=2),
3427			layerContents=dict()
3428		)
3429		reader = UFOReader(self.ufoPath, validate=True)
3430		reader.getGlyphSet()
3431		# UFO 3
3432		self.makeUFO()
3433		reader = UFOReader(self.ufoPath, validate=True)
3434		reader.getGlyphSet()
3435
3436	# missing layer contents
3437
3438	def testMissingLayerContents(self):
3439		self.makeUFO()
3440		path = os.path.join(self.ufoPath, "layercontents.plist")
3441		os.remove(path)
3442		reader = UFOReader(self.ufoPath, validate=True)
3443		self.assertRaises(UFOLibError, reader.getGlyphSet)
3444
3445	# layer contents invalid format
3446
3447	def testInvalidLayerContentsFormat(self):
3448		# bogus
3449		self.makeUFO()
3450		path = os.path.join(self.ufoPath, "layercontents.plist")
3451		os.remove(path)
3452		with open(path, "w") as f:
3453			f.write("test")
3454		reader = UFOReader(self.ufoPath, validate=True)
3455		self.assertRaises(UFOLibError, reader.getGlyphSet)
3456		# dict
3457		self.makeUFO()
3458		path = os.path.join(self.ufoPath, "layercontents.plist")
3459		os.remove(path)
3460		layerContents = {
3461			"public.default" : "glyphs",
3462			"layer 1" : "glyphs.layer 1",
3463			"layer 2" : "glyphs.layer 2",
3464		}
3465		with open(path, "wb") as f:
3466			plistlib.dump(layerContents, f)
3467		reader = UFOReader(self.ufoPath, validate=True)
3468		self.assertRaises(UFOLibError, reader.getGlyphSet)
3469
3470	# layer contents invalid name format
3471
3472	def testInvalidLayerContentsNameFormat(self):
3473		self.makeUFO()
3474		path = os.path.join(self.ufoPath, "layercontents.plist")
3475		os.remove(path)
3476		layerContents = [
3477			(1, "glyphs"),
3478			("layer 1", "glyphs.layer 1"),
3479			("layer 2", "glyphs.layer 2")
3480		]
3481		with open(path, "wb") as f:
3482			plistlib.dump(layerContents, f)
3483		reader = UFOReader(self.ufoPath, validate=True)
3484		self.assertRaises(UFOLibError, reader.getGlyphSet)
3485
3486	# layer contents invalid directory format
3487
3488	def testInvalidLayerContentsDirectoryFormat(self):
3489		self.makeUFO()
3490		path = os.path.join(self.ufoPath, "layercontents.plist")
3491		os.remove(path)
3492		layerContents = [
3493			("public.foregound", "glyphs"),
3494			("layer 1", 1),
3495			("layer 2", "glyphs.layer 2")
3496		]
3497		with open(path, "wb") as f:
3498			plistlib.dump(layerContents, f)
3499		reader = UFOReader(self.ufoPath, validate=True)
3500		self.assertRaises(UFOLibError, reader.getGlyphSet)
3501
3502	# directory listed in contents not on disk
3503
3504	def testLayerContentsHasMissingDirectory(self):
3505		self.makeUFO()
3506		path = os.path.join(self.ufoPath, "layercontents.plist")
3507		os.remove(path)
3508		layerContents = [
3509			("public.foregound", "glyphs"),
3510			("layer 1", "glyphs.doesnotexist"),
3511			("layer 2", "glyphs.layer 2")
3512		]
3513		with open(path, "wb") as f:
3514			plistlib.dump(layerContents, f)
3515		reader = UFOReader(self.ufoPath, validate=True)
3516		self.assertRaises(UFOLibError, reader.getGlyphSet)
3517
3518	# # directory on disk not listed in contents
3519	# XXX should this raise an error?
3520	#
3521	# def testLayerContentsHasMissingDirectory(self):
3522	# 	self.makeUFO()
3523	# 	path = os.path.join(self.ufoPath, "layercontents.plist")
3524	# 	os.remove(path)
3525	# 	layerContents = [
3526	# 		("public.foregound", "glyphs"),
3527	# 		("layer 1", "glyphs.layer 2")
3528	# 	]
3529	# 	with open(path, "wb") as f:
3530	# 		plistlib.dump(layerContents, f)
3531	# 	reader = UFOReader(self.ufoPath, validate=True)
3532	# 	with self.assertRaises(UFOLibError):
3533	# 		reader.getGlyphSet()
3534
3535	# no default layer on disk
3536
3537	def testMissingDefaultLayer(self):
3538		self.makeUFO()
3539		path = os.path.join(self.ufoPath, "layercontents.plist")
3540		os.remove(path)
3541		layerContents = [
3542			("layer 1", "glyphs.layer 1"),
3543			("layer 2", "glyphs.layer 2")
3544		]
3545		with open(path, "wb") as f:
3546			plistlib.dump(layerContents, f)
3547		reader = UFOReader(self.ufoPath, validate=True)
3548		self.assertRaises(UFOLibError, reader.getGlyphSet)
3549
3550	# duplicate layer name
3551
3552	def testDuplicateLayerName(self):
3553		self.makeUFO()
3554		path = os.path.join(self.ufoPath, "layercontents.plist")
3555		os.remove(path)
3556		layerContents = [
3557			("public.foregound", "glyphs"),
3558			("layer 1", "glyphs.layer 1"),
3559			("layer 1", "glyphs.layer 2")
3560		]
3561		with open(path, "wb") as f:
3562			plistlib.dump(layerContents, f)
3563		reader = UFOReader(self.ufoPath, validate=True)
3564		self.assertRaises(UFOLibError, reader.getGlyphSet)
3565
3566	# directory referenced by two layer names
3567
3568	def testDuplicateLayerDirectory(self):
3569		self.makeUFO()
3570		path = os.path.join(self.ufoPath, "layercontents.plist")
3571		os.remove(path)
3572		layerContents = [
3573			("public.foregound", "glyphs"),
3574			("layer 1", "glyphs.layer 1"),
3575			("layer 2", "glyphs.layer 1")
3576		]
3577		with open(path, "wb") as f:
3578			plistlib.dump(layerContents, f)
3579		reader = UFOReader(self.ufoPath, validate=True)
3580		self.assertRaises(UFOLibError, reader.getGlyphSet)
3581
3582	# default without a name
3583
3584	def testDefaultLayerNoName(self):
3585		# get the glyph set
3586		self.makeUFO()
3587		path = os.path.join(self.ufoPath, "layercontents.plist")
3588		os.remove(path)
3589		layerContents = [
3590			("public.foregound", "glyphs"),
3591			("layer 1", "glyphs.layer 1"),
3592			("layer 2", "glyphs.layer 2")
3593		]
3594		with open(path, "wb") as f:
3595			plistlib.dump(layerContents, f)
3596		reader = UFOReader(self.ufoPath, validate=True)
3597		reader.getGlyphSet()
3598
3599	# default with a name
3600
3601	def testDefaultLayerName(self):
3602		# get the name
3603		self.makeUFO()
3604		path = os.path.join(self.ufoPath, "layercontents.plist")
3605		os.remove(path)
3606		layerContents = [
3607			("custom name", "glyphs"),
3608			("layer 1", "glyphs.layer 1"),
3609			("layer 2", "glyphs.layer 2")
3610		]
3611		expected = layerContents[0][0]
3612		with open(path, "wb") as f:
3613			plistlib.dump(layerContents, f)
3614		reader = UFOReader(self.ufoPath, validate=True)
3615		result = reader.getDefaultLayerName()
3616		self.assertEqual(expected, result)
3617		# get the glyph set
3618		self.makeUFO()
3619		path = os.path.join(self.ufoPath, "layercontents.plist")
3620		os.remove(path)
3621		layerContents = [
3622			("custom name", "glyphs"),
3623			("layer 1", "glyphs.layer 1"),
3624			("layer 2", "glyphs.layer 2")
3625		]
3626		with open(path, "wb") as f:
3627			plistlib.dump(layerContents, f)
3628		reader = UFOReader(self.ufoPath, validate=True)
3629		reader.getGlyphSet(expected)
3630
3631	# layer order
3632
3633	def testLayerOrder(self):
3634		self.makeUFO()
3635		path = os.path.join(self.ufoPath, "layercontents.plist")
3636		os.remove(path)
3637		layerContents = [
3638			("public.foregound", "glyphs"),
3639			("layer 1", "glyphs.layer 1"),
3640			("layer 2", "glyphs.layer 2")
3641		]
3642		expected = [name for (name, directory) in layerContents]
3643		with open(path, "wb") as f:
3644			plistlib.dump(layerContents, f)
3645		reader = UFOReader(self.ufoPath, validate=True)
3646		result = reader.getLayerNames()
3647		self.assertEqual(expected, result)
3648		self.makeUFO()
3649		path = os.path.join(self.ufoPath, "layercontents.plist")
3650		os.remove(path)
3651		layerContents = [
3652			("layer 1", "glyphs.layer 1"),
3653			("public.foregound", "glyphs"),
3654			("layer 2", "glyphs.layer 2")
3655		]
3656		expected = [name for (name, directory) in layerContents]
3657		with open(path, "wb") as f:
3658			plistlib.dump(layerContents, f)
3659		reader = UFOReader(self.ufoPath, validate=True)
3660		result = reader.getLayerNames()
3661		self.assertEqual(expected, result)
3662		self.makeUFO()
3663		path = os.path.join(self.ufoPath, "layercontents.plist")
3664		os.remove(path)
3665		layerContents = [
3666			("layer 2", "glyphs.layer 2"),
3667			("layer 1", "glyphs.layer 1"),
3668			("public.foregound", "glyphs")
3669		]
3670		expected = [name for (name, directory) in layerContents]
3671		with open(path, "wb") as f:
3672			plistlib.dump(layerContents, f)
3673		reader = UFOReader(self.ufoPath, validate=True)
3674		result = reader.getLayerNames()
3675		self.assertEqual(expected, result)
3676
3677
3678class UFO3WriteLayersTestCase(unittest.TestCase):
3679
3680	def setUp(self):
3681		self.tempDir = tempfile.mktemp()
3682		os.mkdir(self.tempDir)
3683		self.ufoPath = os.path.join(self.tempDir, "test.ufo")
3684
3685	def tearDown(self):
3686		shutil.rmtree(self.tempDir)
3687
3688	def makeUFO(self, metaInfo=None, layerContents=None):
3689		self.clearUFO()
3690		if not os.path.exists(self.ufoPath):
3691			os.mkdir(self.ufoPath)
3692		# metainfo.plist
3693		if metaInfo is None:
3694			metaInfo = dict(creator="test", formatVersion=3)
3695		path = os.path.join(self.ufoPath, "metainfo.plist")
3696		with open(path, "wb") as f:
3697			plistlib.dump(metaInfo, f)
3698		# layers
3699		if layerContents is None:
3700			layerContents = [
3701				("public.default", "glyphs"),
3702				("layer 1", "glyphs.layer 1"),
3703				("layer 2", "glyphs.layer 2"),
3704			]
3705		if layerContents:
3706			path = os.path.join(self.ufoPath, "layercontents.plist")
3707			with open(path, "wb") as f:
3708				plistlib.dump(layerContents, f)
3709		else:
3710			layerContents = [("", "glyphs")]
3711		for name, directory in layerContents:
3712			glyphsPath = os.path.join(self.ufoPath, directory)
3713			os.mkdir(glyphsPath)
3714			contents = dict(a="a.glif")
3715			path = os.path.join(glyphsPath, "contents.plist")
3716			with open(path, "wb") as f:
3717				plistlib.dump(contents, f)
3718			path = os.path.join(glyphsPath, "a.glif")
3719			with open(path, "w") as f:
3720				f.write(" ")
3721
3722	def clearUFO(self):
3723		if os.path.exists(self.ufoPath):
3724			shutil.rmtree(self.ufoPath)
3725
3726	# __init__: missing layer contents
3727
3728	def testMissingLayerContents(self):
3729		self.makeUFO()
3730		path = os.path.join(self.ufoPath, "layercontents.plist")
3731		os.remove(path)
3732		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3733
3734	# __init__: layer contents invalid format
3735
3736	def testInvalidLayerContentsFormat(self):
3737		# bogus
3738		self.makeUFO()
3739		path = os.path.join(self.ufoPath, "layercontents.plist")
3740		os.remove(path)
3741		with open(path, "w") as f:
3742			f.write("test")
3743		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3744		# dict
3745		self.makeUFO()
3746		path = os.path.join(self.ufoPath, "layercontents.plist")
3747		os.remove(path)
3748		layerContents = {
3749			"public.default" : "glyphs",
3750			"layer 1" : "glyphs.layer 1",
3751			"layer 2" : "glyphs.layer 2",
3752		}
3753		with open(path, "wb") as f:
3754			plistlib.dump(layerContents, f)
3755		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3756
3757	# __init__: layer contents invalid name format
3758
3759	def testInvalidLayerContentsNameFormat(self):
3760		self.makeUFO()
3761		path = os.path.join(self.ufoPath, "layercontents.plist")
3762		os.remove(path)
3763		layerContents = [
3764			(1, "glyphs"),
3765			("layer 1", "glyphs.layer 1"),
3766			("layer 2", "glyphs.layer 2")
3767		]
3768		with open(path, "wb") as f:
3769			plistlib.dump(layerContents, f)
3770		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3771
3772	# __init__: layer contents invalid directory format
3773
3774	def testInvalidLayerContentsDirectoryFormat(self):
3775		self.makeUFO()
3776		path = os.path.join(self.ufoPath, "layercontents.plist")
3777		os.remove(path)
3778		layerContents = [
3779			("public.foregound", "glyphs"),
3780			("layer 1", 1),
3781			("layer 2", "glyphs.layer 2")
3782		]
3783		with open(path, "wb") as f:
3784			plistlib.dump(layerContents, f)
3785		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3786
3787	# __init__: directory listed in contents not on disk
3788
3789	def testLayerContentsHasMissingDirectory(self):
3790		self.makeUFO()
3791		path = os.path.join(self.ufoPath, "layercontents.plist")
3792		os.remove(path)
3793		layerContents = [
3794			("public.foregound", "glyphs"),
3795			("layer 1", "glyphs.doesnotexist"),
3796			("layer 2", "glyphs.layer 2")
3797		]
3798		with open(path, "wb") as f:
3799			plistlib.dump(layerContents, f)
3800		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3801
3802	# __init__: no default layer on disk
3803
3804	def testMissingDefaultLayer(self):
3805		self.makeUFO()
3806		path = os.path.join(self.ufoPath, "layercontents.plist")
3807		os.remove(path)
3808		layerContents = [
3809			("layer 1", "glyphs.layer 1"),
3810			("layer 2", "glyphs.layer 2")
3811		]
3812		with open(path, "wb") as f:
3813			plistlib.dump(layerContents, f)
3814		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3815
3816	# __init__: duplicate layer name
3817
3818	def testDuplicateLayerName(self):
3819		self.makeUFO()
3820		path = os.path.join(self.ufoPath, "layercontents.plist")
3821		os.remove(path)
3822		layerContents = [
3823			("public.foregound", "glyphs"),
3824			("layer 1", "glyphs.layer 1"),
3825			("layer 1", "glyphs.layer 2")
3826		]
3827		with open(path, "wb") as f:
3828			plistlib.dump(layerContents, f)
3829		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3830
3831	# __init__: directory referenced by two layer names
3832
3833	def testDuplicateLayerDirectory(self):
3834		self.makeUFO()
3835		path = os.path.join(self.ufoPath, "layercontents.plist")
3836		os.remove(path)
3837		layerContents = [
3838			("public.foregound", "glyphs"),
3839			("layer 1", "glyphs.layer 1"),
3840			("layer 2", "glyphs.layer 1")
3841		]
3842		with open(path, "wb") as f:
3843			plistlib.dump(layerContents, f)
3844		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath)
3845
3846	# __init__: default without a name
3847
3848	def testDefaultLayerNoName(self):
3849		# get the glyph set
3850		self.makeUFO()
3851		path = os.path.join(self.ufoPath, "layercontents.plist")
3852		os.remove(path)
3853		layerContents = [
3854			("public.foregound", "glyphs"),
3855			("layer 1", "glyphs.layer 1"),
3856			("layer 2", "glyphs.layer 2")
3857		]
3858		with open(path, "wb") as f:
3859			plistlib.dump(layerContents, f)
3860		writer = UFOWriter(self.ufoPath)
3861
3862	# __init__: default with a name
3863
3864	def testDefaultLayerName(self):
3865		self.makeUFO()
3866		path = os.path.join(self.ufoPath, "layercontents.plist")
3867		os.remove(path)
3868		layerContents = [
3869			("custom name", "glyphs"),
3870			("layer 1", "glyphs.layer 1"),
3871			("layer 2", "glyphs.layer 2")
3872		]
3873		with open(path, "wb") as f:
3874			plistlib.dump(layerContents, f)
3875		writer = UFOWriter(self.ufoPath)
3876
3877	# __init__: up convert 1 > 3
3878
3879	def testUpConvert1To3(self):
3880		self.makeUFO(
3881			metaInfo=dict(creator="test", formatVersion=1),
3882			layerContents=dict()
3883		)
3884		writer = UFOWriter(self.ufoPath)
3885		writer.writeLayerContents(["public.default"])
3886		path = os.path.join(self.ufoPath, "layercontents.plist")
3887		with open(path, "rb") as f:
3888			result = plistlib.load(f)
3889		expected = [["public.default", "glyphs"]]
3890		self.assertEqual(expected, result)
3891
3892	# __init__: up convert 2 > 3
3893
3894	def testUpConvert2To3(self):
3895		self.makeUFO(
3896			metaInfo=dict(creator="test", formatVersion=2),
3897			layerContents=dict()
3898		)
3899		writer = UFOWriter(self.ufoPath)
3900		writer.writeLayerContents(["public.default"])
3901		path = os.path.join(self.ufoPath, "layercontents.plist")
3902		with open(path, "rb") as f:
3903			result = plistlib.load(f)
3904		expected = [["public.default", "glyphs"]]
3905		self.assertEqual(expected, result)
3906
3907	# __init__: down convert 3 > 1
3908
3909	def testDownConvert3To1(self):
3910		self.makeUFO()
3911		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath, formatVersion=1)
3912
3913	# __init__: down convert 3 > 2
3914
3915	def testDownConvert3To2(self):
3916		self.makeUFO()
3917		self.assertRaises(UFOLibError, UFOWriter, self.ufoPath, formatVersion=2)
3918
3919	# get glyph sets
3920
3921	def testGetGlyphSets(self):
3922		self.makeUFO()
3923		# hack contents.plist
3924		path = os.path.join(self.ufoPath, "glyphs.layer 1", "contents.plist")
3925		with open(path, "wb") as f:
3926			plistlib.dump(dict(b="a.glif"), f)
3927		path = os.path.join(self.ufoPath, "glyphs.layer 2", "contents.plist")
3928		with open(path, "wb") as f:
3929			plistlib.dump(dict(c="a.glif"), f)
3930		# now test
3931		writer = UFOWriter(self.ufoPath)
3932		# default
3933		expected = ["a"]
3934		result = list(writer.getGlyphSet().keys())
3935		self.assertEqual(expected, result)
3936		# layer 1
3937		expected = ["b"]
3938		result = list(writer.getGlyphSet("layer 1", defaultLayer=False).keys())
3939		self.assertEqual(expected, result)
3940		# layer 2
3941		expected = ["c"]
3942		result = list(writer.getGlyphSet("layer 2", defaultLayer=False).keys())
3943		self.assertEqual(expected, result)
3944
3945	# make a new font with two layers
3946
3947	def testNewFontOneLayer(self):
3948		self.clearUFO()
3949		writer = UFOWriter(self.ufoPath)
3950		writer.getGlyphSet()
3951		writer.writeLayerContents(["public.default"])
3952		# directory
3953		path = os.path.join(self.ufoPath, "glyphs")
3954		exists = os.path.exists(path)
3955		self.assertEqual(True, exists)
3956		# layer contents
3957		path = os.path.join(self.ufoPath, "layercontents.plist")
3958		with open(path, "rb") as f:
3959			result = plistlib.load(f)
3960		expected = [["public.default", "glyphs"]]
3961		self.assertEqual(expected, result)
3962
3963	def testNewFontThreeLayers(self):
3964		self.clearUFO()
3965		writer = UFOWriter(self.ufoPath)
3966		writer.getGlyphSet("layer 1", defaultLayer=False)
3967		writer.getGlyphSet()
3968		writer.getGlyphSet("layer 2", defaultLayer=False)
3969		writer.writeLayerContents(["layer 1", "public.default", "layer 2"])
3970		# directories
3971		path = os.path.join(self.ufoPath, "glyphs")
3972		exists = os.path.exists(path)
3973		self.assertEqual(True, exists)
3974		path = os.path.join(self.ufoPath, "glyphs.layer 1")
3975		exists = os.path.exists(path)
3976		self.assertEqual(True, exists)
3977		path = os.path.join(self.ufoPath, "glyphs.layer 2")
3978		exists = os.path.exists(path)
3979		self.assertEqual(True, exists)
3980		# layer contents
3981		path = os.path.join(self.ufoPath, "layercontents.plist")
3982		with open(path, "rb") as f:
3983			result = plistlib.load(f)
3984		expected = [["layer 1", "glyphs.layer 1"], ["public.default", "glyphs"], ["layer 2", "glyphs.layer 2"]]
3985		self.assertEqual(expected, result)
3986
3987	# add a layer to an existing font
3988
3989	def testAddLayerToExistingFont(self):
3990		self.makeUFO()
3991		writer = UFOWriter(self.ufoPath)
3992		writer.getGlyphSet("layer 3", defaultLayer=False)
3993		writer.writeLayerContents(["public.default", "layer 1", "layer 2", "layer 3"])
3994		# directories
3995		path = os.path.join(self.ufoPath, "glyphs")
3996		exists = os.path.exists(path)
3997		self.assertEqual(True, exists)
3998		path = os.path.join(self.ufoPath, "glyphs.layer 1")
3999		exists = os.path.exists(path)
4000		self.assertEqual(True, exists)
4001		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4002		exists = os.path.exists(path)
4003		self.assertEqual(True, exists)
4004		path = os.path.join(self.ufoPath, "glyphs.layer 3")
4005		exists = os.path.exists(path)
4006		self.assertEqual(True, exists)
4007		# layer contents
4008		path = os.path.join(self.ufoPath, "layercontents.plist")
4009		with open(path, "rb") as f:
4010			result = plistlib.load(f)
4011		expected = [['public.default', 'glyphs'], ['layer 1', 'glyphs.layer 1'], ['layer 2', 'glyphs.layer 2'], ["layer 3", "glyphs.layer 3"]]
4012		self.assertEqual(expected, result)
4013
4014	# rename valid name
4015
4016	def testRenameLayer(self):
4017		self.makeUFO()
4018		writer = UFOWriter(self.ufoPath)
4019		writer.renameGlyphSet("layer 1", "layer 3")
4020		writer.writeLayerContents(["public.default", "layer 3", "layer 2"])
4021		# directories
4022		path = os.path.join(self.ufoPath, "glyphs")
4023		exists = os.path.exists(path)
4024		self.assertEqual(True, exists)
4025		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4026		exists = os.path.exists(path)
4027		self.assertEqual(False, exists)
4028		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4029		exists = os.path.exists(path)
4030		self.assertEqual(True, exists)
4031		path = os.path.join(self.ufoPath, "glyphs.layer 3")
4032		exists = os.path.exists(path)
4033		self.assertEqual(True, exists)
4034		# layer contents
4035		path = os.path.join(self.ufoPath, "layercontents.plist")
4036		with open(path, "rb") as f:
4037			result = plistlib.load(f)
4038		expected = [['public.default', 'glyphs'], ['layer 3', 'glyphs.layer 3'], ['layer 2', 'glyphs.layer 2']]
4039		self.assertEqual(expected, result)
4040
4041	def testRenameLayerDefault(self):
4042		self.makeUFO()
4043		writer = UFOWriter(self.ufoPath)
4044		writer.renameGlyphSet("public.default", "layer xxx")
4045		writer.renameGlyphSet("layer 1", "layer 1", defaultLayer=True)
4046		writer.writeLayerContents(["layer xxx", "layer 1", "layer 2"])
4047		path = os.path.join(self.ufoPath, "glyphs")
4048		exists = os.path.exists(path)
4049		self.assertEqual(True, exists)
4050		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4051		exists = os.path.exists(path)
4052		self.assertEqual(False, exists)
4053		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4054		exists = os.path.exists(path)
4055		self.assertEqual(True, exists)
4056		path = os.path.join(self.ufoPath, "glyphs.layer xxx")
4057		exists = os.path.exists(path)
4058		self.assertEqual(True, exists)
4059		# layer contents
4060		path = os.path.join(self.ufoPath, "layercontents.plist")
4061		with open(path, "rb") as f:
4062			result = plistlib.load(f)
4063		expected = [['layer xxx', 'glyphs.layer xxx'], ['layer 1', 'glyphs'], ['layer 2', 'glyphs.layer 2']]
4064		self.assertEqual(expected, result)
4065
4066	# rename duplicate name
4067
4068	def testRenameLayerDuplicateName(self):
4069		self.makeUFO()
4070		writer = UFOWriter(self.ufoPath)
4071		self.assertRaises(UFOLibError, writer.renameGlyphSet, "layer 1", "layer 2")
4072
4073	# rename unknown layer
4074
4075	def testRenameLayerUnknownName(self):
4076		self.makeUFO()
4077		writer = UFOWriter(self.ufoPath)
4078		self.assertRaises(UFOLibError, writer.renameGlyphSet, "does not exist", "layer 2")
4079
4080	# remove valid layer
4081
4082	def testRemoveLayer(self):
4083		self.makeUFO()
4084		writer = UFOWriter(self.ufoPath)
4085		writer.deleteGlyphSet("layer 1")
4086		writer.writeLayerContents(["public.default", "layer 2"])
4087		# directories
4088		path = os.path.join(self.ufoPath, "glyphs")
4089		exists = os.path.exists(path)
4090		self.assertEqual(True, exists)
4091		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4092		exists = os.path.exists(path)
4093		self.assertEqual(False, exists)
4094		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4095		exists = os.path.exists(path)
4096		self.assertEqual(True, exists)
4097		# layer contents
4098		path = os.path.join(self.ufoPath, "layercontents.plist")
4099		with open(path, "rb") as f:
4100			result = plistlib.load(f)
4101		expected = [["public.default", "glyphs"], ["layer 2", "glyphs.layer 2"]]
4102		self.assertEqual(expected, result)
4103
4104	# remove default layer
4105
4106	def testRemoveDefaultLayer(self):
4107		self.makeUFO()
4108		writer = UFOWriter(self.ufoPath)
4109		writer.deleteGlyphSet("public.default")
4110		# directories
4111		path = os.path.join(self.ufoPath, "glyphs")
4112		exists = os.path.exists(path)
4113		self.assertEqual(False, exists)
4114		path = os.path.join(self.ufoPath, "glyphs.layer 1")
4115		exists = os.path.exists(path)
4116		self.assertEqual(True, exists)
4117		path = os.path.join(self.ufoPath, "glyphs.layer 2")
4118		exists = os.path.exists(path)
4119		self.assertEqual(True, exists)
4120		# layer contents
4121		path = os.path.join(self.ufoPath, "layercontents.plist")
4122		with open(path, "rb") as f:
4123			result = plistlib.load(f)
4124		expected = [["layer 1", "glyphs.layer 1"], ["layer 2", "glyphs.layer 2"]]
4125		self.assertEqual(expected, result)
4126
4127	# remove unknown layer
4128
4129	def testRemoveDefaultLayer(self):
4130		self.makeUFO()
4131		writer = UFOWriter(self.ufoPath)
4132		self.assertRaises(UFOLibError, writer.deleteGlyphSet, "does not exist")
4133
4134	def testWriteAsciiLayerOrder(self):
4135		self.makeUFO(
4136			layerContents=[
4137				["public.default", "glyphs"],
4138				["layer 1", "glyphs.layer 1"],
4139				["layer 2", "glyphs.layer 2"],
4140			]
4141		)
4142		writer = UFOWriter(self.ufoPath)
4143		# if passed bytes string, it'll be decoded to ASCII unicode string
4144		writer.writeLayerContents(["public.default", "layer 2", b"layer 1"])
4145		path = os.path.join(self.ufoPath, "layercontents.plist")
4146		with open(path, "rb") as f:
4147			result = plistlib.load(f)
4148		expected = [
4149			["public.default", "glyphs"],
4150			["layer 2", "glyphs.layer 2"],
4151			["layer 1", "glyphs.layer 1"],
4152		]
4153		self.assertEqual(expected, result)
4154		for layerName, directory in result:
4155			assert isinstance(layerName, unicode)
4156
4157# -----
4158# /data
4159# -----
4160
4161
4162class UFO3ReadDataTestCase(unittest.TestCase):
4163
4164	def getFontPath(self):
4165		testdata = os.path.join(os.path.dirname(__file__), "testdata")
4166		return os.path.join(testdata, "UFO3-Read Data.ufo")
4167
4168	def testUFOReaderDataDirectoryListing(self):
4169		reader = UFOReader(self.getFontPath())
4170		found = reader.getDataDirectoryListing()
4171		expected = [
4172			'org.unifiedfontobject.directory%(s)sbar%(s)slol.txt' % {'s': os.sep},
4173			'org.unifiedfontobject.directory%(s)sfoo.txt' % {'s': os.sep},
4174			'org.unifiedfontobject.file.txt'
4175		]
4176		self.assertEqual(set(found), set(expected))
4177
4178	def testUFOReaderBytesFromPath(self):
4179		reader = UFOReader(self.getFontPath())
4180		found = reader.readBytesFromPath("data/org.unifiedfontobject.file.txt")
4181		expected = b"file.txt"
4182		self.assertEqual(found, expected)
4183		found = reader.readBytesFromPath("data/org.unifiedfontobject.directory/bar/lol.txt")
4184		expected = b"lol.txt"
4185		self.assertEqual(found, expected)
4186		found = reader.readBytesFromPath("data/org.unifiedfontobject.doesNotExist")
4187		expected = None
4188		self.assertEqual(found, expected)
4189
4190	def testUFOReaderReadFileFromPath(self):
4191		reader = UFOReader(self.getFontPath())
4192		fileObject = reader.getReadFileForPath("data/org.unifiedfontobject.file.txt")
4193		self.assertNotEqual(fileObject, None)
4194		hasRead = hasattr(fileObject, "read")
4195		self.assertEqual(hasRead, True)
4196		fileObject.close()
4197		fileObject = reader.getReadFileForPath("data/org.unifiedfontobject.doesNotExist")
4198		self.assertEqual(fileObject, None)
4199
4200
4201class UFO3WriteDataTestCase(unittest.TestCase):
4202
4203	def setUp(self):
4204		self.tempDir = tempfile.mktemp()
4205		os.mkdir(self.tempDir)
4206		self.dstDir = os.path.join(self.tempDir, "test.ufo")
4207
4208	def tearDown(self):
4209		shutil.rmtree(self.tempDir)
4210
4211	def tearDownUFO(self):
4212		if os.path.exists(self.dstDir):
4213			shutil.rmtree(self.dstDir)
4214
4215	def testUFOWriterWriteBytesToPath(self):
4216		# basic file
4217		path = "data/org.unifiedfontobject.writebytesbasicfile.txt"
4218		testBytes = b"test"
4219		writer = UFOWriter(self.dstDir, formatVersion=3)
4220		writer.writeBytesToPath(path, testBytes)
4221		path = os.path.join(self.dstDir, path)
4222		self.assertEqual(os.path.exists(path), True)
4223		with open(path, "rb") as f:
4224			written = f.read()
4225		self.assertEqual(testBytes, written)
4226		self.tearDownUFO()
4227		# basic file with unicode text
4228		path = "data/org.unifiedfontobject.writebytesbasicunicodefile.txt"
4229		text = b"t\xeb\xdft"
4230		writer = UFOWriter(self.dstDir, formatVersion=3)
4231		writer.writeBytesToPath(path, text)
4232		path = os.path.join(self.dstDir, path)
4233		self.assertEqual(os.path.exists(path), True)
4234		with open(path, "rb") as f:
4235			written = f.read()
4236		self.assertEqual(text, written)
4237		self.tearDownUFO()
4238		# basic directory
4239		path = "data/org.unifiedfontobject.writebytesdirectory/level1/level2/file.txt"
4240		testBytes = b"test"
4241		writer = UFOWriter(self.dstDir, formatVersion=3)
4242		writer.writeBytesToPath(path, testBytes)
4243		path = os.path.join(self.dstDir, path)
4244		self.assertEqual(os.path.exists(path), True)
4245		with open(path, "rb") as f:
4246			written = f.read()
4247		self.assertEqual(testBytes, written)
4248		self.tearDownUFO()
4249
4250	def testUFOWriterWriteFileToPath(self):
4251		# basic file
4252		path = "data/org.unifiedfontobject.getwritefile.txt"
4253		writer = UFOWriter(self.dstDir, formatVersion=3)
4254		fileObject = writer.getFileObjectForPath(path)
4255		self.assertNotEqual(fileObject, None)
4256		hasRead = hasattr(fileObject, "read")
4257		self.assertEqual(hasRead, True)
4258		fileObject.close()
4259		self.tearDownUFO()
4260
4261	def testUFOWriterRemoveFile(self):
4262		path1 = "data/org.unifiedfontobject.removefile/level1/level2/file1.txt"
4263		path2 = "data/org.unifiedfontobject.removefile/level1/level2/file2.txt"
4264		path3 = "data/org.unifiedfontobject.removefile/level1/file3.txt"
4265		writer = UFOWriter(self.dstDir, formatVersion=3)
4266		writer.writeBytesToPath(path1, b"test")
4267		writer.writeBytesToPath(path2, b"test")
4268		writer.writeBytesToPath(path3, b"test")
4269		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path1)), True)
4270		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path2)), True)
4271		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), True)
4272		writer.removeFileForPath(path1)
4273		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path1)), False)
4274		self.assertEqual(os.path.exists(os.path.dirname(os.path.join(self.dstDir, path1))), True)
4275		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path2)), True)
4276		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), True)
4277		writer.removeFileForPath(path2)
4278		self.assertEqual(os.path.exists(os.path.dirname(os.path.join(self.dstDir, path1))), False)
4279		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path2)), False)
4280		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), True)
4281		writer.removeFileForPath(path3)
4282		self.assertEqual(os.path.exists(os.path.join(self.dstDir, path3)), False)
4283		self.assertEqual(os.path.exists(os.path.dirname(os.path.join(self.dstDir, path2))), False)
4284		self.assertEqual(os.path.exists(os.path.join(self.dstDir, "data/org.unifiedfontobject.removefile")), False)
4285		self.assertRaises(UFOLibError, writer.removeFileForPath, path="metainfo.plist")
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(GlifLibError, 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
4688if __name__ == "__main__":
4689	from ufoLib.test.testSupport import runTests
4690	runTests()
4691