#!/usr/bin/python
# encoding: utf-8
#
# dirty ldap2 testing module, working on something shinier...


import sys
from os import path
parent = path.dirname(path.dirname(path.abspath(__file__)))
sys.path.append(parent)

import ldap as _ldap

from ipalib import api
from ipalib import errors

# LDAP settings
BIND_DN = u'cn=directory manager'
BIND_PW = u'blablabla'

# testing environment setup
api.bootstrap(
    basedn=u'dc=englab,dc=brq,dc=redhat,dc=com',
    realm=u'ENGLAB.BRQ.REDHAT.COM',
    in_server=True,
    debug=True,
    in_tree=True,
)
api.finalize()
ldap2 = api.Backend.ldap2

# testing entry
entry_attrs = {
    'uid': u'pzuna',
    'givenname': u'Pavel',
    'sn': u'Zůna',
    'cn': u'Pavel Zůna',
    'gecos': u'pzuna',
    'krbprincipalname': u'pzuna@%s' % api.env.realm,
    # random numbers, we don't care for testing purposes
    'uidnumber': 1034,
    'gidnumber': 2240
}

def wrap_assert(val, expected):
    assert val == expected, '%r != %r' % (val, expected)
    assert type(val) == type(expected), '%r != %r' % (type(val),
            type(expected))


api.log.info('**** Testing ldap2 entry encoding/decoding ****')
entry_attrs_copy = dict(entry_attrs)
ldap2._encode_entry_attrs(entry_attrs_copy)
wrap_assert(entry_attrs_copy[u'sn'], entry_attrs[u'sn'].encode('utf-8'))
wrap_assert(entry_attrs_copy[u'uidnumber'], str(entry_attrs[u'uidnumber']))
ldap2._decode_entry_attrs(entry_attrs_copy)
wrap_assert(entry_attrs_copy, entry_attrs)


api.log.info('**** Testing ldap2.create_connection() ****')
ldap2.connect(bind_dn=BIND_DN, bind_pw=BIND_PW)


api.log.info('**** Testing ldap2.normalize_dn() ****')
dn = ldap2.normalize_dn(u'CN=NAME')
dn_result = u'cn=name,%s' % api.env.basedn
wrap_assert(dn, dn_result)


api.log.info('**** Testing ldap2.get_container_rdn() ****')
container_rdn = ldap2.get_container_rdn(u'accounts')
wrap_assert(container_rdn, api.env.container_accounts)


api.log.info('**** Testing ldap2.make_rdn_from_attr() ****')
rdn = ldap2.make_rdn_from_attr(u'uid', entry_attrs[u'uid'])
rdn_result = u'uid=%s' % entry_attrs[u'uid']
wrap_assert(rdn, rdn_result)


api.log.info('**** Testing ldap2.make_dn_from_rdn() ****')
dn = ldap2.make_dn_from_rdn(rdn, container_rdn)
dn_result = u'uid=pzuna,%s,%s' % (api.env.container_accounts, api.env.basedn)
wrap_assert(dn, dn_result)


api.log.info('**** Testing ldap2.make_dn() ****')
dn_result = dn
dn = ldap2.make_dn(entry_attrs, u'uid', container_rdn)
wrap_assert(dn, dn_result)


api.log.info('**** Testing ldap2.get_ipa_config() ****')
config = ldap2.get_ipa_config()
config_attrs = config[1]


# fill in some other attributes from ipaconfig
entry_attrs['objectClass'] = config_attrs[u'ipaUserObjectClasses'] 
entry_attrs['homedirectory'] = config_attrs[u'ipaHomesRootDir']
entry_attrs['loginshell'] = config_attrs[u'ipaDefaultLoginShell']

# try to delete testing entry, in case it already exists
try:
    ldap2.conn.delete_s(dn)
except _ldap.LDAPError:
    pass
dn2 = dn.replace(u'pzuna', u'pzuna2')
try:
    ldap2.conn.delete_s(dn2)
except _ldap.LDAPError:
    pass


api.log.info('**** Testing ldap2.add_entry() ****')
ldap2.add_entry(dn, entry_attrs)


