from __future__ import print_function, unicode_literals

import unittest
from six import text_type

from fs.permissions import Permissions, make_mode


class TestPermissions(unittest.TestCase):
    def test_make_mode(self):
        self.assertEqual(make_mode(None), 0o777)
        self.assertEqual(make_mode(0o755), 0o755)
        self.assertEqual(make_mode(["u_r", "u_w", "u_x"]), 0o700)
        self.assertEqual(make_mode(Permissions(user="rwx")), 0o700)

    def test_parse(self):
        self.assertEqual(Permissions.parse("---------").mode, 0)
        self.assertEqual(Permissions.parse("rwxrw-r--").mode, 0o764)

    def test_create(self):
        self.assertEqual(Permissions.create(None).mode, 0o777)
        self.assertEqual(Permissions.create(0o755).mode, 0o755)
        self.assertEqual(Permissions.create(["u_r", "u_w", "u_x"]).mode, 0o700)
        self.assertEqual(Permissions.create(Permissions(user="rwx")).mode, 0o700)
        with self.assertRaises(ValueError):
            Permissions.create("foo")

    def test_constructor(self):
        p = Permissions(names=["foo", "bar"])
        self.assertIn("foo", p)
        self.assertIn("bar", p)
        self.assertNotIn("baz", p)

        p = Permissions(user="r", group="w", other="x")
        self.assertIn("u_r", p)
        self.assertIn("g_w", p)
        self.assertIn("o_x", p)
        self.assertNotIn("sticky", p)
        self.assertNotIn("setuid", p)
        self.assertNotIn("setguid", p)

        p = Permissions(
            user="rwx", group="rwx", other="rwx", sticky=True, setuid=True, setguid=True
        )
        self.assertIn("sticky", p)
        self.assertIn("setuid", p)
        self.assertIn("setguid", p)

        p = Permissions(mode=0o421)
        self.assertIn("u_r", p)
        self.assertIn("g_w", p)
        self.assertIn("o_x", p)
        self.assertNotIn("u_w", p)
        self.assertNotIn("g_x", p)
        self.assertNotIn("o_r", p)
        self.assertNotIn("sticky", p)
        self.assertNotIn("setuid", p)
        self.assertNotIn("setguid", p)

    def test_properties(self):
        p = Permissions()
        self.assertFalse(p.u_r)
        self.assertNotIn("u_r", p)
        p.u_r = True
        self.assertIn("u_r", p)
        self.assertTrue(p.u_r)
        p.u_r = False
        self.assertNotIn("u_r", p)
        self.assertFalse(p.u_r)

        self.assertFalse(p.u_w)
        p.add("u_w")
        self.assertTrue(p.u_w)
        p.remove("u_w")
        self.assertFalse(p.u_w)

    def test_repr(self):
        self.assertEqual(
            repr(Permissions()), "Permissions(user='', group='', other='')"
        )
        self.assertEqual(repr(Permissions(names=["foo"])), "Permissions(names=['foo'])")
        repr(Permissions(user="rwx", group="rw", other="r"))
        repr(Permissions(user="rwx", group="rw", other="r", sticky=True))
        repr(Permissions(user="rwx", group="rw", other="r", setuid=True))
        repr(Permissions(user="rwx", group="rw", other="r", setguid=True))

    def test_as_str(self):
        p = Permissions(user="rwx", group="rwx", other="rwx")
        self.assertEqual(p.as_str(), "rwxrwxrwx")
        self.assertEqual(str(p), "rwxrwxrwx")
        p = Permissions(mode=0o777, setuid=True, setguid=True, sticky=True)
        self.assertEqual(p.as_str(), "rwsrwsrwt")

    def test_mode(self):
        p = Permissions(user="rwx", group="rw", other="")
        self.assertEqual(p.mode, 0o760)

    def test_serialize(self):
        p = Permissions(names=["foo"])
        self.assertEqual(p.dump(), ["foo"])
        pp = Permissions.load(["foo"])
        self.assertIn("foo", pp)

    def test_iter(self):
        iter_p = iter(Permissions(names=["foo"]))
        self.assertEqual(list(iter_p), ["foo"])

    def test_equality(self):
        self.assertEqual(Permissions(mode=0o700), Permissions(user="rwx"))
        self.assertNotEqual(Permissions(mode=0o500), Permissions(user="rwx"))

        self.assertEqual(Permissions(mode=0o700), ["u_r", "u_w", "u_x"])

    def test_copy(self):
        p = Permissions(mode=0o700)
        p_copy = p.copy()
        self.assertIsNot(p, p_copy)
        self.assertEqual(p, p_copy)

    def test_check(self):
        p = Permissions(user="rwx")
        self.assertTrue(p.check("u_r"))
        self.assertTrue(p.check("u_r", "u_w"))
        self.assertTrue(p.check("u_r", "u_w", "u_x"))
        self.assertFalse(p.check("u_r", "g_w"))
        self.assertFalse(p.check("g_r", "g_w"))
        self.assertFalse(p.check("foo"))

    def test_mode_set(self):
        p = Permissions(user="r")
        self.assertEqual(text_type(p), "r--------")
        p.mode = 0o700
        self.assertEqual(text_type(p), "rwx------")
