blob: a9e343eb155a1280c596d940c05de96e8a8931e3 [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>
Hynek Schlawack52209d32012-05-29 12:04:54 +020058 <key>anEmptyDict</key>
59 <dict/>
60 <key>anEmptyList</key>
61 <array/>
Just van Rossumfc93e172004-10-26 11:02:08 +000062 <key>anInt</key>
63 <integer>728</integer>
64 <key>nestedData</key>
65 <array>
66 <data>
67 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5r
68 PgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5
69 IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBi
70 aW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3Rz
71 IG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQID
72 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAw==
73 </data>
74 </array>
75 <key>someData</key>
76 <data>
77 PGJpbmFyeSBndW5rPg==
78 </data>
79 <key>someMoreData</key>
80 <data>
81 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8
82 bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxs
83 b3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxv
84 dHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90
85 cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAw==
86 </data>
87 <key>\xc3\x85benraa</key>
88 <string>That was a unicode key.</string>
89</dict>
90</plist>
Neal Norwitzeaa16f92007-08-30 06:37:08 +000091""".replace(b" " * 8, b"\t") # Apple as well as plistlib.py output hard tabs
Just van Rossumfc93e172004-10-26 11:02:08 +000092
93
Jack Jansen838e76a2003-02-25 12:58:58 +000094class TestPlistlib(unittest.TestCase):
95
96 def tearDown(self):
97 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000098 os.unlink(support.TESTFN)
Jack Jansen838e76a2003-02-25 12:58:58 +000099 except:
100 pass
101
102 def _create(self):
Just van Rossumfc93e172004-10-26 11:02:08 +0000103 pl = dict(
Jack Jansen838e76a2003-02-25 12:58:58 +0000104 aString="Doodah",
Just van Rossumfc93e172004-10-26 11:02:08 +0000105 aList=["A", "B", 12, 32.5, [1, 2, 3]],
106 aFloat = 0.5,
Jack Jansen838e76a2003-02-25 12:58:58 +0000107 anInt = 728,
Just van Rossumfc93e172004-10-26 11:02:08 +0000108 aDict=dict(
109 anotherString="<hello & 'hi' there!>",
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000110 aUnicodeValue='M\xe4ssig, Ma\xdf',
Jack Jansen838e76a2003-02-25 12:58:58 +0000111 aTrueValue=True,
112 aFalseValue=False,
Just van Rossumfc93e172004-10-26 11:02:08 +0000113 deeperDict=dict(a=17, b=32.5, c=[1, 2, "text"]),
Jack Jansen838e76a2003-02-25 12:58:58 +0000114 ),
Guido van Rossumcd869d82007-08-07 14:26:40 +0000115 someData = plistlib.Data(b"<binary gunk>"),
116 someMoreData = plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10),
117 nestedData = [plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10)],
Just van Rossumfc93e172004-10-26 11:02:08 +0000118 aDate = datetime.datetime(2004, 10, 26, 10, 33, 33),
Hynek Schlawack52209d32012-05-29 12:04:54 +0200119 anEmptyDict = dict(),
120 anEmptyList = list()
Jack Jansen838e76a2003-02-25 12:58:58 +0000121 )
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000122 pl['\xc5benraa'] = "That was a unicode key."
Jack Jansen838e76a2003-02-25 12:58:58 +0000123 return pl
Tim Peters669454e2003-03-07 17:30:48 +0000124
Jack Jansen838e76a2003-02-25 12:58:58 +0000125 def test_create(self):
126 pl = self._create()
127 self.assertEqual(pl["aString"], "Doodah")
128 self.assertEqual(pl["aDict"]["aFalseValue"], False)
129
130 def test_io(self):
131 pl = self._create()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000132 plistlib.writePlist(pl, support.TESTFN)
133 pl2 = plistlib.readPlist(support.TESTFN)
Tim Peters669454e2003-03-07 17:30:48 +0000134 self.assertEqual(dict(pl), dict(pl2))
Jack Jansen838e76a2003-02-25 12:58:58 +0000135
Guido van Rossumcd869d82007-08-07 14:26:40 +0000136 def test_bytes(self):
Just van Rossumfc93e172004-10-26 11:02:08 +0000137 pl = self._create()
Guido van Rossumcd869d82007-08-07 14:26:40 +0000138 data = plistlib.writePlistToBytes(pl)
139 pl2 = plistlib.readPlistFromBytes(data)
Just van Rossumfc93e172004-10-26 11:02:08 +0000140 self.assertEqual(dict(pl), dict(pl2))
Guido van Rossumcd869d82007-08-07 14:26:40 +0000141 data2 = plistlib.writePlistToBytes(pl2)
Just van Rossumfc93e172004-10-26 11:02:08 +0000142 self.assertEqual(data, data2)
143
144 def test_appleformatting(self):
Guido van Rossumcd869d82007-08-07 14:26:40 +0000145 pl = plistlib.readPlistFromBytes(TESTDATA)
146 data = plistlib.writePlistToBytes(pl)
Just van Rossumfc93e172004-10-26 11:02:08 +0000147 self.assertEqual(data, TESTDATA,
148 "generated data was not identical to Apple's output")
149
150 def test_appleformattingfromliteral(self):
151 pl = self._create()
Guido van Rossumcd869d82007-08-07 14:26:40 +0000152 pl2 = plistlib.readPlistFromBytes(TESTDATA)
Just van Rossumfc93e172004-10-26 11:02:08 +0000153 self.assertEqual(dict(pl), dict(pl2),
154 "generated data was not identical to Apple's output")
155
Guido van Rossumcd869d82007-08-07 14:26:40 +0000156 def test_bytesio(self):
157 from io import BytesIO
158 b = BytesIO()
Just van Rossumbcc58e82003-07-01 20:22:30 +0000159 pl = self._create()
Guido van Rossumcd869d82007-08-07 14:26:40 +0000160 plistlib.writePlist(pl, b)
161 pl2 = plistlib.readPlist(BytesIO(b.getvalue()))
Just van Rossumbcc58e82003-07-01 20:22:30 +0000162 self.assertEqual(dict(pl), dict(pl2))
163
Just van Rossum48ecacc2004-11-12 08:34:32 +0000164 def test_controlcharacters(self):
Just van Rossum2dae7642004-11-12 09:36:12 +0000165 for i in range(128):
166 c = chr(i)
167 testString = "string containing %s" % c
168 if i >= 32 or c in "\r\n\t":
169 # \r, \n and \t are the only legal control chars in XML
Guido van Rossumcd869d82007-08-07 14:26:40 +0000170 plistlib.writePlistToBytes(testString)
Just van Rossum2dae7642004-11-12 09:36:12 +0000171 else:
172 self.assertRaises(ValueError,
Guido van Rossumcd869d82007-08-07 14:26:40 +0000173 plistlib.writePlistToBytes,
Just van Rossum2dae7642004-11-12 09:36:12 +0000174 testString)
Just van Rossum48ecacc2004-11-12 08:34:32 +0000175
176 def test_nondictroot(self):
177 test1 = "abc"
178 test2 = [1, 2, 3, "abc"]
Guido van Rossumcd869d82007-08-07 14:26:40 +0000179 result1 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test1))
180 result2 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test2))
Just van Rossum48ecacc2004-11-12 08:34:32 +0000181 self.assertEqual(test1, result1)
182 self.assertEqual(test2, result2)
Jack Jansen838e76a2003-02-25 12:58:58 +0000183
Ned Deilyb8e59f72011-05-28 02:19:19 -0700184 def test_invalidarray(self):
185 for i in ["<key>key inside an array</key>",
186 "<key>key inside an array2</key><real>3</real>",
187 "<true/><key>key inside an array3</key>"]:
188 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
189 ("<plist><array>%s</array></plist>"%i).encode())
190
191 def test_invaliddict(self):
192 for i in ["<key><true/>k</key><string>compound key</string>",
193 "<key>single key</key>",
194 "<string>missing key</string>",
195 "<key>k1</key><string>v1</string><real>5.3</real>"
196 "<key>k1</key><key>k2</key><string>double key</string>"]:
197 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
198 ("<plist><dict>%s</dict></plist>"%i).encode())
199 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
200 ("<plist><array><dict>%s</dict></array></plist>"%i).encode())
201
202 def test_invalidinteger(self):
203 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
204 b"<plist><integer>not integer</integer></plist>")
205
206 def test_invalidreal(self):
207 self.assertRaises(ValueError, plistlib.readPlistFromBytes,
208 b"<plist><integer>not real</integer></plist>")
209
Jack Jansen838e76a2003-02-25 12:58:58 +0000210
211def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000212 support.run_unittest(TestPlistlib)
Jack Jansen838e76a2003-02-25 12:58:58 +0000213
214
215if __name__ == '__main__':
216 test_main()