1from io import BytesIO
2import os
3import unittest
4from fontTools.misc.textTools import bytesjoin, tobytes
5from fontTools.misc.xmlWriter import XMLWriter
6
7HEADER = b'<?xml version="1.0" encoding="UTF-8"?>\n'
8
9class TestXMLWriter(unittest.TestCase):
10
11	def test_comment_escaped(self):
12		writer = XMLWriter(BytesIO())
13		writer.comment("This&that are <comments>")
14		self.assertEqual(HEADER + b"<!-- This&amp;that are &lt;comments&gt; -->", writer.file.getvalue())
15
16	def test_comment_multiline(self):
17		writer = XMLWriter(BytesIO())
18		writer.comment("Hello world\nHow are you?")
19		self.assertEqual(HEADER + b"<!-- Hello world\n     How are you? -->",
20				 writer.file.getvalue())
21
22	def test_encoding_default(self):
23		writer = XMLWriter(BytesIO())
24		self.assertEqual(b'<?xml version="1.0" encoding="UTF-8"?>\n',
25				 writer.file.getvalue())
26
27	def test_encoding_utf8(self):
28		# https://github.com/fonttools/fonttools/issues/246
29		writer = XMLWriter(BytesIO(), encoding="utf8")
30		self.assertEqual(b'<?xml version="1.0" encoding="UTF-8"?>\n',
31				 writer.file.getvalue())
32
33	def test_encoding_UTF_8(self):
34		# https://github.com/fonttools/fonttools/issues/246
35		writer = XMLWriter(BytesIO(), encoding="UTF-8")
36		self.assertEqual(b'<?xml version="1.0" encoding="UTF-8"?>\n',
37				 writer.file.getvalue())
38
39	def test_encoding_UTF8(self):
40		# https://github.com/fonttools/fonttools/issues/246
41		writer = XMLWriter(BytesIO(), encoding="UTF8")
42		self.assertEqual(b'<?xml version="1.0" encoding="UTF-8"?>\n',
43				 writer.file.getvalue())
44
45	def test_encoding_other(self):
46		self.assertRaises(Exception, XMLWriter, BytesIO(),
47				  encoding="iso-8859-1")
48
49	def test_write(self):
50		writer = XMLWriter(BytesIO())
51		writer.write("foo&bar")
52		self.assertEqual(HEADER + b"foo&amp;bar", writer.file.getvalue())
53
54	def test_indent_dedent(self):
55		writer = XMLWriter(BytesIO())
56		writer.write("foo")
57		writer.newline()
58		writer.indent()
59		writer.write("bar")
60		writer.newline()
61		writer.dedent()
62		writer.write("baz")
63		self.assertEqual(HEADER + bytesjoin(["foo", "  bar", "baz"], "\n"),
64				 writer.file.getvalue())
65
66	def test_writecdata(self):
67		writer = XMLWriter(BytesIO())
68		writer.writecdata("foo&bar")
69		self.assertEqual(HEADER + b"<![CDATA[foo&bar]]>", writer.file.getvalue())
70
71	def test_simpletag(self):
72		writer = XMLWriter(BytesIO())
73		writer.simpletag("tag", a="1", b="2")
74		self.assertEqual(HEADER + b'<tag a="1" b="2"/>', writer.file.getvalue())
75
76	def test_begintag_endtag(self):
77		writer = XMLWriter(BytesIO())
78		writer.begintag("tag", attr="value")
79		writer.write("content")
80		writer.endtag("tag")
81		self.assertEqual(HEADER + b'<tag attr="value">content</tag>', writer.file.getvalue())
82
83	def test_dumphex(self):
84		writer = XMLWriter(BytesIO())
85		writer.dumphex("Type is a beautiful group of letters, not a group of beautiful letters.")
86		self.assertEqual(HEADER + bytesjoin([
87		    "54797065 20697320 61206265 61757469",
88		    "66756c20 67726f75 70206f66 206c6574",
89		    "74657273 2c206e6f 74206120 67726f75",
90		    "70206f66 20626561 75746966 756c206c",
91		    "65747465 72732e  ", ""], joiner="\n"), writer.file.getvalue())
92
93	def test_stringifyattrs(self):
94		writer = XMLWriter(BytesIO())
95		expected = ' attr="0"'
96		self.assertEqual(expected, writer.stringifyattrs(attr=0))
97		self.assertEqual(expected, writer.stringifyattrs(attr=b'0'))
98		self.assertEqual(expected, writer.stringifyattrs(attr='0'))
99		self.assertEqual(expected, writer.stringifyattrs(attr=u'0'))
100
101	def test_carriage_return_escaped(self):
102		writer = XMLWriter(BytesIO())
103		writer.write("two lines\r\nseparated by Windows line endings")
104		self.assertEqual(
105			HEADER + b'two lines&#13;\nseparated by Windows line endings',
106			writer.file.getvalue())
107
108	def test_newlinestr(self):
109		header = b'<?xml version="1.0" encoding="UTF-8"?>'
110
111		for nls in (None, '\n', '\r\n', '\r', ''):
112			writer = XMLWriter(BytesIO(), newlinestr=nls)
113			writer.write("hello")
114			writer.newline()
115			writer.write("world")
116			writer.newline()
117
118			linesep = tobytes(os.linesep) if nls is None else tobytes(nls)
119
120			self.assertEqual(
121				header + linesep + b"hello" + linesep + b"world" + linesep,
122				writer.file.getvalue())
123
124
125if __name__ == '__main__':
126	import sys
127	sys.exit(unittest.main())
128