"""
Test cases for ldaptor.protocols.ldap.autofill.sambaAccount module.
"""
from twisted.trial import unittest

from ldaptor.protocols.ldap import ldapsyntax
from ldaptor.protocols.ldap.autofill import sambaAccount, sambaSamAccount
from ldaptor import testutil


class LDAPAutoFill_sambaAccount(unittest.TestCase):
    def testMustHaveObjectClass(self):
        """Test that Autofill_samba fails unless object is a sambaAccount."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["something", "other"],
            },
        )
        autoFiller = sambaAccount.Autofill_samba()
        d = o.addAutofiller(autoFiller)

        def eb(val):
            client.assertNothingSent()
            val.trap(sambaAccount.ObjectMissingObjectClassException)

        d.addCallbacks(testutil.mustRaise, eb)
        return d

    def testDefaultSetting(self):
        """Test that fields get their default values."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaAccount", "other"],
            },
        )
        d = o.addAutofiller(sambaAccount.Autofill_samba())

        def cb(dummy):
            client.assertNothingSent()

            self.failUnless("acctFlags" in o)
            self.failUnlessEqual(o["acctFlags"], ["[UX         ]"])

            self.failUnless("pwdLastSet" in o)
            self.failUnlessEqual(o["pwdLastSet"], ["0"])
            self.failUnless("logonTime" in o)
            self.failUnlessEqual(o["logonTime"], ["0"])
            self.failUnless("logoffTime" in o)
            self.failUnlessEqual(o["logoffTime"], ["0"])
            self.failUnless("pwdCanChange" in o)
            self.failUnlessEqual(o["pwdCanChange"], ["0"])
            self.failUnless("pwdMustChange" in o)
            self.failUnlessEqual(o["pwdMustChange"], ["0"])

        d.addCallback(cb)
        return d

    def testRid(self):
        """Test that rid field is updated based on uidNumber."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaAccount", "other"],
            },
        )
        d = o.addAutofiller(sambaAccount.Autofill_samba())

        def cb(dummy):
            client.assertNothingSent()

            o["uidNumber"] = ["1000"]
            self.failUnless("rid" in o)
            self.failUnlessEqual(o["rid"], [str(2 * 1000 + 1000)])
            o["uidNumber"] = ["1001"]
            self.failUnlessEqual(o["rid"], [str(2 * 1001 + 1000)])
            o["uidNumber"] = ["1002"]
            self.failUnlessEqual(o["rid"], [str(2 * 1002 + 1000)])
            o["uidNumber"] = ["2000"]
            self.failUnlessEqual(o["rid"], [str(2 * 2000 + 1000)])
            o["uidNumber"] = ["3000"]
            self.failUnlessEqual(o["rid"], [str(2 * 3000 + 1000)])
            o["uidNumber"] = ["0"]
            self.failUnlessEqual(o["rid"], [str(2 * 0 + 1000)])
            o["uidNumber"] = ["16000"]
            self.failUnlessEqual(o["rid"], [str(2 * 16000 + 1000)])

        d.addCallback(cb)
        return d

    def testPrimaryGroupId(self):
        """Test that primaryGroupID field is updated based on gidNumber."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaAccount", "other"],
            },
        )
        d = o.addAutofiller(sambaAccount.Autofill_samba())

        def cb(dummy):
            client.assertNothingSent()

            o["gidNumber"] = ["1000"]
            self.failUnless("primaryGroupID" in o)
            self.failUnlessEqual(o["primaryGroupID"], [str(2 * 1000 + 1001)])
            o["gidNumber"] = ["1001"]
            self.failUnlessEqual(o["primaryGroupID"], [str(2 * 1001 + 1001)])
            o["gidNumber"] = ["1002"]
            self.failUnlessEqual(o["primaryGroupID"], [str(2 * 1002 + 1001)])
            o["gidNumber"] = ["2000"]
            self.failUnlessEqual(o["primaryGroupID"], [str(2 * 2000 + 1001)])
            o["gidNumber"] = ["3000"]
            self.failUnlessEqual(o["primaryGroupID"], [str(2 * 3000 + 1001)])
            o["gidNumber"] = ["0"]
            self.failUnlessEqual(o["primaryGroupID"], [str(2 * 0 + 1001)])
            o["gidNumber"] = ["16000"]
            self.failUnlessEqual(o["primaryGroupID"], [str(2 * 16000 + 1001)])

        d.addCallback(cb)
        return d


