"""
Test cases for ldaptor.protocols.ldap.autofill.posixAccount module.
"""

from twisted.trial import unittest
from ldaptor.protocols.ldap import ldapsyntax, autofill
from ldaptor.protocols import pureldap
from ldaptor.protocols.ldap.autofill import posixAccount
from ldaptor.testutil import LDAPClientTestDriver


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

        d = o.addAutofiller(autoFiller)

        failure = self.failureResultOf(d)
        self.assertIsInstance(failure.value, autofill.ObjectMissingObjectClassException)
        client.assertNothingSent()

    def testDefaultSetting(self):
        """Test that fields get their default values."""

        client = LDAPClientTestDriver(
            # uid==1000 -> free
            [
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1000 -> taken
            [
                pureldap.LDAPSearchResultEntry(
                    objectName="",
                    attributes=[("objectClass", ("foo", "posixAccount", "bar"))],
                ),
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1500 -> free
            [
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1250 -> free
            [
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1125 -> free
            [
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1062 -> free
            [
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1031 -> free
            [
                pureldap.LDAPSearchResultEntry(
                    objectName="",
                    attributes=[("objectClass", ("foo", "posixAccount", "bar"))],
                ),
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1046 -> free
            [
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1038 -> taken
            [
                pureldap.LDAPSearchResultEntry(
                    objectName="",
                    attributes=[("objectClass", ("foo", "posixAccount", "bar"))],
                ),
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1042 -> free
            [
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1040 -> taken
            [
                pureldap.LDAPSearchResultEntry(
                    objectName="",
                    attributes=[("objectClass", ("foo", "posixAccount", "bar"))],
                ),
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
            # gid==1041 -> taken
            [
                pureldap.LDAPSearchResultEntry(
                    objectName="",
                    attributes=[("objectClass", ("foo", "posixAccount", "bar"))],
                ),
                pureldap.LDAPSearchResultDone(
                    resultCode=0, matchedDN="", errorMessage=""
                ),
            ],
        )

        o = ldapsyntax.LDAPEntryWithAutoFill(
            client=client,
            dn="cn=foo,dc=example,dc=com",
            attributes={
                "objectClass": ["posixAccount", "other"],
            },
        )

        d = o.addAutofiller(posixAccount.Autofill_posix(baseDN="dc=example,dc=com"))
        d.addCallback(self._cb_testDefaultSetting, client, o)
        return d

    def _cb_testDefaultSetting(self, val, client, o):
        client.assertSent(
            *[
                pureldap.LDAPSearchRequest(
                    baseObject="dc=example,dc=com",
                    scope=2,
                    derefAliases=0,
                    sizeLimit=1,
                    timeLimit=0,
                    typesOnly=0,
                    filter=pureldap.LDAPFilter_equalityMatch(
                        attributeDesc=pureldap.LDAPAttributeDescription(
                            value="uidNumber"
                        ),
                        assertionValue=pureldap.LDAPAssertionValue(value="1000"),
                    ),
                    attributes=(),
                ),
            ]
            + [
                pureldap.LDAPSearchRequest(
                    baseObject="dc=example,dc=com",
                    scope=2,
                    derefAliases=0,
                    sizeLimit=1,
                    timeLimit=0,
                    typesOnly=0,
                    filter=pureldap.LDAPFilter_equalityMatch(
                        attributeDesc=pureldap.LDAPAttributeDescription(
                            value="gidNumber"
                        ),
                        assertionValue=pureldap.LDAPAssertionValue(value=str(x)),
                    ),
                    attributes=(),
                )
                for x in (
                    1000,
                    1500,
                    1250,
                    1125,
                    1062,
                    1031,
                    1046,
                    1038,
                    1042,
                    1040,
                    1041,
                )
            ]
        )

        self.failUnless("loginShell" in o)
        self.failUnlessEqual(o["loginShell"], ["/bin/sh"])

        self.failUnless("uidNumber" in o)
        self.failUnlessEqual(o["uidNumber"], ["1000"])
        self.failUnless("gidNumber" in o)
        self.failUnlessEqual(o["gidNumber"], ["1042"])