api.log.info('**** Testing ldap2.find_entries() ****')
flt = u'(uid=pzuna)'
found_entries = ldap2.find_entries(flt, [u'sn'])
wrap_assert(len(found_entries), 1)
found_entry_dn = found_entries[0][0]
found_entry_attrs = found_entries[0][1]
wrap_assert(found_entry_dn, dn)
wrap_assert(len(found_entry_attrs), 1)
wrap_assert(u'sn' in found_entry_attrs, True)
wrap_assert(found_entry_attrs[u'sn'][0], entry_attrs[u'sn'])


api.log.info('**** Testing ldap2.make_filter() ****')
filter_attrs = [u'objectClass', u'cn', u'uid']
flt = ldap2.make_filter(entry_attrs, filter_attrs, ldap2.MATCH_ALL)
found_entries = ldap2.find_entries(flt)
wrap_assert(len(found_entries), 1)
found_entry_dn = found_entries[0][0]
wrap_assert(found_entry_dn, dn)


api.log.info('**** Testing ldap2.get_entry() ****')
found_entry = ldap2.get_entry(dn)
found_entry_attrs = found_entry[1]
wrap_assert(u'sn' in found_entry_attrs, True)
wrap_assert(found_entry_attrs[u'sn'][0], entry_attrs[u'sn'])


api.log.info('**** Testing ldap2.update_entry_rdn() ****')
rdn = ldap2.make_rdn_from_attr(u'uid', u'pzuna2')
ldap2.update_entry_rdn(dn, rdn)
dn = ldap2.make_dn_from_rdn(rdn, container_rdn)
found_entry = ldap2.get_entry(dn)


api.log.info('**** Testing ldap2.update_entry() ****')
update_entry_attrs = {'loginshell': None, 'givenname': u'Paul'}
ldap2.update_entry(dn, update_entry_attrs)
found_entry = ldap2.get_entry(dn)
found_entry_attrs = found_entry[1]
wrap_assert(u'loginShell' not in found_entry_attrs, True)
wrap_assert(len(found_entry_attrs[u'givenName']), 1)
wrap_assert(found_entry_attrs[u'givenName'][0], u'Paul')


api.log.info('**** Testing ldap2.set_entry_activity() ****')
# this tests add_entry_to_group/remove_entry_from_group as well
ldap2.deactivate_entry(dn)
try:
    ldap2.deactivate_entry(dn)
except errors.AlreadyInactiveError:
    pass
else:
    assert False, 'entry should be already inactive'
ldap2.activate_entry(dn)
try:
    ldap2.activate_entry(dn)
except errors.AlreadyActiveError:
    pass
else:
    assert False, 'entry should be already active'


api.log.info('**** Testing ldap2.delete_entry() ****')
ldap2.delete_entry(dn)


api.log.info('**** Testing ldap2.create() ****')
entry_attrs['dn'] = dn
entry = ldap2.create(**entry_attrs)
wrap_assert(u'dn' in entry, True)
wrap_assert(entry[u'sn'][0], entry_attrs[u'sn'])


api.log.info('**** Testing ldap2.retrieve() ****')
entry = ldap2.retrieve(dn, None)
wrap_assert(u'dn' in entry, True)
wrap_assert(entry[u'cn'][0], entry_attrs[u'cn'])


api.log.info('**** Testing ldap2.update() ****')
entry = ldap2.update(dn, **update_entry_attrs)
wrap_assert(u'dn' in entry, True)
wrap_assert(u'loginShell' not in entry, True)
wrap_assert(len(entry[u'givenName']), 1)
wrap_assert(entry[u'givenName'][0], u'Paul')


api.log.info('**** Testing ldap2.search() ****')
search_criteria = {'givenName': u'Paul', 'uid': u'pzuna2'}
entries = ldap2.search(**search_criteria)
entry = entries[0]
wrap_assert(u'dn' in entry, True)
wrap_assert(entry[u'cn'][0], entry_attrs[u'cn'])


api.log.info('**** Testing ldap2.delete() ****')
ldap2.delete(dn)


api.log.info('**** Testing ldap2.destroy_connection() ****')
ldap2.disconnect()