class LDAPAutoFill_sambaSamAccount(unittest.TestCase):
    def testMustHaveObjectClass(self):
        """Test that Autofill_samba fails unless object is a sambaSamAccount."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["something", "other"],
            },
        )
        autoFiller = sambaSamAccount.Autofill_samba(domainSID="foo")
        d = o.addAutofiller(autoFiller)

        def eb(val):
            client.assertNothingSent()
            val.trap(sambaSamAccount.ObjectMissingObjectClassException)

        d.addCallbacks(testutil.mustRaise, eb)
        return d

    def testDefaultSetting(self):
        """Test that fields get their default values."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaSamAccount", "other"],
            },
        )
        d = o.addAutofiller(sambaSamAccount.Autofill_samba(domainSID="foo"))

        def cb(dummy):
            client.assertNothingSent()

            self.failUnlessEqual(
                set(o.keys()),
                {
                    "objectClass",
                    "sambaAcctFlags",
                    "sambaLogoffTime",
                    "sambaLogonTime",
                    "sambaPwdCanChange",
                    "sambaPwdLastSet",
                    "sambaPwdMustChange",
                },
            )

            self.failUnlessEqual(o["sambaAcctFlags"], ["[UX         ]"])
            self.failUnlessEqual(o["sambaPwdLastSet"], ["1"])
            self.failUnlessEqual(o["sambaLogonTime"], ["0"])
            self.failUnlessEqual(o["sambaLogoffTime"], ["0"])
            self.failUnlessEqual(o["sambaPwdCanChange"], ["0"])
            self.failUnlessEqual(o["sambaPwdMustChange"], ["0"])

        d.addCallback(cb)
        return d

    def testDefaultSetting_fixedPrimaryGroupSID(self):
        """Test that fields get their default values."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaSamAccount", "other"],
            },
        )
        d = o.addAutofiller(
            sambaSamAccount.Autofill_samba(
                domainSID="foo", fixedPrimaryGroupSID=4131312
            )
        )

        def cb(dummy):
            client.assertNothingSent()

            self.failUnlessEqual(
                set(o.keys()),
                {
                    "objectClass",
                    "sambaAcctFlags",
                    "sambaLogoffTime",
                    "sambaLogonTime",
                    "sambaPwdCanChange",
                    "sambaPwdLastSet",
                    "sambaPwdMustChange",
                    "sambaPrimaryGroupSID",
                },
            )

            self.failUnlessEqual(o["sambaPrimaryGroupSID"], ["foo-4131312"])
            self.failUnlessEqual(o["sambaAcctFlags"], ["[UX         ]"])
            self.failUnlessEqual(o["sambaPwdLastSet"], ["1"])
            self.failUnlessEqual(o["sambaLogonTime"], ["0"])
            self.failUnlessEqual(o["sambaLogoffTime"], ["0"])
            self.failUnlessEqual(o["sambaPwdCanChange"], ["0"])
            self.failUnlessEqual(o["sambaPwdMustChange"], ["0"])

        d.addCallback(cb)
        return d

    def testSambaSID(self):
        """Test that sambaSID field is updated based on uidNumber."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaSamAccount", "other"],
            },
        )
        d = o.addAutofiller(sambaSamAccount.Autofill_samba(domainSID="foo"))

        def cb(dummy):
            client.assertNothingSent()

            o["uidNumber"] = ["1000"]
            self.failUnless("sambaSID" in o)
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 1000 + 1000)])
            o["uidNumber"] = ["1001"]
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 1001 + 1000)])
            o["uidNumber"] = ["1002"]
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 1002 + 1000)])
            o["uidNumber"] = ["2000"]
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 2000 + 1000)])
            o["uidNumber"] = ["3000"]
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 3000 + 1000)])
            o["uidNumber"] = ["0"]
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 0 + 1000)])
            o["uidNumber"] = ["16000"]
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 16000 + 1000)])

        d.addCallback(cb)
        return d

    def testSambaSID_preExisting(self):
        """Test that sambaSID field is updated based on uidNumber."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaSamAccount", "other"],
                "uidNumber": ["1000"],
            },
        )
        d = o.addAutofiller(sambaSamAccount.Autofill_samba(domainSID="foo"))

        def cb(dummy):
            client.assertNothingSent()

            self.failUnless("sambaSID" in o)
            self.failUnlessEqual(o["sambaSID"], ["foo-%s" % (2 * 1000 + 1000)])

        d.addCallback(cb)
        return d

    def testSambaPrimaryGroupSID(self):
        """Test that sambaPrimaryGroupSID field is updated based on gidNumber."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaSamAccount", "other"],
            },
        )
        d = o.addAutofiller(sambaSamAccount.Autofill_samba(domainSID="foo"))

        def cb(dummy):
            client.assertNothingSent()

            o["gidNumber"] = ["1000"]
            self.failUnless("sambaPrimaryGroupSID" in o)
            self.failUnlessEqual(
                o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 1000 + 1001)]
            )
            o["gidNumber"] = ["1001"]
            self.failUnlessEqual(
                o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 1001 + 1001)]
            )
            o["gidNumber"] = ["1002"]
            self.failUnlessEqual(
                o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 1002 + 1001)]
            )
            o["gidNumber"] = ["2000"]
            self.failUnlessEqual(
                o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 2000 + 1001)]
            )
            o["gidNumber"] = ["3000"]
            self.failUnlessEqual(
                o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 3000 + 1001)]
            )
            o["gidNumber"] = ["0"]
            self.failUnlessEqual(o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 0 + 1001)])
            o["gidNumber"] = ["16000"]
            self.failUnlessEqual(
                o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 16000 + 1001)]
            )

        d.addCallback(cb)
        return d

    def testSambaPrimaryGroupSID_preExisting(self):
        """Test that sambaPrimaryGroupSID field is updated based on gidNumber."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaSamAccount", "other"],
                "gidNumber": ["1000"],
            },
        )
        d = o.addAutofiller(sambaSamAccount.Autofill_samba(domainSID="foo"))

        def cb(dummy):
            client.assertNothingSent()

            self.failUnless("sambaPrimaryGroupSID" in o)
            self.failUnlessEqual(
                o["sambaPrimaryGroupSID"], ["foo-%s" % (2 * 1000 + 1001)]
            )

        d.addCallback(cb)
        return d

    def testSambaPrimaryGroupSID_notUpdatedWhenFixed(self):
        """Test that sambaPrimaryGroupSID field is updated based on gidNumber."""
        client = testutil.LDAPClientTestDriver()
        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["sambaSamAccount", "other"],
            },
        )
        d = o.addAutofiller(
            sambaSamAccount.Autofill_samba(domainSID="foo", fixedPrimaryGroupSID=4242)
        )

        def cb(dummy):
            client.assertNothingSent()

            self.failUnless("sambaPrimaryGroupSID" in o)
            self.failUnlessEqual(o["sambaPrimaryGroupSID"], ["foo-4242"])
            o["gidNumber"] = ["1000"]
            self.failUnless("sambaPrimaryGroupSID" in o)
            self.failUnlessEqual(o["sambaPrimaryGroupSID"], ["foo-4242"])

        d.addCallback(cb)
        return d
