# Copyright (C) 2003 Python Software Foundation

import unittest
import plistlib
import os
import datetime
from test import support


# This test data was generated through Cocoa's NSDictionary class
TESTDATA = b"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//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>&lt;hello &amp; 'hi' there!&gt;</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>
""".replace(b" " * 8, b"\t")  # Apple as well as plistlib.py output hard tabs


class TestPlistlib(unittest.TestCase):

    def tearDown(self):
        try:
            os.unlink(support.TESTFN)
        except:
            pass

    def _create(self):
        pl = dict(
            aString="Doodah",
            aList=["A", "B", 12, 32.5, [1, 2, 3]],
            aFloat = 0.5,
            anInt = 728,
            aDict=dict(
                anotherString="<hello & 'hi' there!>",
                aUnicodeValue='M\xe4ssig, Ma\xdf',
                aTrueValue=True,
                aFalseValue=False,
                deeperDict=dict(a=17, b=32.5, c=[1, 2, "text"]),
            ),
            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)],
            aDate = datetime.datetime(2004, 10, 26, 10, 33, 33),
        )
        pl['\xc5benraa'] = "That was a unicode key."
        return pl

    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()
        plistlib.writePlist(pl, support.TESTFN)
        pl2 = plistlib.readPlist(support.TESTFN)
        self.assertEqual(dict(pl), dict(pl2))

    def test_bytes(self):
        pl = self._create()
        data = plistlib.writePlistToBytes(pl)
        pl2 = plistlib.readPlistFromBytes(data)
        self.assertEqual(dict(pl), dict(pl2))
        data2 = plistlib.writePlistToBytes(pl2)
        self.assertEqual(data, data2)

    def test_appleformatting(self):
        pl = plistlib.readPlistFromBytes(TESTDATA)
        data = plistlib.writePlistToBytes(pl)
        self.assertEqual(data, TESTDATA,
                         "generated data was not identical to Apple's output")

    def test_appleformattingfromliteral(self):
        pl = self._create()
        pl2 = plistlib.readPlistFromBytes(TESTDATA)
        self.assertEqual(dict(pl), dict(pl2),
                         "generated data was not identical to Apple's output")

    def test_bytesio(self):
        from io import BytesIO
        b = BytesIO()
        pl = self._create()
        plistlib.writePlist(pl, b)
        pl2 = plistlib.readPlist(BytesIO(b.getvalue()))
        self.assertEqual(dict(pl), dict(pl2))

    def test_controlcharacters(self):
        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
                plistlib.writePlistToBytes(testString)
            else:
                self.assertRaises(ValueError,
                                  plistlib.writePlistToBytes,
                                  testString)

    def test_nondictroot(self):
        test1 = "abc"
        test2 = [1, 2, 3, "abc"]
        result1 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test1))
        result2 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test2))
        self.assertEqual(test1, result1)
        self.assertEqual(test2, result2)

    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>")


def test_main():
    support.run_unittest(TestPlistlib)


if __name__ == '__main__':
    test_main()
