| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  | # Copyright (C) 2003 Python Software Foundation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | import plistlib | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  | import datetime | 
					
						
							| 
									
										
										
										
											2008-05-20 21:35:26 +00:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # This test data was generated through Cocoa's NSDictionary class | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  | TESTDATA = b"""<?xml version="1.0" encoding="UTF-8"?>
 | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \ | 
					
						
							|  |  |  | "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | 
					
						
							|  |  |  | <plist version="1.0"> | 
					
						
							|  |  |  | <dict> | 
					
						
							|  |  |  |         <key>aDate</key> | 
					
						
							|  |  |  |         <date>2004-10-26T10:33:33Z</date> | 
					
						
							|  |  |  |         <key>aDict</key> | 
					
						
							|  |  |  |         <dict> | 
					
						
							|  |  |  |                 <key>aFalseValue</key> | 
					
						
							|  |  |  |                 <false/> | 
					
						
							|  |  |  |                 <key>aTrueValue</key> | 
					
						
							|  |  |  |                 <true/> | 
					
						
							|  |  |  |                 <key>aUnicodeValue</key> | 
					
						
							|  |  |  |                 <string>M\xc3\xa4ssig, Ma\xc3\x9f</string> | 
					
						
							|  |  |  |                 <key>anotherString</key> | 
					
						
							|  |  |  |                 <string><hello & 'hi' there!></string> | 
					
						
							|  |  |  |                 <key>deeperDict</key> | 
					
						
							|  |  |  |                 <dict> | 
					
						
							|  |  |  |                         <key>a</key> | 
					
						
							|  |  |  |                         <integer>17</integer> | 
					
						
							|  |  |  |                         <key>b</key> | 
					
						
							|  |  |  |                         <real>32.5</real> | 
					
						
							|  |  |  |                         <key>c</key> | 
					
						
							|  |  |  |                         <array> | 
					
						
							|  |  |  |                                 <integer>1</integer> | 
					
						
							|  |  |  |                                 <integer>2</integer> | 
					
						
							|  |  |  |                                 <string>text</string> | 
					
						
							|  |  |  |                         </array> | 
					
						
							|  |  |  |                 </dict> | 
					
						
							|  |  |  |         </dict> | 
					
						
							|  |  |  |         <key>aFloat</key> | 
					
						
							|  |  |  |         <real>0.5</real> | 
					
						
							|  |  |  |         <key>aList</key> | 
					
						
							|  |  |  |         <array> | 
					
						
							|  |  |  |                 <string>A</string> | 
					
						
							|  |  |  |                 <string>B</string> | 
					
						
							|  |  |  |                 <integer>12</integer> | 
					
						
							|  |  |  |                 <real>32.5</real> | 
					
						
							|  |  |  |                 <array> | 
					
						
							|  |  |  |                         <integer>1</integer> | 
					
						
							|  |  |  |                         <integer>2</integer> | 
					
						
							|  |  |  |                         <integer>3</integer> | 
					
						
							|  |  |  |                 </array> | 
					
						
							|  |  |  |         </array> | 
					
						
							|  |  |  |         <key>aString</key> | 
					
						
							|  |  |  |         <string>Doodah</string> | 
					
						
							|  |  |  |         <key>anInt</key> | 
					
						
							|  |  |  |         <integer>728</integer> | 
					
						
							|  |  |  |         <key>nestedData</key> | 
					
						
							|  |  |  |         <array> | 
					
						
							|  |  |  |                 <data> | 
					
						
							|  |  |  |                 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5r | 
					
						
							|  |  |  |                 PgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5 | 
					
						
							|  |  |  |                 IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBi | 
					
						
							|  |  |  |                 aW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3Rz | 
					
						
							|  |  |  |                 IG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQID | 
					
						
							|  |  |  |                 PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAw== | 
					
						
							|  |  |  |                 </data> | 
					
						
							|  |  |  |         </array> | 
					
						
							|  |  |  |         <key>someData</key> | 
					
						
							|  |  |  |         <data> | 
					
						
							|  |  |  |         PGJpbmFyeSBndW5rPg== | 
					
						
							|  |  |  |         </data> | 
					
						
							|  |  |  |         <key>someMoreData</key> | 
					
						
							|  |  |  |         <data> | 
					
						
							|  |  |  |         PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8 | 
					
						
							|  |  |  |         bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxs | 
					
						
							|  |  |  |         b3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxv | 
					
						
							|  |  |  |         dHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90 | 
					
						
							|  |  |  |         cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAw== | 
					
						
							|  |  |  |         </data> | 
					
						
							|  |  |  |         <key>\xc3\x85benraa</key> | 
					
						
							|  |  |  |         <string>That was a unicode key.</string> | 
					
						
							|  |  |  | </dict> | 
					
						
							|  |  |  | </plist> | 
					
						
							| 
									
										
										
										
											2007-08-30 06:37:08 +00:00
										 |  |  | """.replace(b" " * 8, b"\t")  # Apple as well as plistlib.py output hard tabs
 | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  | class TestPlistlib(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tearDown(self): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2008-05-20 21:35:26 +00:00
										 |  |  |             os.unlink(support.TESTFN) | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |         except: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _create(self): | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |         pl = dict( | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |             aString="Doodah", | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |             aList=["A", "B", 12, 32.5, [1, 2, 3]], | 
					
						
							|  |  |  |             aFloat = 0.5, | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |             anInt = 728, | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |             aDict=dict( | 
					
						
							|  |  |  |                 anotherString="<hello & 'hi' there!>", | 
					
						
							| 
									
										
										
										
											2007-05-02 19:09:54 +00:00
										 |  |  |                 aUnicodeValue='M\xe4ssig, Ma\xdf', | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |                 aTrueValue=True, | 
					
						
							|  |  |  |                 aFalseValue=False, | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |                 deeperDict=dict(a=17, b=32.5, c=[1, 2, "text"]), | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |             ), | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |             someData = plistlib.Data(b"<binary gunk>"), | 
					
						
							|  |  |  |             someMoreData = plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10), | 
					
						
							|  |  |  |             nestedData = [plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10)], | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |             aDate = datetime.datetime(2004, 10, 26, 10, 33, 33), | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2007-05-02 19:09:54 +00:00
										 |  |  |         pl['\xc5benraa'] = "That was a unicode key." | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |         return pl | 
					
						
							| 
									
										
										
										
											2003-03-07 17:30:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  |     def test_create(self): | 
					
						
							|  |  |  |         pl = self._create() | 
					
						
							|  |  |  |         self.assertEqual(pl["aString"], "Doodah") | 
					
						
							|  |  |  |         self.assertEqual(pl["aDict"]["aFalseValue"], False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_io(self): | 
					
						
							|  |  |  |         pl = self._create() | 
					
						
							| 
									
										
										
										
											2008-05-20 21:35:26 +00:00
										 |  |  |         plistlib.writePlist(pl, support.TESTFN) | 
					
						
							|  |  |  |         pl2 = plistlib.readPlist(support.TESTFN) | 
					
						
							| 
									
										
										
										
											2003-03-07 17:30:48 +00:00
										 |  |  |         self.assertEqual(dict(pl), dict(pl2)) | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |     def test_bytes(self): | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |         pl = self._create() | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |         data = plistlib.writePlistToBytes(pl) | 
					
						
							|  |  |  |         pl2 = plistlib.readPlistFromBytes(data) | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |         self.assertEqual(dict(pl), dict(pl2)) | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |         data2 = plistlib.writePlistToBytes(pl2) | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |         self.assertEqual(data, data2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_appleformatting(self): | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |         pl = plistlib.readPlistFromBytes(TESTDATA) | 
					
						
							|  |  |  |         data = plistlib.writePlistToBytes(pl) | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |         self.assertEqual(data, TESTDATA, | 
					
						
							|  |  |  |                          "generated data was not identical to Apple's output") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_appleformattingfromliteral(self): | 
					
						
							|  |  |  |         pl = self._create() | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |         pl2 = plistlib.readPlistFromBytes(TESTDATA) | 
					
						
							| 
									
										
										
										
											2004-10-26 11:02:08 +00:00
										 |  |  |         self.assertEqual(dict(pl), dict(pl2), | 
					
						
							|  |  |  |                          "generated data was not identical to Apple's output") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |     def test_bytesio(self): | 
					
						
							|  |  |  |         from io import BytesIO | 
					
						
							|  |  |  |         b = BytesIO() | 
					
						
							| 
									
										
										
										
											2003-07-01 20:22:30 +00:00
										 |  |  |         pl = self._create() | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |         plistlib.writePlist(pl, b) | 
					
						
							|  |  |  |         pl2 = plistlib.readPlist(BytesIO(b.getvalue())) | 
					
						
							| 
									
										
										
										
											2003-07-01 20:22:30 +00:00
										 |  |  |         self.assertEqual(dict(pl), dict(pl2)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-12 08:34:32 +00:00
										 |  |  |     def test_controlcharacters(self): | 
					
						
							| 
									
										
										
										
											2004-11-12 09:36:12 +00:00
										 |  |  |         for i in range(128): | 
					
						
							|  |  |  |             c = chr(i) | 
					
						
							|  |  |  |             testString = "string containing %s" % c | 
					
						
							|  |  |  |             if i >= 32 or c in "\r\n\t": | 
					
						
							|  |  |  |                 # \r, \n and \t are the only legal control chars in XML | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |                 plistlib.writePlistToBytes(testString) | 
					
						
							| 
									
										
										
										
											2004-11-12 09:36:12 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 self.assertRaises(ValueError, | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |                                   plistlib.writePlistToBytes, | 
					
						
							| 
									
										
										
										
											2004-11-12 09:36:12 +00:00
										 |  |  |                                   testString) | 
					
						
							| 
									
										
										
										
											2004-11-12 08:34:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_nondictroot(self): | 
					
						
							|  |  |  |         test1 = "abc" | 
					
						
							|  |  |  |         test2 = [1, 2, 3, "abc"] | 
					
						
							| 
									
										
										
										
											2007-08-07 14:26:40 +00:00
										 |  |  |         result1 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test1)) | 
					
						
							|  |  |  |         result2 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test2)) | 
					
						
							| 
									
										
										
										
											2004-11-12 08:34:32 +00:00
										 |  |  |         self.assertEqual(test1, result1) | 
					
						
							|  |  |  |         self.assertEqual(test2, result2) | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-28 02:19:19 -07:00
										 |  |  |     def test_invalidarray(self): | 
					
						
							|  |  |  |         for i in ["<key>key inside an array</key>", | 
					
						
							|  |  |  |                   "<key>key inside an array2</key><real>3</real>", | 
					
						
							|  |  |  |                   "<true/><key>key inside an array3</key>"]: | 
					
						
							|  |  |  |             self.assertRaises(ValueError, plistlib.readPlistFromBytes, | 
					
						
							|  |  |  |                               ("<plist><array>%s</array></plist>"%i).encode()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_invaliddict(self): | 
					
						
							|  |  |  |         for i in ["<key><true/>k</key><string>compound key</string>", | 
					
						
							|  |  |  |                   "<key>single key</key>", | 
					
						
							|  |  |  |                   "<string>missing key</string>", | 
					
						
							|  |  |  |                   "<key>k1</key><string>v1</string><real>5.3</real>" | 
					
						
							|  |  |  |                   "<key>k1</key><key>k2</key><string>double key</string>"]: | 
					
						
							|  |  |  |             self.assertRaises(ValueError, plistlib.readPlistFromBytes, | 
					
						
							|  |  |  |                               ("<plist><dict>%s</dict></plist>"%i).encode()) | 
					
						
							|  |  |  |             self.assertRaises(ValueError, plistlib.readPlistFromBytes, | 
					
						
							|  |  |  |                               ("<plist><array><dict>%s</dict></array></plist>"%i).encode()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_invalidinteger(self): | 
					
						
							|  |  |  |         self.assertRaises(ValueError, plistlib.readPlistFromBytes, | 
					
						
							|  |  |  |                           b"<plist><integer>not integer</integer></plist>") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_invalidreal(self): | 
					
						
							|  |  |  |         self.assertRaises(ValueError, plistlib.readPlistFromBytes, | 
					
						
							|  |  |  |                           b"<plist><integer>not real</integer></plist>") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def test_main(): | 
					
						
							| 
									
										
										
										
											2008-05-20 21:35:26 +00:00
										 |  |  |     support.run_unittest(TestPlistlib) | 
					
						
							| 
									
										
										
										
											2003-02-25 12:58:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     test_main() |