blob: 5f980d0a2d6de18a62d3e89ec188a732c66f4aae [file] [log] [blame]
Jack Jansen838e76a2003-02-25 12:58:58 +00001# Copyright (C) 2003 Python Software Foundation
2
3import unittest
4import plistlib
5import os
Just van Rossumfc93e172004-10-26 11:02:08 +00006import datetime
Benjamin Petersonee8712c2008-05-20 21:35:26 +00007from test import support
Jack Jansen838e76a2003-02-25 12:58:58 +00008
Just van Rossumfc93e172004-10-26 11:02:08 +00009
10# This test data was generated through Cocoa's NSDictionary class
Guido van Rossumcd869d82007-08-07 14:26:40 +000011TESTDATA = b"""<?xml version="1.0" encoding="UTF-8"?>
Ronald Oussorenae2a0ae2010-04-21 06:01:23 +000012<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" \
Just van Rossumfc93e172004-10-26 11:02:08 +000013"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
14<plist version="1.0">
15<dict>
16 <key>aDate</key>
17 <date>2004-10-26T10:33:33Z</date>
18 <key>aDict</key>
19 <dict>
20 <key>aFalseValue</key>
21 <false/>
22 <key>aTrueValue</key>
23 <true/>
24 <key>aUnicodeValue</key>
25 <string>M\xc3\xa4ssig, Ma\xc3\x9f</string>
26 <key>anotherString</key>
27 <string>&lt;hello &amp; 'hi' there!&gt;</string>
28 <key>deeperDict</key>
29 <dict>
30 <key>a</key>
31 <integer>17</integer>
32 <key>b</key>
33 <real>32.5</real>
34 <key>c</key>
35 <array>
36 <integer>1</integer>
37 <integer>2</integer>
38 <string>text</string>
39 </array>
40 </dict>
41 </dict>
42 <key>aFloat</key>
43 <real>0.5</real>
44 <key>aList</key>
45 <array>
46 <string>A</string>
47 <string>B</string>
48 <integer>12</integer>
49 <real>32.5</real>
50 <array>
51 <integer>1</integer>
52 <integer>2</integer>
53 <integer>3</integer>
54 </array>
55 </array>
56 <key>aString</key>
57 <string>Doodah</string>
58 <key>anInt</key>
59 <integer>728</integer>
60 <key>nestedData</key>
61 <array>
62 <data>
63 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5r
64 PgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5
65 IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBi
66 aW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3Rz
67 IG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQID
68 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAw==
69 </data>
70 </array>
71 <key>someData</key>
72 <data>
73 PGJpbmFyeSBndW5rPg==
74 </data>
75 <key>someMoreData</key>
76 <data>
77 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8
78 bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxs
79 b3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxv
80 dHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90
81 cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAw==
82 </data>
83 <key>\xc3\x85benraa</key>
84 <string>That was a unicode key.</string>
85</dict>
86</plist>
Neal Norwitzeaa16f92007-08-30 06:37:08 +000087""".replace(b" " * 8, b"\t") # Apple as well as plistlib.py output hard tabs
Just van Rossumfc93e172004-10-26 11:02:08 +000088
89
Jack Jansen838e76a2003-02-25 12:58:58 +000090class TestPlistlib(unittest.TestCase):
91
92 def tearDown(self):
93 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000094 os.unlink(support.TESTFN)
Jack Jansen838e76a2003-02-25 12:58:58 +000095 except:
96 pass
97
98 def _create(self):
Just van Rossumfc93e172004-10-26 11:02:08 +000099 pl = dict(
Jack Jansen838e76a2003-02-25 12:58:58 +0000100 aString="Doodah",
Just van Rossumfc93e172004-10-26 11:02:08 +0000101 aList=["A", "B", 12, 32.5, [1, 2, 3]],
102 aFloat = 0.5,
Jack Jansen838e76a2003-02-25 12:58:58 +0000103 anInt = 728,
Just van Rossumfc93e172004-10-26 11:02:08 +0000104 aDict=dict(
105 anotherString="<hello & 'hi' there!>",
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000106 aUnicodeValue='M\xe4ssig, Ma\xdf',
Jack Jansen838e76a2003-02-25 12:58:58 +0000107 aTrueValue=True,
108 aFalseValue=False,
Just van Rossumfc93e172004-10-26 11:02:08 +0000109 deeperDict=dict(a=17, b=32.5, c=[1, 2, "text"]),
Jack Jansen838e76a2003-02-25 12:58:58 +0000110 ),
Guido van Rossumcd869d82007-08-07 14:26:40 +0000111 someData = plistlib.Data(b"<binary gunk>"),
112 someMoreData = plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10),
113 nestedData = [plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10)],
Just van Rossumfc93e172004-10-26 11:02:08 +0000114 aDate = datetime.datetime(2004, 10, 26, 10, 33, 33),
Jack Jansen838e76a2003-02-25 12:58:58 +0000115 )
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000116 pl['\xc5benraa'] = "That was a unicode key."
Jack Jansen838e76a2003-02-25 12:58:58 +0000117 return pl
Tim Peters669454e2003-03-07 17:30:48 +0000118
Jack Jansen838e76a2003-02-25 12:58:58 +0000119 def test_create(self):
120 pl = self._create()
121 self.assertEqual(pl["aString"], "Doodah")
122 self.assertEqual(pl["aDict"]["aFalseValue"], False)
123
124 def test_io(self):
125 pl = self._create()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000126 plistlib.writePlist(pl, support.TESTFN)
127 pl2 = plistlib.readPlist(support.TESTFN)
Tim Peters669454e2003-03-07 17:30:48 +0000128 self.assertEqual(dict(pl), dict(pl2))
Jack Jansen838e76a2003-02-25 12:58:58 +0000129
Guido van Rossumcd869d82007-08-07 14:26:40 +0000130 def test_bytes(self):
Just van Rossumfc93e172004-10-26 11:02:08 +0000131 pl = self._create()
Guido van Rossumcd869d82007-08-07 14:26:40 +0000132 data = plistlib.writePlistToBytes(pl)
133 pl2 = plistlib.readPlistFromBytes(data)
Just van Rossumfc93e172004-10-26 11:02:08 +0000134 self.assertEqual(dict(pl), dict(pl2))
Guido van Rossumcd869d82007-08-07 14:26:40 +0000135 data2 = plistlib.writePlistToBytes(pl2)
Just van Rossumfc93e172004-10-26 11:02:08 +0000136 self.assertEqual(data, data2)
137
138 def test_appleformatting(self):
Guido van Rossumcd869d82007-08-07 14:26:40 +0000139 pl = plistlib.readPlistFromBytes(TESTDATA)
140 data = plistlib.writePlistToBytes(pl)
Just van Rossumfc93e172004-10-26 11:02:08 +0000141 self.assertEqual(data, TESTDATA,
142 "generated data was not identical to Apple's output")
143
144 def test_appleformattingfromliteral(self):
145 pl = self._create()
Guido van Rossumcd869d82007-08-07 14:26:40 +0000146 pl2 = plistlib.readPlistFromBytes(TESTDATA)
Just van Rossumfc93e172004-10-26 11:02:08 +0000147 self.assertEqual(dict(pl), dict(pl2),
148 "generated data was not identical to Apple's output")
149
Guido van Rossumcd869d82007-08-07 14:26:40 +0000150 def test_bytesio(self):
151 from io import BytesIO
152 b = BytesIO()
Just van Rossumbcc58e82003-07-01 20:22:30 +0000153 pl = self._create()
Guido van Rossumcd869d82007-08-07 14:26:40 +0000154 plistlib.writePlist(pl, b)
155 pl2 = plistlib.readPlist(BytesIO(b.getvalue()))
Just van Rossumbcc58e82003-07-01 20:22:30 +0000156 self.assertEqual(dict(pl), dict(pl2))
157
Just van Rossum48ecacc2004-11-12 08:34:32 +0000158 def test_controlcharacters(self):
Just van Rossum2dae7642004-11-12 09:36:12 +0000159 for i in range(128):
160 c = chr(i)
161 testString = "string containing %s" % c
162 if i >= 32 or c in "\r\n\t":
163 # \r, \n and \t are the only legal control chars in XML
Guido van Rossumcd869d82007-08-07 14:26:40 +0000164 plistlib.writePlistToBytes(testString)
Just van Rossum2dae7642004-11-12 09:36:12 +0000165 else:
166 self.assertRaises(ValueError,
Guido van Rossumcd869d82007-08-07 14:26:40 +0000167 plistlib.writePlistToBytes,
Just van Rossum2dae7642004-11-12 09:36:12 +0000168 testString)
Just van Rossum48ecacc2004-11-12 08:34:32 +0000169
170 def test_nondictroot(self):
171 test1 = "abc"
172 test2 = [1, 2, 3, "abc"]
Guido van Rossumcd869d82007-08-07 14:26:40 +0000173 result1 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test1))
174 result2 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test2))
Just van Rossum48ecacc2004-11-12 08:34:32 +0000175 self.assertEqual(test1, result1)
176 self.assertEqual(test2, result2)
Jack Jansen838e76a2003-02-25 12:58:58 +0000177
Ned Deilyb8e59f72011-05-28 02:19:19 -0700178 def test_invalidarray(self):
179 for i in ["<key>key inside an array</key>",
180 "<key>key inside an array2</key><real>3</real>",
181 "<true/><key>key inside an array3</key>"]:
182 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
183 ("<plist><array>%s</array></plist>"%i).encode())
184
185 def test_invaliddict(self):
186 for i in ["<key><true/>k</key><string>compound key</string>",
187 "<key>single key</key>",
188 "<string>missing key</string>",
189 "<key>k1</key><string>v1</string><real>5.3</real>"
190 "<key>k1</key><key>k2</key><string>double key</string>"]:
191 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
192 ("<plist><dict>%s</dict></plist>"%i).encode())
193 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
194 ("<plist><array><dict>%s</dict></array></plist>"%i).encode())
195
196 def test_invalidinteger(self):
197 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
198 b"<plist><integer>not integer</integer></plist>")
199
200 def test_invalidreal(self):
201 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
202 b"<plist><integer>not real</integer></plist>")
203
Jack Jansen838e76a2003-02-25 12:58:58 +0000204
205def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000206 support.run_unittest(TestPlistlib)
Jack Jansen838e76a2003-02-25 12:58:58 +0000207
208
209if __name__ == '__main__':
210 test_main()